Unity 2018-NPC在范围内时平稳地转向面对玩家

时间:2018-07-02 00:19:21

标签: c# unity3d

使用当前代码,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");
        }
    }
}

1 个答案:

答案 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;
        }
    }
}