首页 > 解决方案 > 如何使 2d 对象不断向一个方向移动,但是当给定水平输入改变方向但不改变速度时?

问题描述

我很抱歉,因为我是 Unity 库和 Unity 本身的纯菜鸟。

我正在创建一个简单的 2d 游戏,其中 2d 对象需要不断地朝着一个方向移动,但是当应用水平输入(例如 A、D)时,它需要改变运动矢量而不是改变速度。

该对象有一个属性 Rididbody2d

到目前为止,这是我想出的:

{ 
      [SerializeField]
      private float speed;

      [SerializeField]
      private float rotationSpeed;
      
    // Start is called before the first frame update  

    void Start()
    {       

    }


    // Update is called once per frame
     void Update ()
     {      
           
           float horizontalInput = Input.GetAxis("Horizontal");
           float verticalInput = Input.GetAxis("Vertical");

            

            Vector2 movementDirection = new Vector2(horizontalInput, verticalInput);
            float inputMagnitude = Mathf.Clamp01(movementDirection.magnitude);
            movementDirection.Normalize();

 
            transform.Translate(movementDirection * speed * inputMagnitude * Time.deltaTime, Space.World);

            if (movementDirection != Vector2.zero) {
                  Quaternion toRotation = Quaternion.LookRotation(Vector3.forward, movementDirection);
                  transform.rotation = Quaternion.RotateTowards(transform.rotation, toRotation, rotationSpeed * Time.deltaTime);
            }

            
     }
}

我的想法是,在更新期间,我们应该获取输入是否已注册,如果是,则当前向量乘以(?)已接收到的角度(如果按下 0.1 秒 -> 0deg+1deg,如果按下2 秒 -> 0 度 + 比如说 90 度,例如)。

然而!按照教程,我设法让这个东西只有在按下键时才能移动。我用谷歌搜索了一下,发现实际上没有任何帮助。手册被重读了很多遍。请帮我!

PS 英语不是我的母语,如有错误请见谅!

标签: c#unity3d

解决方案


一旦涉及物理,您根本不想通过刚体组件做任何事情,而是通过刚体组件而不是在...中,否则您会遇到各种奇怪的行为并破坏物理/碰撞检测!transformUpdateFixedUpdate

在我看来,您想要做的是:

[SerializeField] private float speed;
[SerializeField] private float rotationSpeed;

// reference this in the Inspector if possible
[SerializeField] private Rigidbody2D rigidbody;

// keep track of the target rotation
// for Rigidbody2D this is a simple float for the rotation angle
private float angle = 0;

private void Awake()
{
    // as fallback get the Rigidboy2D on runtime
    if(!rigidbody) rigidbody = GetComponent<Rigidbody2D>();
}

private void Update ()
{      
    // Still get user input in Update to not miss a frame

    // evtl you would need to swap the sign according to your needs
    angle += Time.deltaTime * rotationSpeed * Input.GetAxis("Horizontal");
}

private void FixedUpdate()
{
    // rotate the Rigidbody applying the configured interpolation
    rb.MoveRotation(angle);

    // assuming if the object is not rotated you want to go right
    // otherwise simply change this vector
    rb.velocity = rb.GetRelativeVector(Vector3.right).normalized * speed;
}

推荐阅读