我有一个Guard预制件,它有两个子组件:一个用于检测目标是否在范围内,另一个用于检测目标是否在捕获范围内。捕获范围的OnTriggerEnter对预制的两个实例都有效。但是用于检测目标是否在范围内的一个只适用于生成的Prefab的第一个实例。两个子对象都有一个刚体,设置为运动学,并有自己的任务碰撞器。父类没有碰撞器。在我的脚本中检测它是否在范围内,我有两个触发器函数:
TGuardMovement mov;
void Start()
{
mov = GameObject.FindGameObjectWithTag("Guard").GetComponent<TGuardMovement>();
}
public void OnTriggerEnter2D(Collider2D a_Collider2D)
{
if (a_Collider2D.gameObject.CompareTag("Animal"))
{
//invoke chase
mov.InvokeChase();
}
}
public void OnTriggerExit2D(Collider2D a_Collider2D)
{
//cancel Invoke
if (a_Collider2D.gameObject.CompareTag("Animal"))
{
mov.CancelInvokeChase();
}
}
TGuardMovement是父节点上处理AI移动的脚本
public void InvokeChase()
{
InvokeRepeating("UpdatePath", 0f, .5f);
}
public void CancelInvokeChase()
{
CancelInvoke("UpdatePath");
}
这些是子对象调用的函数。只需调用函数分别开始和停止跟踪即可。这是UpdatePath()函数:
void UpdatePath()
{
if(m_GState == GuardState.PATROLING)
{
TriggerMovement();
}
else if (m_GState == GuardState.CHASING)
{
if (m_Seeker.IsDone())
{
m_Seeker.StartPath(m_Rb2D.position, targetGO.transform.position, OnPathComplete);
}
}
if (targetGO == null)
{
m_Seeker.StartPath(m_Rb2D.position, m_objManager.m_goTGuardObject.transform.position, OnPathComplete);
}
}
我有点在我的想法结束错误可能是什么。移动的触发事件是由不移动的预制件触发的,但它不会开始移动。即使只是传送实例也只能移动第一个生成的实例。
问题很可能出在第一个脚本的Start函数中。GameObject.FindGameObjectWithTag(string)
只返回它找到的第一个GameObject
。
可能的修复:
-
您可以使用
GameObject.FindGameObjectsWithTag(string)
,注意它说的是Objects
而不是Object
,并将其存储在GameObjects[]
中。 -
如果守卫在运行时被实例化,你可以通过创建一个列表来存储对守卫的引用:
public List<GameObject> guards = new List<GameObject>();
然后在产卵函数中:
guards.Add(Instantiate(guardPrefab));
-
如果警卫可能来来去去,你只是想让所有的警卫在该地区,你可以使用
Physics.OverlapSphere(...);
。它可以像光线投射一样使用,除了它获得一个区域中的所有碰撞器。你可以将它们存储在数组中,并在需要时访问它们的脚本。