我无法将游戏对象保留在包含的空间内。当它们到达边缘时,会有一些瞬间推回,但随后它们将穿过墙壁。
我在玩家上使用了Box Collider,在水平墙上使用了Mesh Collider。我对玩家角色(太空飞船)的问题表明该运动是由玩家控制的。并且使用射弹,它们会发射并且忘记以恒定的速度移动。
这是我的播放器的移动代码。它正在FixedUpdate()
函数中运行。
//Movement
haxis = Input.GetAxis("Horizontal") * speed;
vaxis = Input.GetAxis("Vertical") * speed;
moveVector.x = haxis;
moveVector.z = vaxis;
if(moveVector.magnitude > 1)
{
moveVector.Normalize();
}
rigidbody.MovePosition(transform.position + moveVector * speed);
使用子弹,他们会获得一个速度,引擎会计算他们的电影。他们正在使用Box Collider并将其设置为Trigger,因此他们没有物理。但我用OnTriggerEnter
来摧毁它们。
//Projectiles without physics collisiions
function OnTriggerEnter (other : Collider) {
Destroy(gameObject);
}
撞击网格对撞墙时,有些但不是所有的子弹都会被摧毁。玩家有时会击中并停止,但通常可以通过它。如何每次都使用网格对撞机进行碰撞?
答案 0 :(得分:12)
我有一个弹球原型,在同样的领域也给了我很多麻烦。这些是我几乎(但尚未完全)解决这些问题的所有步骤:
对于快速移动的物体:
将刚体的插值设置为'插值'(这不会影响实际的物理模拟,但会正确更新对象的渲染 - 仅在渲染的角度使用此对象,如播放器,或弹球,但不是弹丸)
将碰撞检测设置为连续动态
将脚本DontGoThroughThings(https://www.auto.tuwien.ac.at/wordpress/?p=260)附加到您的对象。这个脚本巧妙地使用我在其他答案中发布的Raycasting解决方案,在碰撞点之前将有问题的对象拉回来。
在Edit -> Project Settings -> Physics中:
将Penalty的Min Penetration设置为非常低的值。我把我的设定为0.001
将Solver Iteration Count设置为更高的值。我把我的定为50,但你可以用更少的东西做好。
所有这些都将在性能上受到惩罚,但这是不可避免的。默认值在性能上是软的,但并不是真正用于正确模拟小型和快速移动的对象。
答案 1 :(得分:10)
与快速移动的物体碰撞始终是个问题。确保检测到所有碰撞的好方法是使用Raycasting而不是依赖于物理模拟。这适用于项目符号或小对象,但不会为大型对象产生良好的结果。 http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html
伪编码(我这里没有代码完成和内存不足):
void FixedUpdate()
{
Vector3 direction = new Vector3(transform.position - lastPosition);
Ray ray = new Ray(lastPosition, direction);
RaycastHit hit;
if (Physics.Raycast(ray, hit, direction.magnitude))
{
// Do something if hit
}
this.lastPosition = transform.position;
}
答案 2 :(得分:6)
如何将刚体的碰撞检测设置为连续或连续动态?
http://unity3d.com/support/documentation/Components/class-Rigidbody.html
答案 3 :(得分:1)
所以我无法让Mesh Colliders工作。我使用简单的盒子碰撞器创建了一个复合碰撞器,它的工作方式完全符合预期。
使用简单网格碰撞器进行的其他测试也是如此。
看起来最好的答案是用简单的盒子/球体碰撞器构建复合对撞机。
对于我的具体案例,我写了一个创建管状复合对撞机的向导。
@script AddComponentMenu("Colliders/Pipe Collider");
class WizardCreatePipeCollider extends ScriptableWizard
{
public var outterRadius : float = 200;
public var innerRadius : float = 190;
public var sections : int = 12;
public var height : float = 20;
@MenuItem("GameObject/Colliders/Create Pipe Collider")
static function CreateWizard()
{
ScriptableWizard.DisplayWizard.<WizardCreatePipeCollider>("Create Pipe Collider");
}
public function OnWizardUpdate() {
helpString = "Creates a Pipe Collider";
}
public function OnWizardCreate() {
var theta : float = 360f / sections;
var width : float = outterRadius - innerRadius;
var sectionLength : float = 2 * outterRadius * Mathf.Sin((theta / 2) * Mathf.Deg2Rad);
var container : GameObject = new GameObject("Pipe Collider");
var section : GameObject;
var sectionCollider : GameObject;
var boxCollider : BoxCollider;
for(var i = 0; i < sections; i++)
{
section = new GameObject("Section " + (i + 1));
sectionCollider = new GameObject("SectionCollider " + (i + 1));
section.transform.parent = container.transform;
sectionCollider.transform.parent = section.transform;
section.transform.localPosition = Vector3.zero;
section.transform.localRotation.eulerAngles.y = i * theta;
boxCollider = sectionCollider.AddComponent.<BoxCollider>();
boxCollider.center = Vector3.zero;
boxCollider.size = new Vector3(width, height, sectionLength);
sectionCollider.transform.localPosition = new Vector3(innerRadius + (width / 2), 0, 0);
}
}
}
答案 4 :(得分:1)
编辑---&gt;项目设置---&gt;时间......减少&#34;固定时间步&#34;这将解决问题,但会对性能产生负面影响。
另一个解决方案是可以计算坐标(例如,你有一个球和墙。球将撞到墙上。所以计算墙的坐标并根据这些坐标设置击球过程)
答案 5 :(得分:1)
旧问题,但也许对某人有帮助。
转到项目设置&gt;时间并尝试将固定时间步长和最大允许时间步长除以2或4。
我遇到的问题是我的球员能够通过小于球员对撞机的开口挤出并解决了它。它还有助于阻止快速移动的物体。
答案 6 :(得分:0)
1。)切勿使用MESH COLLIDER。使用盒子和胶囊对撞机的组合。
2.)检查RigidBody中的约束。如果勾选冻结位置X,它将通过X轴上的对象。 (y轴相同)。
答案 7 :(得分:0)
尝试将模型设置为环境和静态。那解决了我的问题。