如何在unity3d中平稳地上下移动刚体对象

How to move rigidbody object up or down smoothly in unity3d

我已经开始一个项目,我在我的播放器上附加了一个刚体,以便在 运行 我的项目时对 it.So 施加一些力,然后在 FixedUpdate() 函数中我对 FixedUpdate() 施加力播放器向前移动它 direction.So 当我按下左箭头或右箭头时它执行 'tilt' 意味着旋转它的翅膀。 但是现在我想通过按下向上箭头或向下箭头来平滑地向上或向下移动我的播放器,当我同时按下向上箭头和向下箭头时,它一定会对播放器产生影响。 这是我的 code.Please 帮助。 :(

void FixedUpdate ()
{
  rb.AddForce(transform.forward *1000f);
  float movedir = Input.GetAxis ("Horizontal");

  Vector3 movement = new Vector3 (movedir, 0.0f, 0.0f);
  rb.velocity = movement * movingspeed;
  rb.rotation = Quaternion.Euler (0.0f, 0.0f, rb.velocity.x * -3f);//perform tilt


 if (Input.GetKeyDown (KeyCode.UpArrow)) 
      { 
       //code for smoothly move up from current position to = current position + 2f 
      }

  if (Input.GetKeyDown (KeyCode.DownArrow)) 
      { 
        //code for smoothly move down from current position to = current position - 2f 
      }


}

你的问题不是很清楚。移动 smoothly 可能意味着很多事情。

一般来说,您应该使用 RigidBody.MovePosition and Rigidbody.MoveRotation 来设置 Rigidbody 的变换而不是 rb.rotationrb.position 以获得“平滑”的运动:

Use Rigidbody.MovePosition to move a Rigidbody, complying with the Rigidbody's interpolation setting.

If Rigidbody interpolation is enabled on the Rigidbody, calling Rigidbody.MovePosition results in a smooth transition between the two positions in any intermediate frames rendered. This should be used if you want to continuously move a rigidbody in each FixedUpdate.

Set Rigidbody.position instead, if you want to teleport a rigidbody from one position to another, with no intermediate positions being rendered.

因此您可以看到,根据您的设置,使用 Rigidbody.MovePosition 可能已经导致“平滑”移动。

rb.MovePosition(transform.position + Vector3.up * 2.0f);

你也使用 Input.GetKeyDown 所以它像触发器一样工作......它不会像 Input.GetKey

那样连续调用

如果你想在按住键的同时连续移动,请使用例如

// set e.g. in the inspector
public float verticalMoveSpeed;

// ...

if (Input.GetKey(KeyCode.UpArrow)) 
{ 
    rb.MovePosition(transform.position + Vector3.up * verticalMoveSpeed * Time.deltaTime);
}

if (Input.GetKey(KeyCode.DownArrow)) 
{ 
    rb.MovePosition(transform.position - Vector3.up * verticalMoveSpeed * Time.deltaTime);
}

如果你只想用 GetKeyDown 触发移动,你也可以做一些类似

的事情
// set e.g. in the inspector
public float verticalMoveSpeed;

// ...

if (Input.GetKeyDown(KeyCode.UpArrow)) 
{ 
    StartCoroutine(MoveVertical(2.0f, verticalMoveSpeed));
} 
else if (Input.GetKeyDown(KeyCode.DownArrow)) 
{ 
    StartCoroutine(MoveVertical(-2.0f, verticalMoveSpeed));
}

// ...

private IEnumerator MoveVertical(float distance, float speed)
{
    var originalY = transform.position.y;
    var targetY = originalY + distance;

    var currentY = originalY; 
    do
    {     
        rb.MovePosition(new Vector 3(transform.position.x, currentY, transform.positiom.z);

        // Update currentY to the next Y position
        currentY = Mathf.Clamp(currentY + speed * Time.deltaTime, originalY, targetY);
        yield return null;
    }
    while(currentY < originalY);

    // make sure you didn't move to much on Y
    rb.MovePosition(new Vector3(transform.position.x, targetY, transform.position,z));
}

有两个选项可以防止并发例程:

  1. 使用标志。这也可以防止例程 interrupted/called twice/called concurrent

    privtae bool isMovingVertical;
    
    // ...
    
    if (Input.GetKeyDown(KeyCode.UpArrow) && !isMovingVertical ) 
    { 
        StartCoroutine(MoveVertical(2.0f, verticalMoveSpeed));
    } 
    else if (Input.GetKeyDown(KeyCode.DownArrow) && !isMovingVertical ) 
    { 
        StartCoroutine(MoveVertical(-2.0f, verticalMoveSpeed));
    }
    
    // ...
    
    private IEnumerator MoveVertical(float distance, float speed)
    {
        isMovingVertical = true;
    
        // ...
    
        isMovingVertical = false;
    }
    
  2. 使用StopAllCoroutines中断运行例程(注意这可能会导致在一个方向上“无限”移动——至少你不会通过额外的检查来阻止它)

    if (Input.GetKeyDown(KeyCode.UpArrow)) 
    { 
        StopAllCoroutines();
        StartCoroutine(MoveVertical(2.0f, verticalMoveSpeed));
    }
    
    if (Input.GetKeyDown(KeyCode.DownArrow)) 
    { 
        StopAllCoroutines();
        StartCoroutine(MoveVertical(-2.0f, verticalMoveSpeed));
    }