我的导航系统是围绕 Aron Granberg 的 A* Pathfinder 项目构建的(Unity 资产商店中的资产,或简称为“webbing”)。它的语法与 Unity 的 Navmesh 非常相似
我的导航系统是围绕 Aron Granberg 的 A* Pathfinder 项目(在 Unity 资产商店中找到的资产或简称为“webbing”)。其语法与 Unity 的 Navmesh 导航的读写方式非常相似。
下面的代码示例正确地将代理导航到 内的预定位置 List<T>
根据其 Vector3
排名 获得目标 。我的逻辑失败之处在于整个阵型不会像我目前所做的那样旋转。所有个体都会独立旋转和移动,但每次调用这些函数时,位置对齐都会保持在同一方向上。
TL;DR :这会将单位移动到战术排列中,但不会旋转整个阵型。我想旋转整个阵型。
public class ReadyUnit
{
public PlayerControl player { get; set; }
public int rank { get; set; }
}
public class Formation : MonoBehaviour
{
public Formation Instance { get; private set; }
enum order
{
loose,
column,
circle,
vanguard,
firingLine
}
[Header("All player characters share the same SINGLE PathOrganizer in the scene.")]
[SerializeField] order arrangement = order.loose;
[Range(1, 15)][SerializeField] int rank;
PathOrganizer organizer;
ReadyUnit unit;
public static List<ReadyUnit> readyUnitList = new List<ReadyUnit>();
int currentRank;
private void Awake()
{
unit = new ReadyUnit { player = gameObject.GetComponent<PlayerControl>(), rank = currentRank };
}
private void Start()
{
if (IsLeader())
{
unit.rank = 0;
}
else
{
unit.rank = rank;
}
/* There should only be ONE instance of PathOrganizer in the scene */
organizer = FindFirstObjectByType<PathOrganizer>();
Selector.Instance.UnitSelectedEvent += OnUnitSelected;
}
void OnUnitSelected(object sender, EventArgs e)
{
if (Selector.Instance.GetSelectedPlayersList().Contains(gameObject.GetComponent<PlayerControl>()) &&
readyUnitList.Contains(unit) == false)
{
readyUnitList.Add(unit);
}
if (Selector.Instance.GetSelectedPlayersList().Contains(gameObject.GetComponent<PlayerControl>()) == false &&
readyUnitList.Contains(unit))
{
readyUnitList.Remove(unit);
}
if (Selector.Instance.GetSelectedUnit() == gameObject.GetComponent<PlayerControl>())
{
unit.rank = 0;
}
else
{
unit.rank = rank;
}
SortUnitsByRank();
}
void SortUnitsByRank()
{
readyUnitList.Sort((leftHand, rightHand) => leftHand.rank.CompareTo(rightHand.rank));
}
public void FallInStep(Vector3 point)
{
if (point == null)
{
return;
}
if (readyUnitList == null)
{
return;
}
SortUnitsByRank();
MoveToPosition(point);
}
void MoveToPosition(Vector3 point)
{
switch (arrangement)
{
case order.loose:
LooseArrangement(point);
break;
case order.column:
ColumnArrangement(point);
break;
case order.circle:
CircleArrangement(point);
break;
case order.vanguard:
VanguardArrangement(point);
break;
case order.firingLine:
FiringLine(point);
break;
}
}
bool IsLeader()
{
return Selector.Instance.GetSelectedUnit() == gameObject.GetComponent<PlayerControl>();
}
void LooseArrangement(Vector3 point)
{
float offset = Random.Range(-2f, 2f);
List<Vector3> values = new List<Vector3>
{
point,
point + new Vector3(offset, 0, offset),
point + new Vector3(offset, 0, offset),
point + new Vector3(offset, 0, offset),
point + new Vector3(offset, 0, offset),
point + new Vector3(offset, 0, offset),
point + new Vector3(offset, 0, offset),
point + new Vector3(offset, 0, offset),
point + new Vector3(offset, 0, offset),
point + new Vector3(offset, 0, offset),
point + new Vector3(offset, 0, offset),
point + new Vector3(offset, 0, offset)
};
for (int i = 0; i < values.Count; i++)
{
PlayerControl player = readyUnitList[i].player;
player.GetComponent<MovementManager>().MoveToDestination(values[i]);
}
}
void ColumnArrangement(Vector3 point)
{
List<Vector3> values = new List<Vector3>()
{
point,
point + new Vector3(2f, 0, 0),
point + new Vector3(0, 0, -2f),
point + new Vector3(2f, 0, -2f),
point + new Vector3(0, 0, -4f),
point + new Vector3(2f, 0, -4f),
point + new Vector3(0, 0, -6f),
point + new Vector3(2f, 0, -6f),
point + new Vector3(0, 0, -8f),
point + new Vector3(2f, 0, -8f),
point + new Vector3(0, 0, -10f),
point + new Vector3(2f, 0, -10f),
};
for (int i = 0; i < readyUnitList.Count; i++)
{
PlayerControl player = readyUnitList[i].player;
organizer.transform.position = point;
organizer.AssignPosition(values[i]);
player.GetComponent<MovementManager>().MoveToDestination(organizer.ConfirmedPosition());
}
}
void CircleArrangement(Vector3 point)
{
float diameter = 2.5f;
for (int i = 0; i < readyUnitList.Count; i++)
{
float angle = (float)(i * (2f * Math.PI / readyUnitList.Count));
float cos = (float)Math.Cos(angle) * diameter;
float sin = (float)Math.Sin(angle) * diameter;
point = new Vector3(point.x + cos, point.y, point.z + sin);
PlayerControl player = readyUnitList[i].player;
player.GetComponent<MovementManager>().MoveToDestination(point);
}
}
void VanguardArrangement(Vector3 point)
{
List<Vector3> values = new List<Vector3>()
{
point,
point + new Vector3(1f, 0, -1f),
point + new Vector3(-1f, 0, -1f),
point + new Vector3(2f, 0, -2f),
point + new Vector3(-2f, 0, -2f),
point + new Vector3(3f, 0, -3f),
point + new Vector3(-3f, 0, -3f),
point + new Vector3(4f, 0, -4f),
point + new Vector3(-4f, 0, -4f),
point + new Vector3(5f, 0, -5f),
point + new Vector3(-5f, 0, -5f),
point + new Vector3(0, 0, -1f),
};
for (int i = 0; i < readyUnitList.Count; i++)
{
PlayerControl player = readyUnitList[i].player;
organizer.transform.position = point;
organizer.AssignPosition(values[i]);
player.GetComponent<MovementManager>().MoveToDestination(organizer.ConfirmedPosition());
}
}
void FiringLine(Vector3 point)
{
List<Vector3> values = new List<Vector3>()
{
point,
point + new Vector3(1f, 0, 0),
point + new Vector3(-1f, 0, 0),
point + new Vector3(2f, 0, 0),
point + new Vector3(-2f, 0, 0),
point + new Vector3(3f, 0, 0),
point + new Vector3(-3f, 0, 0),
point + new Vector3(4f, 0, 0),
point + new Vector3(-4f, 0, 0),
point + new Vector3(5f, 0, 0),
point + new Vector3(-5f, 0, 0),
point + new Vector3(6f, 0, 0),
};
for (int i = 0; i < values.Count; i++)
{
PlayerControl player = readyUnitList[i].player;
player.GetComponent<MovementManager>().MoveToDestination(values[i]);
}
}
}
其意义跨越了党派界限:
public class PathOrganizer : MonoBehaviour
{
[SerializeField] GameObject destinationMarker = null;
IAstarAI agent;
MovementManager movement;
Vector3 callback = Vector3.zero;
private void Awake()
{
agent = GetComponent<IAstarAI>();
GetComponent<MovementManager>();
}
void Start()
{
transform.position = Selector.Instance.GetSelectedUnit().transform.position;
movement.ReachDestinationEvent += OnDestinationReached;
}
void OnDestinationReached(object sender, EventArgs e)
{
foreach (Transform child in gameObject.transform)
{
Destroy(child.gameObject);
}
}
public void ClearDestinationMarkers()
{
foreach(Transform child in gameObject.transform)
{
Destroy(child.gameObject);
}
}
public void AssignPosition(Vector3 point)
{
agent.destination = point;
GameObject waypoint = Instantiate(destinationMarker, point, Quaternion.identity);
waypoint.transform.SetParent(gameObject.transform, true);
waypoint.transform.eulerAngles = new Vector3(90, 0, 0);
callback = point;
}
public Vector3 ConfirmedPosition()
{
return callback;
}
public void SteerFormation()
{
agent.destination = Input.mousePosition;
}
}
变量 Vector3 回调 将向量返回到 MovementManager.cs ,从而完成移动。这部分也运行得很好。最后一种方法 ( SteerFormation ) 是我遇到的问题。您在那里看到的只是一个占位符命令,直到我最终能够在这个挑战中获得 \'W\'。我尝试了更复杂的旋转逻辑,包括查找方向和幅度或将其与相机的视野对齐。之前的失败和上面的失败确实会转动容器 GameObject ( PathOrganizer ),但其中的位置从未改变。
我认为问题在于,这些实例化的位置(通过 destinationMarker)反映了全球定位,实际上只不过是它们所在地面上的标记。我希望这些标记能够像公交车一样放在 PathOrganizer 内,而代理则是追赶公交车的狗。理论上,如果我驾驶公交车,整个羊群都会跟着我。我调查过类似的查询,但没有找到(或者可能没有理解)令人满意的解决方案。