我知道标题不是很解释,但这是我的问题:
我有一个玩家(仅是一个带有刚体,对撞机和移动脚本的立方体),并且我的地板是一个由1乘1的小立方体(带盒对撞机的立方体)组成的地板。
由于某种我不知道的原因,当我的玩家多维数据集掉落并试图与地板水平碰撞时,他只是逐步通过...但是要他像垂直一样,被多维数据集阻塞。任何帮助将不胜感激;)
这是一个立方体对象
此处是玩家对象
这是玩家穿过地板的gif
这是我的c#播放器移动脚本(我知道它很糟糕,但是我希望将其放在此处,以防它与我的问题有关):
void ApplyMovement()
{
transform.position += new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
}
如果您需要更多信息来帮助我,请告诉我,我会尽快提供。
答案 0 :(得分:0)
我重新创建了您最后描述的场景。我将您的“ ApplyMovement”代码放在“更新”中。我基本上可以重现您的结果。
在我看来,问题可能出在播放器上冻结X / Z位置。我认为既然这样做了,您就是在告诉刚体组件,不允许将对象的X / Z位置修改为碰撞分辨率和物理模拟的一部分。当我关闭这两个功能时,我得到的结果(我认为)更接近您的期望。
请注意:您的“ ApplyMovement”代码是锁定帧的,这意味着您的播放器将以不同的速度以不同的帧速率移动。要解决此问题,您需要将Input.GetAxis值乘以Time.deltaTime。
此外,如果您的玩家移动得太快,它仍然能够通过碰撞并导致奇怪的行为,因此请确保将玩家的最大移动速率限制在某个合理的值。
答案 1 :(得分:0)
您应该对角色的Rigidbody
施加力,而不要直接操纵transform.position
(这将阻止物理引擎解决碰撞)。您还将冻结Rigidbody
上的X和Z位置;您不希望这样做,因为它完全阻止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
别忘了这应该在FixedUpdate()
而不是Update()
中发生(所有物理操作应在FixedUpdate()
中完成)
请注意,您的刚体还有可能仍然移动得太快并互相穿过。即使在使用力和速度时,这也是可能的,因此,如果您遇到这种情况,请调查Collision Detection Modes。 TLDR;它们是性能与准确性之间权衡的设置。
答案 2 :(得分:0)
的值
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中的示例。
在处理RigidBody
时,切勿直接更改transform.position
(和rotation
)!
如果您将想使RigidBody
跳到某个位置,而不要使用
rigidBody.position = transform.position + ...;
不过,您想要的是平稳移动,以保持碰撞检测完好无损。因此,您应该改用RigidBody.MovePosition
rigidBody.MovePosition(transform.position + ...);
您不必对付武力等。
还向地板对象添加一个RigidBody
组件。即使对象没有移动,这也可以改善碰撞检测(以物理引擎为代价)。而且由于对象不应该移动集合
您还可以设置freeze position
和freeze rotation
。
在楼层和播放器对象上均设置Collision Detection
-> Continous Dynamic
。
这样可以改善碰撞检测,并在帧之间查找碰撞。
但是请注意,动态检测非常昂贵,因此只有在对象过快时仍然有问题时才使用它。
在播放器上,您可能还希望使用interpolate
。
最后
请注意,连续碰撞检测旨在作为一种安全网,以防万一物体相互之间通过而无法传递物理上准确的碰撞结果,因此您仍可以考虑在TimeManager检查器 如果您遇到快速移动物体的问题,则可以使仿真更加精确。
有关更多信息,请参见RigidBody manual和Colliders manual