【问题标题】:Unity 2018 - NPC smoothly turning to face the Player while within rangeUnity 2018 - NPC 在射程内顺利转向面对玩家
【发布时间】:2020-07-02 08:56:51
【问题描述】:

使用当前代码,NPC 将检测到并转向播放所需动画的玩家。但是,NPC 只会快速面对玩家,并且不会继续旋转,因为玩家在范围内时围绕 NPC 走动。

我想对此进行修改,以便 NPC 在玩家处于对撞机范围内时始终平稳地转向面对角色。我认为它可以在 void update 中做一些事情,但是由于当前的转函数在 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");
        }
    }
}

【问题讨论】:

  • 如果您不打算使用Update,请删除它。 Unity 在编译时创建一个对象列表以调用 Update(如果已定义)。因此,当您不使用 Update 时,它会影响性能。

标签: c# unity3d


【解决方案1】:

如果您希望游戏对象平滑地面对另一个游戏对象,请使用Quaternion.LookRotation 计算目标旋转,然后使用Quaternion.Lerp 在当前旋转和使用Quaternion.LookRotation 计算的目标旋转之间调整。最后,随着时间的推移做 lerping。请参阅this 帖子以了解如何应对轮换。您可以在 Update 函数中执行此操作,但我将在协程函数中使用它,因为它为您提供更多控制权。

一个简单的 Look-at smooth 函数:

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

【讨论】:

  • 顶部抽屉!!!并帮助我更清楚地了解如何以及为什么使用协程。谢谢!!!
  • 确实!一开始我不确定协程是什么!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-13
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多