Unity C#:transform.up行为异常

时间:2019-12-23 22:13:57

标签: c# unity3d transform

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public GameObject player;
    public Rigidbody2D playerRB;
    public Transform playerTF;

    public float moveForce;
    public float rotateForce;

    private string currentMoveKey = "";
    private string currentRotateKey = "";

    void Update()
    {
        //move
        if(Input.GetKey("w") && currentMoveKey == "")
        {
            currentMoveKey = "w";

            playerRB.AddForce(transform.up * moveForce * Time.deltaTime);
        }

        if (Input.GetKeyUp("w") && currentMoveKey == "w")
        {
            playerRB.velocity = new Vector2(0, 0);//resets when keyup and not already reset

            currentMoveKey = "";
        }

        if (Input.GetKey("s") && currentMoveKey == "")
        {
            currentMoveKey = "s";

            playerRB.AddForce(transform.up * -moveForce * Time.deltaTime);
        }

        if (Input.GetKeyUp("s") && currentMoveKey == "s")
        {
            playerRB.velocity = new Vector2(0, 0);

            currentMoveKey = "";
        }
        //rotate
        if (Input.GetKeyDown("a") && currentRotateKey == "")
        {
            currentRotateKey = "a";
        }
        if (Input.GetKey("a") && currentRotateKey == "a")
        {
            playerTF.Rotate(transform.forward * rotateForce * Time.deltaTime);
        }
        if (Input.GetKeyUp("a") && currentRotateKey == "a")
        {
            currentRotateKey = "";
        }

        if (Input.GetKeyDown("d") && currentRotateKey == "")
        {
            currentRotateKey = "d";
        }
        if (Input.GetKey("d") && currentRotateKey == "d")
        {
            playerTF.Rotate(transform.forward * -rotateForce * Time.deltaTime);
        }
        if (Input.GetKeyUp("d") && currentRotateKey == "d")
        {
            currentRotateKey = "";
        }
    }
}

嘿!由于某些原因,在我将力添加到RigidBody2D的行中,如果我在移动玩家的同时旋转播放器-从而改变了transform.up的指向位置-播放器继续朝着原始指向的方向移动。换句话说,他看起来像他在滑动,我必须停止移动并重新开始移动以更新他指向的方向。我该怎么做才能解决此问题,以便在他旋转时,他的移动方向会同时更新?

1 个答案:

答案 0 :(得分:0)

加力只是不断增加刚体的动量;您已经知道了这一点,因为您在抬起琴键时已重置速度。当您转身但保持向前移动时,刚体速度不会被重置,而只是进行了相加更改。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public GameObject player;
    public Rigidbody2D playerRB;
    public Transform playerTF;

    public float moveForce;
    public float rotateForce;

    private Vector3 movement;

    private string currentRotateKey = "";

    void Update()
    {
        //move in Local space
        if (Input.GetKeyDown(KeyCode.W))
        {
            movement += Vector3.up;
        }

        if (Input.GetKeyUp(KeyCode.W))
        {
            movement -= Vector3.up;
        }

        if (Input.GetKeyDown(KeyCode.S))
        {
            movement -= Vector3.up;
        }

        if (Input.GetKeyUp(KeyCode.S))
        {
            movement += Vector3.up;
        }

        //rotate
        if (Input.GetKeyDown("a") && currentRotateKey == "")
        {
            currentRotateKey = "a";
        }
        if (Input.GetKey("a") && currentRotateKey == "a")
        {
            playerTF.Rotate(transform.forward * rotateForce * Time.deltaTime);
        }
        if (Input.GetKeyUp("a") && currentRotateKey == "a")
        {
            currentRotateKey = "";
        }

        if (Input.GetKeyDown("d") && currentRotateKey == "")
        {
            currentRotateKey = "d";
        }
        if (Input.GetKey("d") && currentRotateKey == "d")
        {
            playerTF.Rotate(transform.forward * -rotateForce * Time.deltaTime);
        }
        if (Input.GetKeyUp("d") && currentRotateKey == "d")
        {
            currentRotateKey = "";
        }

        // Implicit cast from Vector3 to Vector2, takes X and Ys
        ApplyMovement(movement);
    }

    public void ApplyMovement(Vector2 movement)
    {
        playerRB.velocity = player.transform.TransformDirection(movement.x, movement.y, 0) * moveForce * Time.deltaTime;
    }
}

我发现使用KeyCode枚举而不是字符串值会更干净一些,而且我想为该类跟踪本地Vector3 movement而不是检查currentMovementKey。这样一来,您可以一次按下多个键,并在编译时捕获拼写错误。

将移动“应用”到自己的方法中有助于改变您的行为。

movement在本地空间中处理,使用Vector3.up而不是transform.up以避免旋转时出错,然后将其应用于playerRB.velocity时,我们可以转换回世界空间使用player.transform.TransformDirection(movement.x, movement.y, 0)(如果该组件与RigidBody2D组件位于同一GameObject上,则也可以是transform.TransformDirection(movement.x, movement.y, 0)

如果您想保持加速度而不是想跳起来而不是减速,但是又不想像真实物体那样漂移,事情会变得有些棘手,这是解决问题的一种方法:

    public void ApplyMovement(Vector3 movement)
    {
        if (movement.sqrMagnitude > Mathf.Epsilon)
        {
            playerRB.drag = 0; // or some other small value
            if (playerRB.velocity.sqrMagnitude > Mathf.Epsilon)
            {
                playerRB.velocity = player.transform.TransformDirection(movement.normalized) * playerRB.velocity.magnitude;
            }

            playerRB.AddRelativeForce(movement * moveForce * Time.deltaTime);
        }
        else
        {
            playerRB.drag = 100f; // or some other value larger than the small one
        }
    }

我们现在正在做的是检查是否有不可忽略的运动量(基本为0),如果要移动,就不施加阻力,因为那样会减慢速度我们的积极加速,这使得难以预测设置游戏时应具有的值。

由于我们现在没有在物体上的阻力,因此它应该根据物理学原理漂移。这就是您目前所看到的。如果我们不希望这样做,可以检查是否有不可忽略的(基本为0)速度,并将其与所需的运动方向对齐。不要忘记movement仍在本地空间中,playerRB.velocity仍在世界空间中。

然后,由于我们要应用运动,因此应使用AddRelativeVelocity local 运动应用到身体,以继续沿所需方向加速。目前,这种情况一直持续下去,但是您最终可能希望限制最大速度。

如果我们不应用运动,我们希望物理学应用阻力并降低玩家的速度。如果我们让物理学做功,您应该获得合理的加速或减速速度(取决于阻力值和作用力),但是由于我们忽略了漂移,因此您应该立即转弯。