使用当前代码,NPC将检测到并转向具有所需动画播放的播放器。但是,当玩家在NPC范围内时,NPC只能在面对玩家时卡住并且不会继续旋转。
我想对此进行修改,以使NPC在玩家处于对撞机范围内时始终如一且平稳地转向面对角色。我认为这将在void更新中有所作为,但是由于转弯功能当前位于onTriggerEnter
中,因此对于像我这样的初学者来说有些困惑。
public class helloTrigger : MonoBehaviour
{
public Animator anim;
public CharacterController player;
public Transform Player;
void Start()
{
player = GameObject.FindObjectOfType<CharacterController>();
anim = GetComponent<Animator>();
}
void OnTriggerEnter(Collider other)
{
if (other.tag != "Player") return;
anim.Play("Hello");
Vector3 lookAt = Player.position;
lookAt.y = transform.position.y;
transform.LookAt(lookAt);
}
void OnTriggerExit(Collider other)
{
if (other.tag == "Player")
{
anim.Play("Idle");
}
}
}
答案 0 :(得分:3)
如果您希望一个GameObject平稳地面对另一个GameObject,请使用Quaternion.LookRotation
计算目标旋转,然后使用Quaternion.Lerp
在当前旋转和使用Quaternion.LookRotation
计算的目标旋转之间进行切换。最后,随着时间的流逝。请参阅this帖子以了解如何忍受轮换工作。您可以在Update
函数中执行此操作,但是我将在协程函数中使用它,因为它可以为您提供更多控制。
简单的Look-at平滑功能:
IEnumerator LookAtSmoothly(Transform objectToMove, Vector3 worldPosition, float duration)
{
Quaternion currentRot = objectToMove.rotation;
Quaternion newRot = Quaternion.LookRotation(worldPosition -
objectToMove.position, objectToMove.TransformDirection(Vector3.up));
float counter = 0;
while (counter < duration)
{
counter += Time.deltaTime;
objectToMove.rotation =
Quaternion.Lerp(currentRot, newRot, counter / duration);
yield return null;
}
}
您的新脚本:
public class helloTrigger : MonoBehaviour
{
public Animator anim;
public CharacterController player;
public Transform Player;
Coroutine smoothMove = null;
// Use this for initialization
void Start()
{
player = GameObject.FindObjectOfType<CharacterController>();
anim = GetComponent<Animator>();
}
void OnTriggerEnter(Collider other)
{
if (other.tag == "Player")
{
anim.Play("Hello");
LookSmoothly();
}
}
void OnTriggerExit(Collider other)
{
if (other.tag == "Player")
{
anim.Play("Idle");
}
}
void LookSmoothly()
{
float time = 1f;
Vector3 lookAt = Player.position;
lookAt.y = transform.position.y;
//Start new look-at coroutine
if (smoothMove == null)
smoothMove = StartCoroutine(LookAtSmoothly(transform, lookAt, time));
else
{
//Stop old one then start new one
StopCoroutine(smoothMove);
smoothMove = StartCoroutine(LookAtSmoothly(transform, lookAt, time));
}
}
IEnumerator LookAtSmoothly(Transform objectToMove, Vector3 worldPosition, float duration)
{
Quaternion currentRot = objectToMove.rotation;
Quaternion newRot = Quaternion.LookRotation(worldPosition -
objectToMove.position, objectToMove.TransformDirection(Vector3.up));
float counter = 0;
while (counter < duration)
{
counter += Time.deltaTime;
objectToMove.rotation =
Quaternion.Lerp(currentRot, newRot, counter / duration);
yield return null;
}
}
}