前提
移動中の対象へ経路探索をしたい
コード
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using System.Linq; 5 6namespace UtilityModule 7{ 8 public class Moving_from_PositionA_to_PositionB : MonoBehaviour 9 { 10 private int map_Width = 100; 11 private int map_Height = 100; 12 private ChessboardPathFinder pathFinder; 13 public List<Vector2> moveList = new List<Vector2>(); 14 private float speed = 2.5f; 15 public bool stoped_Movement; 16 //始動したコルーチンを覚えておくためのフィールドを追加し... 17 private Coroutine movementAction; 18 19 void Awake() 20 { 21 pathFinder = new ChessboardPathFinder(map_Width, map_Height); 22 } 23 24 public bool Find_Path(Vector2Int startPosition,Vector2Int goalPosition) 25 { 26 bool pathFound = pathFinder.FindPath(startPosition, goalPosition); 27 28 return pathFound; 29 } 30 31 public void Start_MovementAction() 32 { 33 //コルーチン始動時にそれを保存 34 movementAction = StartCoroutine(Move()); 35 } 36 37 //そして覚えておいたコルーチンを停止するためのメソッドを用意 38 public void Stop_MovementAction() 39 { 40 if (movementAction != null) 41 { 42 StopCoroutine(movementAction); 43 moveList.Clear(); 44 } 45 } 46 47 IEnumerator Move() 48 { 49 foreach (Vector2Int position in pathFinder.Path.Skip(1)) 50 { 51 Vector2 pos = new Vector3(position.x, position.y); 52 moveList.Add(pos); 53 } 54 55 Vector2 unitPos = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y); 56 if(moveList.Contains(unitPos)) 57 { 58 moveList.Remove(unitPos); 59 } 60 61 int count = 0; 62 63 while (true) 64 { 65 if(stoped_Movement) 66 { 67 break; 68 } 69 70 gameObject.transform.position = Vector2.MoveTowards(gameObject.transform.position, moveList[count], speed * Time.deltaTime); 71 72 if (count < moveList.Count - 1) 73 { 74 count++; 75 } 76 77 if (gameObject.transform.position == (Vector3)moveList[moveList.Count - 1]) 78 { 79 break; 80 } 81 82 yield return null; 83 } 84 } 85 } 86}
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using Module_of_Unit; 5using UtilityModule; 6 7namespace Module_of_Berserkermode 8{ 9 public class Berserkermode : MonoBehaviour 10 { 11 private Unit_RandomWalk unit_RandomWalk; 12 private Unit gameObjectUnit; 13 private Moving_from_PositionA_to_PositionB moving_From_PositionA_To_PositionB; 14 private Unit_RandomWalk unit_RandomWalk_SelectedUnit; 15 private GameObject selectedUnit; 16 private bool get_Distance; 17 private bool switched_Berserkermode; 18 //前回のUpdateで調べたターゲットの位置を保存するためのフィールドを追加 19 private Vector2Int latestTargetPos; 20 21 private void Awake() 22 { 23 unit_RandomWalk = gameObject.GetComponent<Unit_RandomWalk>(); 24 gameObjectUnit = gameObject.GetComponent<Unit>(); 25 moving_From_PositionA_To_PositionB = gameObject.GetComponent<Moving_from_PositionA_to_PositionB>(); 26 } 27 28 public void Action() 29 { 30 //不満値が100%になったら、ランダム移動を停止する 31 unit_RandomWalk.Stop_RandomWalk(); 32 33 Invoke("Go", 1); 34 } 35 36 private void Go() 37 { 38 //ランダムに対象を選択する 39 int random = Random.Range(0, gameObjectUnit.playerOwnedUnits_List.Count); 40 selectedUnit = gameObjectUnit.playerOwnedUnits_List[random]; 41 unit_RandomWalk_SelectedUnit = selectedUnit.GetComponent<Unit_RandomWalk>(); 42 get_Distance = true; 43 switched_Berserkermode = true; 44 45 //対象がいた座標に向かって移動する 46 Go_To_TargetUnit(); 47 } 48 49 private void Update() 50 { 51 if(get_Distance) 52 { 53 //このユニットと対象のユニットの距離が、5タイル以内に入ったら、対象のユニットの移動を停止する 54 float distanse = Vector2.Distance(gameObject.transform.position, selectedUnit.transform.position); 55 if (distanse <= 3) 56 { 57 unit_RandomWalk_SelectedUnit.Stop_RandomWalk(); 58 int x = Mathf.RoundToInt(unit_RandomWalk_SelectedUnit.transform.position.x); 59 int y = Mathf.RoundToInt(unit_RandomWalk_SelectedUnit.transform.position.y); 60 unit_RandomWalk_SelectedUnit.transform.position = new Vector3(x, y, 0); 61 } 62 } 63 64 //対象のユニットが存在していた座標に到達したら、また移動する 65 /* 66 if (switched_Berserkermode && gameObject.transform.position == (Vector3)moving_From_PositionA_To_PositionB.moveList[moving_From_PositionA_To_PositionB.moveList.Count - 1]) 67 { 68 Go_To_TargetUnit(); 69 } 70 */ 71 72 if (switched_Berserkermode) 73 { 74 //現在のターゲットの位置を調べ... 75 Vector2Int targetPos = new Vector2Int((int)selectedUnit.transform.position.x, (int)selectedUnit.transform.position.y); 76 77 //敵の位置に変化があったら... 78 if (targetPos != latestTargetPos) 79 { 80 //現在動作中の移動コルーチンは中止し、目的地への経路を再計算 81 latestTargetPos = targetPos; 82 Stop_Movement(); 83 Go_To_TargetUnit(); 84 } 85 } 86 } 87 88 void Stop_Movement() 89 { 90 moving_From_PositionA_To_PositionB.Stop_MovementAction(); 91 } 92 93 void Go_To_TargetUnit() 94 { 95 //moving_From_PositionA_To_PositionB.moveList.Clear(); 96 97 Vector2Int startPos = new Vector2Int((int)gameObject.transform.position.x, (int)gameObject.transform.position.y); 98 Vector2Int goalPos = new Vector2Int((int)selectedUnit.transform.position.x, (int)selectedUnit.transform.position.y); 99 100 Vector2Int up = new Vector2Int(goalPos.x, goalPos.y + 1); 101 Vector2Int down = new Vector2Int(goalPos.x, goalPos.y - 1); 102 Vector2Int right = new Vector2Int(goalPos.x + 1, goalPos.y); 103 Vector2Int left = new Vector2Int(goalPos.x - 1, goalPos.y); 104 105 float up_Distance = Vector2.Distance(startPos, up); 106 float down_Distance = Vector2.Distance(startPos, down); 107 float right_Distance = Vector2.Distance(startPos, right); 108 float left_Distance = Vector2.Distance(startPos, left); 109 110 float min = Mathf.Min(up_Distance, down_Distance, right_Distance, left_Distance); 111 112 if(min == up_Distance) 113 { 114 goalPos = up; 115 } 116 117 if (min == down_Distance) 118 { 119 goalPos = down; 120 } 121 122 if (min == right_Distance) 123 { 124 goalPos = right; 125 } 126 127 if (min == left_Distance) 128 { 129 goalPos = left; 130 } 131 132 if (moving_From_PositionA_To_PositionB.Find_Path(startPos, goalPos)) 133 { 134 moving_From_PositionA_To_PositionB.Start_MovementAction(); 135 } 136 } 137 } 138}
試したこと
【回答を追記・編集しました】
ユニットはランダムに移動しているのですが、ユニットの「不満値」というパラメータが100になると、他のユニットの隣接に移動して、攻撃する、という実装にしようと思っていました。
ユニットが移動するスクリプトはUnit_RandomWalk.csというスクリプトです。すべてのユニットにこのスクリプトがアタッチされています。
目的のユニットが移動するたびに経路が再計算されるため、上記の図のように、ぐらぐらと揺れながら移動してしまっています。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2021/06/25 18:04 編集
2021/06/25 21:07
退会済みユーザー
2021/06/26 07:29
退会済みユーザー
2021/06/26 07:31
2021/06/27 00:13
退会済みユーザー
2021/06/27 05:27
2021/06/27 08:56
退会済みユーザー
2021/06/27 12:11