C# Enemyi在Y轴上以相反方向旋转
当战斗旗帜熄灭,玩家进入敌人的战斗区域后,我想在玩家移动时跟踪它,确保敌人的Z轴始终指向玩家 当玩家进入战区时,敌人会自动将玩家标记为其目标,但在首次发起战斗时,Z轴可能不会指向敌人的目标。我决定在战旗熄灭时从敌人的Z轴发射一束射线,并旋转敌人,直到射线与玩家相交,从而告诉我敌人的Z轴已正确排列 敌人总是有一个指向其当前目标的参考。我的想法是,一旦敌人最初发现其目标,它可以保存最近发现的位置,然后获取当前targetPosition.x和最后发现的位置.x的增量,如果增量为正,则向右旋转,如果增量为负,则向左旋转 问题是:我的数学或逻辑一定有缺陷,因为尽管有时有效,但其他时候敌人会随机向相反方向旋转,射线投射基本上会选择长路径来击中玩家,而不是预期的最短路径。代码如下C# Enemyi在Y轴上以相反方向旋转,c#,unity3d,collision-detection,game-physics,C#,Unity3d,Collision Detection,Game Physics,当战斗旗帜熄灭,玩家进入敌人的战斗区域后,我想在玩家移动时跟踪它,确保敌人的Z轴始终指向玩家 当玩家进入战区时,敌人会自动将玩家标记为其目标,但在首次发起战斗时,Z轴可能不会指向敌人的目标。我决定在战旗熄灭时从敌人的Z轴发射一束射线,并旋转敌人,直到射线与玩家相交,从而告诉我敌人的Z轴已正确排列 敌人总是有一个指向其当前目标的参考。我的想法是,一旦敌人最初发现其目标,它可以保存最近发现的位置,然后获取当前targetPosition.x和最后发现的位置.x的增量,如果增量为正,则向右旋转,如果增
//create ray from enemy position orgin and point it on the Z-Axis
Ray ray = new Ray(CurrentEnemyTransform.position, CurrentEnemyTransform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 50f))
{
Debug.DrawLine(ray.origin, hit.point);
//ray hits current enemy target
if (hit.transform == CurrentTargetTransform)
{
//check if enemy has seen its target before while in this battle
//or is it the first time
if (enemy.hasTargetLastPosition)
//replace old last seen position with most recent spotting
enemy.ReplaceTargetLastPosition(hit.transform.position);
//or add the first spotting of target while in this battle
else enemy.AddTargetLastPosition(hit.transform.position);
}
//ray is not intersectiing with the enemy's current target so rotate to look for it
if (hit.transform != CurrentTargetTransform)
{
//check if enemy has seen its target once before in battle
if (enemy.hasTargetLastPosition)
{
//since last spotting has my target moved more to the left or right?
if (enemy.targetLastPosition.value.x > CurrentTargetTransform.position.x)
{
//rotate right
CurrentEnemyTransform.Rotate(-Vector3.up, 5f, Space.Self);
}
//rotate left
else CurrentEnemyTransform.Rotate(Vector3.up, 5f, Space.Self);
}
//never seen target yet during this battle so default rotation to right till you found it
else CurrentEnemyTransform.Rotate(-Vector3.up, 5f, Space.Self);
}
一个明显的问题是这一行:
if (enemy.targetLastPosition.value.x > CurrentTargetTransform.position.x)
这可以检查目标是否位于敌人目标位置的右侧。但它并不适用于所有可能的职位。(在Z轴上翻转坐标的图片-它还能工作吗?)
正确的方法是使用二维叉积:
(Ax,Az)x(Bx,Bz)=Ax*Bz-Az*Bx
如果向量A
相对于B
顺时针旋转,则为正,反之亦然
(此外,我们需要检查相对于敌人的相对位置,而不是他们的世界位置;要做到这一点,只需减去CurrentEnemyTransform.position
)
对此还有其他改进,例如,使敌人精确瞄准目标,而不是在5度范围内瞄准。但这应该是一个粗糙的方法
private static bool isOnRight(Vector3 a, Vector3 b)
{
return a.x * b.z - a.z * b.x > 0.0f;
}
//...
// is last known position on the right of the actual position?
if (isOnRight(enemy.targetLastPosition - CurrentEnemyTransform.position,
CurrentTargetTransform.position - CurrentEnemyTransform.position))
{
// rotate *left*, not right
CurrentEnemyTransform.Rotate(Vector3.up, -5f, Space.Self);
}
else CurrentEnemyTransform.Rotate(Vector3.up, 5f, Space.Self);