0

我知道标题不是很解释,但这是我的问题:

我有一个玩家(只是一个带有刚体、对撞机和运动脚本的立方体),我有一个由 1 x 1 x 1 的小立方体(带有盒子碰撞器的立方体)组成的地板。

出于某种我不知道的原因,当我的玩家立方体掉落并试图与地板水平碰撞时,他只是逐步通过......但希望他像垂直一样被立方体阻挡。任何帮助将不胜感激 ;)

这是场景的样子

这是一个立方体对象

这是玩家对象

这是玩家穿过地板的 GIF

这是我的 c# 玩家移动脚本(我知道它非常糟糕,但我更喜欢把它放在这里以防它与我的问题有关):

void ApplyMovement()
{        

 transform.position += new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));

}

如果您需要更多信息来帮助我,请告诉我,我会尽快提供。

4

3 回答 3

1
  1. 的价值

    new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"))
    

    是取决于帧率的。这意味着帧速率越快,对象移动的速度就越快。这通常不是你想要的。而是使用Time.deltaTime

    // Adjust the speed in the inspector
    public float speedMultiplicator = 1;
    
    //...
    
    new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * speedMultiplicator * Time.deltaTime
    

    获得与帧率无关的运动。另请参阅Input.GetAxis中的示例。

  2. 处理时RigidBody永远不要直接更改transform.position(和rotation)!

    如果您跳转到RigidBody某个位置,请使用

    rigidBody.position = transform.position + ...;
    

    但是,您想要的是平稳的运动,以保持碰撞检测的完整性。所以你应该改用RigidBody.MovePosition

    rigidBody.MovePosition(transform.position + ...);
    

    您不必处理武力等。

  3. 还将组件添加RigidBody到地板对象。即使对象没有移动,这也会提高碰撞检测(当然以物理引擎的性能为代价)。而且由于对象不应该移动设置

    • isKinematic -> 真
    • 使用重力->假

    您还可以设置freeze positionfreeze rotation

  4. 在地板和玩家对象上设置Collision Detection-> Continous Dynamic
    这改进了碰撞检测并且还在帧之间寻找碰撞。
    但是请注意,动态检测非常昂贵,因此只有在对象太快仍然存在问题时才使用它。

  5. 在您可能还想使用的播放器上interpolate

  6. 最后

    请注意,连续碰撞检测旨在作为一个安全网,以在对象相互穿过的情况下捕获碰撞,但不会提供物理上准确的碰撞结果,因此您仍可以考虑减少 TimeManager 检查器中的固定时间步长值以如果您遇到快速移动物体的问题,请使模拟更加精确。

有关更多信息,请参阅RigidBody 手册Colliders 手册

于 2019-01-25T05:37:40.030 回答
0

我重新创建了您最后描述的场景。我将您的“ApplyMovement”代码放在“更新”中。我基本上能够重现你的结果。

在我看来,问题可能是在播放器上冻结位置 X/Z。我认为既然你这样做了,你就是在告诉刚体组件,作为碰撞分辨率和物理模拟的一部分,不允许修改对象的 X/Z 位置。当我关闭这两个时,我得到的结果(我认为)更接近你正在寻找的结果。

请注意:您的“ApplyMovement”代码是帧锁定的,这意味着您的播放器将以不同的帧速率以不同的速度移动。要解决这个问题,您需要将 Input.GetAxis 值乘以 Time.deltaTime。

此外,如果您的玩家移动得太快,它仍然能够通过碰撞并导致奇怪的行为,因此请务必将玩家的最大移动速率限制在某个合理的值。

于 2019-01-25T03:46:05.030 回答
0

您应该Rigidbody对角色施加力,而不是直接操纵transform.position(这会阻止物理引擎解决碰撞)。您还冻结了 ; 上的 X 和 Z 位置Rigidbody。你不希望这样,因为它完全阻止了Rigidbody操纵这些值。

而不是transform.postion += ...首先获取对Rigidbody脚本中某处的引用(最好在Awake()方法中完成):

private Rigidbody _body;
private void Awake() {
    _body = GetComponent<Rigidbody>();
}

然后确保从您的输入构建的向量被应用于对象的“运动”,而不是它的位置:

Vector3 inputVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
// You can multiply this vector by a float to adjust "speed"

_body.ApplyForce(inputVector, ForceMode.VelocityChange);

最后,您应该阅读不同的ForceMode选项并决定哪一个适合您的偏好:https ://docs.unity3d.com/ScriptReference/ForceMode.html

不要忘记这应该发生在 a 中FixedUpdate(),而不是 an Update()(所有物理操作都应该在 中完成FixedUpdate()


附带说明一下,您的刚体仍有可能向上移动过快并相互穿过。即使您使用力和速度,这也是可能的,因此如果您遇到这种情况,请调查Collision Detection Modes。TLDR;它们是性能与准确性权衡的设置。

于 2019-01-25T03:51:24.043 回答