Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unity3d 如何防止对撞机相互碰撞?_Unity3d_Game Physics - Fatal编程技术网

Unity3d 如何防止对撞机相互碰撞?

Unity3d 如何防止对撞机相互碰撞?,unity3d,game-physics,Unity3d,Game Physics,我无法将游戏对象保持在包含的空间内。当它们到达边缘时,会有一些瞬间的推回,但随后它们会直接穿过墙壁 我在播放器上使用一个长方体碰撞器,在关卡的墙上使用一个网格碰撞器。我对玩家角色(太空船)的移动由玩家控制都有问题。还有射弹,它们是以恒定速度发射和移动的 这是我的球员的动作代码。它正在fixeupdate()函数中运行 //Movement haxis = Input.GetAxis("Horizontal") * speed; vaxis = Input.GetAxis("Ver

我无法将游戏对象保持在包含的空间内。当它们到达边缘时,会有一些瞬间的推回,但随后它们会直接穿过墙壁

我在播放器上使用一个长方体碰撞器,在关卡的墙上使用一个网格碰撞器。我对玩家角色(太空船)的移动由玩家控制都有问题。还有射弹,它们是以恒定速度发射和移动的

这是我的球员的动作代码。它正在
fixeupdate()函数中运行

//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);
有了子弹,他们就有了一个速度,引擎就会计算出他们的电影。他们使用的是盒式对撞机,它被设置为一个触发器,所以他们没有物理知识。但是我使用了
OnTriggerEnter
来销毁它们

//Projectiles without physics collisiions
function OnTriggerEnter (other : Collider) {
    Destroy(gameObject);
}

当撞击网格碰撞器壁时,一些但不是所有的子弹将被摧毁。玩家有时会击打它并停下来,但通常可以推开它。如何使每次使用网格碰撞器的碰撞都有效?

如何将刚体的碰撞检测设置为连续连续动态


所以我无法让网格碰撞器工作。我使用简单的长方体碰撞器创建了一个复合碰撞器,它完全按照预期工作

使用简单网格碰撞器进行的其他测试也得出了相同的结果

看起来最好的答案是用简单的盒子/球体碰撞器构建一个复合碰撞器

针对我的具体情况,我编写了一个向导,创建了一个管状复合碰撞器

@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);
        }
    }
}
@script AddComponentMenu(“碰撞器/管道碰撞器”);
类WizardCreatePipeCollider扩展了ScriptableWizard
{
外部公共变量:浮动=200;
公共变量innerRadius:float=190;
公共变量部分:int=12;
公共变量高度:浮动=20;
@MenuItem(“游戏对象/碰撞器/创建管道碰撞器”)
静态函数CreateWizard()
{
ScriptableWizard.DisplayWizard.(“创建管道碰撞器”);
}
公共函数OnWizardUpdate(){
helpString=“创建管道碰撞器”;
}
公共函数OnWizardCreate(){
varθ:浮动=360f/截面;
变量宽度:浮动=外部-内部半径;
可变截面长度:浮点=2*outterRadius*Mathf.Sin((θ/2)*Mathf.Deg2Rad);
var容器:GameObject=newgameobject(“管道碰撞器”);
var部分:游戏对象;
虚拟对撞机:游戏对象;
var boxCollider:boxCollider;
对于(变量i=0;i
与快速移动的物体碰撞始终是一个问题。确保检测到所有碰撞的一个好方法是使用光线投射,而不是依赖物理模拟。这适用于项目符号或小对象,但不会对大对象产生好的效果。

伪代码(我这里没有代码完成和内存不足):


我有一个弹球原型,在同样的领域也给了我很多麻烦。这些是我几乎(但尚未完全)解决这些问题所采取的所有步骤:

对于快速移动的对象:

  • 将刚体的“插值”设置为“插值”(这不会影响实际的物理模拟,但会正确更新对象的渲染-仅从渲染角度对重要对象使用此选项,如球员或弹球,但不用于投射物)

  • 将碰撞检测设置为“连续动态”

  • 将脚本DontGoThroughThings()附加到对象。这个脚本巧妙地使用了我在另一个答案中发布的光线投射解决方案,将有问题的对象拉回到碰撞点之前

在:

  • 将惩罚的最小穿透设置为非常低的值。我已将我的设置为0.001

  • 将解算器迭代计数设置为更高的值。我已经把我的设定为50,但你可能可以用更少的钱来做

所有这些都将在比赛中受到处罚,但这是不可避免的。默认值在性能上是软的,但并非真正用于正确模拟小型和快速移动的对象。

  • 编辑-->项目设置-->时间。。。减少“固定时间步长”值。。这将解决问题,但会对性能产生负面影响

  • 另一个解决方案是计算坐标(例如,你有一个球和一堵墙。球会撞到墙上。所以计算墙的坐标并根据这些坐标设置击球过程)

1.)切勿使用网格碰撞器。使用组合的盒子和胶囊对撞机

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

2.)检查刚体中的约束。如果勾选“冻结位置X”,则它将通过X轴上的对象。(y轴相同)

这是一个老问题,但可能对某人有所帮助

转到“项目设置”>“时间”,然后尝试将固定时间步长和允许的最大时间步长除以2或4


我有一个问题,我的球员能够挤过比球员对撞机小的开口,这就解决了这个问题。它还有助于停止快速移动的对象。

尝试将模型设置为环境和静态。这解决了我的问题