关于C#:如何在Unity3D中平稳地上下移动刚体对象

How to move rigidbody object up or down smoothly in unity3d

我已经启动了一个项目,并在播放器上附加了刚体以对其施加一些力。因此,当我运行项目时,在FixedUpdate()功能中,我会向播放器施加力以使其向前移动。我按向左箭头或向右箭头执行"倾斜",即旋转翅膀。
但是现在我想通过按Uparrow或Downarrow平稳地上下移动播放器,当我同时按下Uparrow和Downarrow时,这一定会对播放器产生影响。
这是我的代码。请帮助我。 :(

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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和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可能已经导致"平滑"运动。

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

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

那样被连续调用

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 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触发移动,也可以执行类似

的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 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
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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;
    }
  • 使用StopAllCoroutines中断正在运行的例程(注意这可能会导致"无限"向一个方向移动-至少在没有通过其他检查阻止它的情况下)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    if (Input.GetKeyDown(KeyCode.UpArrow))
    {
        StopAllCoroutines();
        StartCoroutine(MoveVertical(2.0f, verticalMoveSpeed));
    }

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