首页 > 解决方案 > 在给定力时计算 FixedUpdate 中的未来速度,并计算它是否对当前速度为负

问题描述

我在一个物体上使用相对力。这个想法是

我要解决的问题是,当向下箭头按下到足以使对象最终减速时,我需要对象停止并且不改变方向。

简而言之,我需要做的是,FixedUpdate如果物体的速度(或方向)对运动的方向(或速度)是负的,那么我需要做的是通过计算。这似乎是可能的,但是我不确定正确的计算AddForce用途。

我的猜测是我需要使用一些计算和Vector3.Dot方法

两个向量的点积。

点积是一个浮点值,等于两个向量的大小相乘,然后乘以它们之间夹角的余弦值。

像这样的东西

var future = (forward) * _body.velocity.magnitude * _body.mass;

但是,我不确定需要什么。

给定

private Rigidbody _body;

public float Speed;

物理计算

private void FixedUpdate()
{

  // get the controls
  var hAxis = Input.GetAxis("Horizontal");
  var vAxis = Input.GetAxis("Vertical");

  if (_body.velocity == Vector3.zero)
  {
     // this is just to give some forward moment when stationary
     // this will change at some stage and not my problem
     var movement = new Vector3(hAxis, 0.0f, vAxis);
     if (vAxis > 0)
        _body.AddForce(movement * Speed);
  }
  else
  {

     // get the direction we are traveling
     var direction = _body.velocity.normalized;

     // calculate the vertical force from the controls
     var forward = direction * vAxis * Speed;

     // Calculate the side force from teh controls
     var side = Vector3.Cross(direction, Vector3.up) * hAxis * -1f * Speed;

     // This is equation is wrong. 
     var future = (forward) * _body.velocity.magnitude * _body.mass;

     // what I am trying to say, is if the future velocity is negative
     // i.e the user has pressed the back arrow so much it will go backwards
     // then I want to come to a dead stop, and not apply any backwards force
     if (Vector3.Dot(direction, future.normalized) < 0)
     {
        _body.velocity = Vector3.zero;         
        return;
     }

     _body.AddForce(forward + side);
  }
}

标签: c#unity3d

解决方案


我不是真正的物理专业人士,但我会尽力而为;)

您可以在更新FixedUpdate后的下一次调用 so时进行钳制_body.velocity

public Rigidbody _body;
public float Speed;

// store the last forward direction
private Vector3 lastForward;

private void FixedUpdate()
{
    // Check and clamp the current velocity against the last one
    // so after forces from last call have been applied
    if (Vector3.Dot(lastForward, _body.velocity.normalized) < 0)
    {
        Debug.Log("Clamped negative");
        _body.velocity = Vector3.zero;
    }

    lastForward = _body.velocity.normalized;

    var hAxis = Input.GetAxis("Horizontal");
    var vAxis = Input.GetAxis("Vertical");

    // == for Vector3 has only a precision of 0.00001
    // to be sure you coul use this instead
    if (Mathf.Approximately(_body.velocity.magnitude, 0))
    {
        if (vAxis > 0) _body.AddForce(new Vector3(hAxis, 0.0f, vAxis) * Speed);
    }
    else
    {
        var forwardForce = Speed * vAxis * lastForward;
        var sideForce = Speed * hAxis * -1f * Vector3.Cross(lastForward, Vector3.up);

        _body.AddForce(forwardForce + sideForce);
    }
}

或者我猜你可以用什么沉浸式来代替自己AddForce直接计算力velocity

public Rigidbody _body;
public float Speed;

private void FixedUpdate()
{
    var currentVelocity = _body.velocity;
    var currentDirection = currentVelocity.normalized;

    var hAxis = Input.GetAxis("Horizontal");
    var vAxis = Input.GetAxis("Vertical");

    if(Mathf.Approximately(_body.velocity.magnitude, 0))
    {
        // Directly calculating the velocity as Immersive said:
        // newVelocity = currentVelocity + Time.deltaTime * Force / Mass
        // where Force = direction * Speed
        // 
        // Ofcourse you could also just use AddForce for this case but
        // just for consistency I would use the same method for both cases
        if(vAxis>0) _body.velocity += new Vector3(hAxis, 0.0f, vAxis) * (Time.deltaTime * Speed / _body.mass);
    }
    else
    {
        var forwardForce = Speed * vAxis * currentDirection;
        var sideForce = Speed * hAxis * -1f * Vector3.Cross(currentDirection, Vector3.up);

        // calculate the future velocity directly without using AddForce
        // (see comment above)
        var newVelocity = currentVelocity + (forwardForce + sideForce) * (Time.deltaTime / _body.mass);

        // Only use this velocity if the new direction is still forward
        // otherwise stop
        _body.velocity = Vector3.Dot(currentVelocity, newVelocity) < 0 ? Vector3.zero : newVelocity;
    }
}

到达PC并立即对其进行测试;)两者都应该基本上可以工作

AddForce在下一次通话中使用和钳制

在此处输入图像描述

使用计算velocity

在此处输入图像描述


推荐阅读