Unity 5:如何自然地减缓刚体,而不是突然停止

时间:2016-10-31 19:22:18

标签: unity3d

我正在使用它:

void Update(){
    if(leftJoystick){
        rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
    }
}

将我的角色向前移动(使用喷气背包)。当我放开操纵杆时,我的角色会立即停止。我想要的是,在释放操纵杆并且时间减慢并逐渐停止后,角色继续向前移动。我的角色就​​像撞墙一样停下来看起来很愚蠢。我应该使用什么样的力/速度/变换,以便在我放开操纵杆后物理减慢我的角色?

我的刚体设置:

  • 质量:100
  • 拖动:0
  • 角度阻力:0.05
  • 使用重力
  • 不是运动学
  • 插值:插值
  • 碰撞检测:离散
  • 冻结位置:无
  • 冻结轮换:全部

角色还有一个胶囊对撞机,它不是触发器,没有物理材料。

编辑:这是完整的代码,以便您可以查看我的代码中是否存在任何冲突

using UnityEngine;
using System.Collections;
using UnityStandardAssets.CrossPlatformInput;

public class JetpackController : MonoBehaviour{

    Rigidbody rb;

    // controller axes
    [SerializeField]
    public string speedAxis = "Vertical";
    public string rotateAxis = "HorizontalRotate";

    [SerializeField]
    public float forwardSpeed;
    public float upSpeed;
    public float rotateSpeed;
    public float rotationIgnoreZone;
    public float MAX_HEIGHT;

    float speedInput;
    float rotateInput;
    public bool leftJoystick;
    public bool rightJoystick;

    ParticleSystem jetpackFire1;

    Vector3 originalGravity;

    // access Joystick script in Standard assets to detect when right joystick is held down
    Joystick joystick_left;
    Joystick joystick_right;

    void Start () {
        if (GetComponent<Rigidbody> ()) {
            rb = GetComponent<Rigidbody> ();
        } else {
            Debug.LogError ("Player needs to have a rigidbody.");
        }

        // get Joysticks
        if (GameObject.Find ("MobileJoystick_left").GetComponent<Joystick> ()) {
             joystick_left = GameObject.Find ("MobileJoystick_left").GetComponent<Joystick> ();
         } else {
             Debug.LogError ("Either gameobject with name 'MobileJoystick_right' does not exist in the scene or it does not have script called Joystick.cs attached to it.");
        }
        if (GameObject.Find ("MobileJoystick_right").GetComponent<Joystick> ()) {
            joystick_right = GameObject.Find ("MobileJoystick_right").GetComponent<Joystick> ();
        } else {
            Debug.LogError ("Either gameobject with name 'MobileJoystick_right' does not exist in the scene or it does not have script called Joystick.cs attached to it.");
        }

        jetpackFire1 = GameObject.Find("JetpackFire1").GetComponent<ParticleSystem> ();
        jetpackFire1.playbackSpeed = 5.0f;

        originalGravity = Physics.gravity;
    }

    void FixedUpdate () {

        GetInput ();

        // move forward and backward according to left joysticks input
        if(leftJoystick){
            // left joystick held down
            rb.AddRelativeForce(0, 0, forwardSpeed*speedInput, ForceMode.Impulse);
        }

        // if right joystick is used
        if (rightJoystick) {
            jetpackFire1.Play ();

        if (transform.position.y < MAX_HEIGHT) {
            // allow going up
            //rb.AddRelativeForce (0, upSpeed, 0, ForceMode.Impulse);
            rb.AddForce(transform.forward * forwardSpeed);
        } else if (transform.position.y >= MAX_HEIGHT) {
            // prevent player to go any further up and also falling
            Physics.gravity = Vector3.zero; // no gravity to prevent player from falling
            rb.velocity = Vector3.zero;
        }
            // rotate
            // always keep rotating (player can go past look at joystick dir)
            if (rotateInput >= rotationIgnoreZone || rotateInput <= -rotationIgnoreZone) {
                transform.Rotate(Vector3.up * rotateInput, Time.deltaTime * rotateSpeed);
            }
    } else {
            jetpackFire1.Stop ();
            // if right joystick is released
            Physics.gravity = originalGravity; // normal gravity -> player can fall
        }

    } 

public void GetInput(){
    speedInput = CrossPlatformInputManager.GetAxis (speedAxis);
    rotateInput = CrossPlatformInputManager.GetAxis (rotateAxis);
    // access Joystick.cs script to grab wether right joystick is pressed or not
    leftJoystick = joystick_left.leftJoystickPressed;
    rightJoystick = joystick_right.rightJoystickPressed;
}

}

3 个答案:

答案 0 :(得分:2)

无法发表评论

就像J.Small所说的那样,你可以将速度乘以0.95附近的数字来慢慢减速刚体。如果你将乘法放在Update方法中,我建议你将~0.95的数字与Time.deltaTime相乘,所以速度降低将与传递的时间成正比。

void Update(){
    if(leftJoystick){
        rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
    }

    if(noJoystick){
        rb.velocity = rb.velocity * 0.95 * Time.deltaTime;
        //Or: rb.velocity.x
    }
}

如果你想以一种更可配置的方式减慢刚体的速度,你也可以使用少量的力而不是乘以速度(如果你把它放到Update中,那么量应该基于Time.deltaTime - 它会被调用一旦一帧),但上面的方法更容易。

答案 1 :(得分:2)

我不是编码专家,所以我不确定这是否适用于每个人,但我尝试了类似的方法来解决类似的问题。

    void FixedUpdate()
    {
        playerRigidbody.AddRelativeForce(Vector2.up * forwardInput * playerSpeed * Time.fixedDeltaTime);

        if (forwardInput <= 0)
        {
            playerRigidbody.velocity = playerRigidbody.velocity / 1.005f; // <-- This will gradually slow down the player when they're idle.
        }
    } 

答案 2 :(得分:0)

你可以做一个简单的线性减速。

void Update(){
    if(leftJoystick){
        rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
    }

    if(noJoystick){
        rb.velocity = rb.velocity * 0.9;
    }
}

请注意,更新函数会在帧更新时调用,因此我建议将其置于FixedUpdate()函数中,这样慢速率将不依赖于帧速率。