当前位置: 首页 > 知识库问答 >
问题:

自定义物理引擎中的AABB与循环冲突

刘才俊
2023-03-14

我已经学习了这个教程:https://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2D-physics-engine-the-basics-and-impulse-resolution-gamedev-6331来创建一个用C#(他几乎所有的工作时间都是错误和不一致的伪C++)的二维物理引擎。但是,当尝试AABB vs Circle collison(下图)时,两个刚体只是粘在一起,缓慢地向一个方向移动。

如果有人能帮助我,我会非常感谢,因为我已经花了几天时间,仍然不知道是什么导致了错误。

如果有人需要我的代码提供更多信息,我很乐意提供。

public static bool AABBvsCircle(ref Collision result) {
        RigidBody AABB = result.a.Shape is AABB ? result.a : result.b;
        RigidBody CIRCLE = result.b.Shape is Circle ? result.b : result.a;

        Vector2 n = CIRCLE.Position - AABB.Position;

        Vector2 closest = n;

        float x_extent = ((AABB)AABB.Shape).HalfWidth;
        float y_extent = ((AABB)AABB.Shape).HalfHeight;

        closest.X = Clamp(-x_extent, x_extent, closest.X);
        closest.Y = Clamp(-y_extent, y_extent, closest.Y);


        bool inside = false;

        if (n == closest) {
            inside = true;

            if (Abs(n.X) > Abs(n.Y)) {
                // Clamp to closest extent
                if (closest.X > 0)
                    closest.X = x_extent;
                else
                    closest.X = -x_extent;
            }

            // y axis is shorter
            else {
                // Clamp to closest extent
                if (closest.Y > 0)
                    closest.Y = y_extent;
                else
                    closest.Y = -y_extent;
            }
        }

        Vector2 normal = n - closest;
        float d = normal.LengthSquared();
        float r = ((Circle)CIRCLE.Shape).Radius;

        // Early out of the radius is shorter than distance to closest point and
        // Circle not inside the AABB
        if (d > (r * r) && !inside)
            return false;

        // Avoided sqrt until we needed
        d = (float)Sqrt(d);

        if (inside) {
            result.normal = -normal / d;
            result.penetration = r - d;
        }
        else {
            result.normal = normal / d;
            result.penetration = r - d;
        }

        return true;
    }

在“碰撞”结构中编辑1碰撞解析方法

public void Resolve() {
        Vector2 rv = b.Velocity - a.Velocity;
        float velAlongNormal = Vector2.Dot(rv, normal);

        if (velAlongNormal > 0)
            return;

        float e = Min(a.Restitution, b.Restitution);

        float j = -(1 + e) * velAlongNormal;
        j /= a.InvertedMass + b.InvertedMass;

        Vector2 impulse = j * normal;
        a.Velocity -= a.InvertedMass * impulse;
        b.Velocity += b.InvertedMass * impulse;

        const float percent = 0.2f; // usually 20% to 80%
        const float slop = 0.01f; // usually 0.01 to 0.1
        Vector2 correction = Max(penetration - slop, 0.0f) / (a.InvertedMass + b.InvertedMass) * percent * normal;
        if (float.IsNaN(correction.X) || float.IsNaN(correction.Y))
            correction = Vector2.Zero;
        a.Position -= a.InvertedMass * correction;
        b.Position += b.InvertedMass * correction;
    }

共有1个答案

戚默
2023-03-14

在对代码逻辑进行任何详细检查之前,我发现了这个潜在的错误:

result.normal=-normal/d;

由于D被设置为Normal.LengthSquared而不是Normal.Length,因此应用的位置校正可能比预期的小(多)或大(多)。鉴于您的对象“粘在一起”,很可能是前者,即d>1

 类似资料:
  • 学过之前的那些章节,你就能做出来一款好玩的小游戏了,可是当你试图做一款复杂的游戏,那游戏需要模拟现实世界的情境,比如模拟两个物体碰撞,模拟物体受到重力,你就不知道该怎么办了。别担心,本章就介绍物理引擎,让我们来探索一下如何合理的使用物理引擎! 是否需要使用物理引擎 当你的需求很简单时,就不要使用物理引擎。比如只需要确定两个对象是否有碰撞,结合使用节点对象的 update 函数和 Rect 对象的

  • 打开编辑器,点击菜单栏中的 项目 -> 项目设置 -> 模块设置,勾选 3D Physics。然后选择合适的 3D 物理引擎,可选项包括 cannon.js 和 Builtin,默认为 cannon.js。若不勾选 3D Physics,则不能使用物理相关的组件和接口,否则会导致运行时出现报错。 注意:预览过程中物理引擎始终为 cannon.js,只有在构建工程时,该选项设置才会生效。 物理引擎(

  • 上下文是我一直在尝试为我的实体设置一个自定义循环引用处理程序,它将影响所有实体。 根据文件(https://symfony.com/doc/current/components/serializer.html#handling-循环引用),我们被引导在文件中的服务下设置值: 我的实际问题是,当序列化程序尝试加载循环引用处理程序时,我的覆盖似乎不存在:显示键引用的图像显示上下文为空 为什么我的超驰装

  • 问题内容: 好的,我从节点服务器获取一个关联数组,并尝试在Jade中进行渲染。我显然需要一个foreach循环,但是似乎没有任何作用!我尝试了这两个代码: 和 我传递的数组称为“行”。知道为什么这不起作用吗?我收到此错误: 并且,使用第二个代码: 问题答案: 尝试

  • 我在反序列化遵循以下格式的Json数组时遇到了一些问题: 它基本上是一个类别数组,其中每个类别也可以有一个子类别列表,依此类推。我的类模型看起来有点像这样: 现在,Gson显然抱怨循环引用。有没有办法解析这个Json输入,因为我不能假设有多少个类别级别?提前感谢。 编辑:以防万一有人有类似的问题,根据Spaeth的回答,我将解决方案调整为使用反射的更一般的情况。唯一的要求是JSON数组表示的对象列