首页 文章

如何防止对手穿过对方?

提问于
浏览
13

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

我在玩家身上使用了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);
}

击中网眼对撞墙时,有些但不是所有的子弹都会被摧毁 . 玩家有时会击中并停止,但通常可以通过它 . 如何每次都与网格对撞机碰撞?

7 回答

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

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

  • 0

    所以我无法让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);
            }
        }
    }
    
  • 0

    老问题,但也许它可以帮助某人 .

    转到项目设置>时间并尝试将固定时间步长和最大允许时间步长除以2或4 .

    我遇到的问题是我的球员能够通过比球员对撞机小的开口挤压而且解决了它 . 它还有助于阻止快速移动的物体 .

  • 6

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

    对于快速移动的物体:

    • 将刚体的插值设置为'插值'(这不会影响实际的物理模拟,但会正确更新对象的渲染 - 仅在渲染视角的重要对象上使用它,如播放器或弹球,但不适用于射弹)

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

    • 将脚本DontGoThroughThings(https://www.auto.tuwien.ac.at/wordpress/?p=260)附加到您的对象 . 这个脚本巧妙地使用我在其他答案中发布的Raycasting解决方案,在碰撞点之前将有问题的对象拉回来 .

    Edit -> Project Settings -> Physics

    • 将Penalty的Min Penetration设置为非常低的值 . 我把我的设定为0.001

    • 将Solver Iteration Count设置为更高的值 . 我把我的设定为50,但你可以用更少的东西做好 .

    所有这一切都将在性能上受到惩罚,但这是不可避免的 . 默认值在性能上是软的,但并不是真正用于正确模拟小型和快速移动的对象 .

  • 10

    如何将刚体的碰撞检测设置为 ContinuousContinuous Dynamic

    http://unity3d.com/support/documentation/Components/class-Rigidbody.html

  • 12

    与快速移动的物体碰撞总是一个问题 . 确保检测到所有碰撞的一种好方法是使用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;
    }
    
  • 1

    1.)切勿使用MESH COLLIDER . 使用盒子和胶囊对撞机的组合 .

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

相关问题