预知断言失败

本文关键字:失败 断言 | 更新日期: 2023-09-27 18:08:32

我们正在为学校项目创造一款游戏。这是一款2D平台游戏,还处于早期阶段。我们使用c#/XNA,我们正在实现Farseer物理引擎。我现在正在努力学习地图课。在类中,我们有一个DrawableGameObjects的列表,我们存储地图的每个贴图并绘制它们。但是当我们尝试绘制它们时,我们得到一个"断言失败"。进一步研究这个问题,我得出的结论是,每当我们试图向世界添加更多静态物体时(即使没有绘制它们),我们都会遇到这种失败。把消息

Game1.cs:line 210 is:

world.Step(0.033333f);

和Program.cs:第15行是

game.Run();
下面是Map类的代码:
class Map
{
    private List<DrawableGameObject> ground = new List<DrawableGameObject>();
    public Map(World world, Texture2D texture)
    {
        for (int i = 0; i < 32; i++)
        {
            DrawableGameObject floor = new DrawableGameObject(world, texture, new Vector2(40, 40), 100, "ground");
            floor.Position = new Vector2(i * 40, 500);
            floor.body.BodyType = BodyType.Static;
            ground.Add(floor);
        }
    }
    public void Draw(SpriteBatch spriteBatch){
        foreach (DrawableGameObject dgo in ground)
            dgo.Draw(spriteBatch);
    }
}

任何想法?我已经在Farseer的论坛上发布了这个问题,但是他们还没有很有帮助…

预知断言失败

这是Farseer中的一个bug。 (Version 3.3.1)

我打开了Farseer源代码的问题(World.SolveTOI)的方法,发现两个调用Debug.Assert。事实上,在我的代码副本中,我已经遇到了这个bug,并注释了其中一个,特别是:

Debug.Assert(typeA == BodyType.Dynamic || typeB == BodyType.Dynamic);

基本上它不想尝试处理两个静态体之间的接触。

幸运的是,下面的代码实际上检查了本质上相同的条件,如果是这种情况,continue将循环:

bool awakeA = bA.Awake && typeA != BodyType.Static;
bool awakeB = bB.Awake && typeB != BodyType.Static;
// Is at least one body awake?
if (awakeA == false && awakeB == false)
{
    continue;
}

因此,简单地注释掉或删除断言是相当安全的。(当然,您应该从源代码构建Farseer -它使生活更容易。)


要重现Farseer bug:有两个静态体和一个与两者都接触的动态体,然后将动态体设置为静态。assert将触发。

assert在联系人处理循环中。通常一对静力物体不会产生接触。但是如果一个body开始是动态的,可以创建联系人——当body被设置为静态时,它们不会被删除。