前提
Unityで箱庭系ゲームを作っています。今は木や石などを複数のキャラクターが順番に採取できるようなシステムを作っているのですが、一人目が採取を終えるとほかのまだ採取していたキャラクターたちが止まってしまいます。エラーは出ていません。
実現したいこと
・複数のキャラクターが指定した採取物を順番に採取する。
・採取をそれぞれ個別に終わらせる。
該当のソースコード
CharacterAIController
キャラクター操作の大本のスクリプト
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.AI; 5using System.Linq; 6using System; 7 8public class CharacterAIController : MonoBehaviour 9{ 10 public enum State { 11 Wait, 12 Walk, 13 Mine 14 15 } 16 //navMeshAgent 17 [SerializeField] 18 protected UnityEngine.AI.NavMeshAgent navMeshAgent; 19 //State 20 protected State state; 21 //Animator 22 [SerializeField] 23 protected Animator anim; 24 //移動する位置 25 protected List<Transform> targetPositions = new List<Transform>(); 26 //次に移動する位置 27 protected int nowTargetPosition = 0; 28 //目的地 29 private Transform destination; 30 31 // Start is called before the first frame update 32 void Start() 33 { 34 35 } 36 37 // Update is called once per frame 38 void Update() 39 { 40 41 } 42 43 44 45 //Stateを変更する 46 public void SetState(State state) { 47 this.state = state; 48 if(state == State.Wait) { 49 anim.SetFloat("Walk", 0f); 50 anim.SetBool("isMining", false); 51 // elapsedTime = 0f; 52 } else if(state == State.Walk) { 53 anim.SetBool("isMining", false); 54 SetNextPosition(); 55 navMeshAgent.SetDestination(GetDestination().position); 56 } else if(state == State.Mine) { 57 anim.SetBool("isMining", true); 58 } 59 } 60 61 //Stateを参照する 62 public State GetState() { 63 return state; 64 } 65 66 //セッター 67 public void SetDestination(Transform position) { 68 destination = position; 69 } 70 //ゲッター 71 public Transform GetDestination(){ 72 return destination; 73 } 74 75 //次の場所をセットする 76 public void SetNextPosition() { 77 SetDestination(targetPositions[nowTargetPosition]); 78 if(!GetDestination().GetComponent<DestructibleObjectManager>().IsPartnerSet()) { 79 GetDestination().GetComponent<DestructibleObjectManager>().SetPartner(gameObject); 80 } else { 81 if(targetPositions.Any()) { 82 RemoveList(); 83 SetNextPosition(); 84 } 85 } 86 } 87 88 protected void RemoveList() { 89 targetPositions.Remove(GetDestination()); 90 } 91}
CharacterMiningManager
採取用の継承スクリプト
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.AI; 5using System.Linq; 6using System; 7 8public class CharacterMiningManager : CharacterAIController 9{ 10 //採取中かどうか 11 private bool isMining = false; 12 //なんかいヒットしたか 13 private int mineHitCount; 14 //経過した時間 15 private float elapsedTime; 16 //採掘にかかる時間 17 [SerializeField] 18 private float waitTime; 19 // Start is called before the first frame update 20 void Start() 21 { 22 SetState(State.Wait); 23 mineHitCount = 0; 24 25 } 26 27 // Update is called once per frame 28 void Update() 29 { 30 if(isMining) { 31 Mining(); 32 } 33 } 34 35 //採掘処理 36 private void Mining() { 37 if(state == State.Walk) { 38 anim.SetFloat("Walk", navMeshAgent.desiredVelocity.magnitude); 39 elapsedTime = 0; 40 if(navMeshAgent.remainingDistance < 2.7f) { 41 mineHitCount = 0; 42 SetState(State.Mine); 43 } 44 } else if(state == State.Wait) { 45 elapsedTime += Time.deltaTime; 46 navMeshAgent.velocity = Vector3.zero; 47 if(elapsedTime > waitTime) { 48 SetState(State.Walk); 49 } 50 } else if (state == State.Mine) { 51 navMeshAgent.velocity = Vector3.zero; 52 if(mineHitCount > 4) { 53 SetState(State.Wait); 54 RemoveList(); 55 BreakDown(); 56 } 57 } 58 59 if(!targetPositions.Any()) { 60 FinishMining(); 61 } 62 } 63 64 //採掘開始 65 public void MineStart(List<Transform> mineTargets) { 66 targetPositions = mineTargets; 67 isMining = true; 68 SetState(State.Wait); 69 } 70 71 private void hitMine() { 72 mineHitCount ++; 73 } 74 75 private void BreakDown() { 76 GetDestination().GetComponent<DestructibleObjectManager>().ItemDrop(); 77 Destroy(GetDestination().gameObject); 78 } 79 80 private void FinishMining() { 81 isMining = false; 82 SetState(State.Wait); 83 } 84}
Mine
選した採取物をリストに入れてCharacterMiningManagerに送るスクリプト
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.UI; 5using System.Linq; 6 7public class Mine : MonoBehaviour 8{ 9 //採掘画面 10 [SerializeField] 11 private GameObject MinePanel; 12 [SerializeField] 13 // private CharacterMiningManager cMM; 14 private CharacterMiningManager[] cMMs; 15 //選択した木とかのリスト 16 private List<Transform> mineTargets = new List<Transform>(); 17 // Start is called before the first frame update 18 void Start() 19 { 20 MinePanel.SetActive(true); 21 } 22 23 // Update is called once per frame 24 void Update() 25 { 26 //クリックしたオブジェクトをリストに入れる 27 if(Input.GetButtonDown("Fire1")) { 28 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 29 30 RaycastHit hit; 31 if(Physics.Raycast(ray, out hit)) { 32 if(hit.collider.CompareTag("Destructible")) { 33 Transform hitRoot = hit.transform.parent.parent.parent; 34 int num = mineTargets.IndexOf(hitRoot); 35 36 if(num >= 0) { 37 mineTargets.Remove(hitRoot); 38 Destroy(hitRoot.Find("MineIcon(Clone)").gameObject); 39 } else { 40 mineTargets.Add(hitRoot); 41 Icon(hitRoot); 42 } 43 } 44 } 45 } 46 } 47 //採取を開始する 48 public void MineButton() { 49 //近い順に並べる 50 var sort = mineTargets.OrderBy(a => Vector3.Distance(a.transform.position, transform.position)).ToList(); 51 mineTargets = sort.ToList(); 52 foreach (var cMM in cMMs) 53 { 54 cMM.MineStart(mineTargets); 55 } 56 } 57}
DestructibleObjectManager
採取物にパートナー設定をするスクリプト
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class DestructibleObjectManager : MonoBehaviour 6{ 7 public GameObject ItemObject; 8 [SerializeField] 9 private Item item; 10 [Header("ドロップさせるアイテムの名前")] 11 [SerializeField] 12 private string ItemName; 13 14 //パートナーがいるかどうか 15 private bool isPartner = false; 16 // Start is called before the first frame update 17 void Start() 18 { 19 20 } 21 22 // Update is called once per frame 23 void Update() 24 { 25 26 } 27 28 public void ItemDrop() { 29 if(item.GetItemName() == ItemName) { 30 for(int i = 0; i < item.GetAmount(); i++){ 31 Instantiate(ItemObject, new Vector3(transform.position.x, transform.position.y + i, transform.position.z), Quaternion.identity); 32 } 33 } 34 } 35 36 public void SetPartner(GameObject partner) { 37 Debug.Log("SetPartner"); 38 Debug.Log(partner); 39 Debug.Log(gameObject); 40 isPartner = true; 41 } 42 43 public bool IsPartnerSet() { 44 Debug.Log("IsPartnerSet" + gameObject); 45 Debug.Log(isPartner); 46 return isPartner; 47 } 48}
試したこと
Debug.Logなどを用いてisMiningやリストのnull非null、パートナーは設定できているかなどを調べたところ、パートナーは設定できているのですが、一人目が採取を終えるとほかの人のリストもnullになっていて、isMiningがfalseになってしまっていました。
補足情報(FW/ツールのバージョンなど)
Unity 2020.3.26f1
あなたの回答
tips
プレビュー