【问题标题】:How to move rigidbody object up or down smoothly in unity3d如何在unity3d中平滑地向上或向下移动刚体对象
【发布时间】:2019-06-14 13:20:59
【问题描述】:

我已经开始了一个项目,并在我的播放器上附加了一个刚体以对其施加一些力。所以当我运行我的项目时,然后在 FixedUpdate() 函数中我对播放器施加一个力以使其向前移动。所以当我按下左箭头或右箭头它执行“倾斜”意味着旋转它的翅膀。 但是现在我想通过按 Uparrow 或 Downarrow 平滑地向上或向下移动我的播放器,当我同时按下 uparrow 和 downarrow 时,它必须对播放器产生影响。 这是我的代码。请帮助我。 :(

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 
      }


}

【问题讨论】:

  • 所以你的代码差不多完成了。你有你的速度。使用速度量 * Time.Delta per Update 更改您的坐标
  • 我不专业,不知道怎么改坐标,能不能在这里写点代码?

标签: c# unity3d smoothing rigid-bodies


【解决方案1】:

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

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

使用 Rigidbody.MovePosition 移动刚体,符合刚体的插值设置。

如果在刚体上启用刚体插值,则调用 Rigidbody.MovePosition 会导致任何中间帧中两个位置之间的平滑过渡。如果您想在每个 FixedUpdate 中连续移动刚体,则应使用此选项。

如果您想将刚体从一个位置传送到另一个位置,而不渲染中间位置,请改为设置 Rigidbody.position。

因此,您可以看到,根据您的设置,使用 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. 使用标志。这也可以防止例程被中断/调用两次/调用并发

    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));
    }
    

【讨论】:

  • 谢谢先生,您的回答已经解决了我 90% 的问题。但是还有一个小问题,我希望当我按下 Uparrow 时,我的播放器向上移动并停在特定位置。例如,我的播放器当前位置是 5,我想将它移动到 7 并且当它到达时7 然后它应该停止向上移动。
  • 您可以存储原始的 position.Y 值,然后停止例程,例如已达到originalY + 2.0foriginalY - 2.0f
  • 先生,我试过了,但我没有在确切的位置停止它。有时它会向上或向下移动一点,你能写一些确切的代码来停止它吗?
  • @FaisalmirzaMirza 您选择了哪种解决方案?
  • 我选择了您使用 startcoroutine() 的解决方案。
猜你喜欢
  • 1970-01-01
  • 2020-04-06
  • 1970-01-01
  • 2020-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-20
  • 1970-01-01
相关资源
最近更新 更多