【问题标题】:3d Wall sliding collision3d墙滑动碰撞
【发布时间】:2013-08-18 21:57:57
【问题描述】:

我正在处理我的游戏中的墙壁碰撞问题,而我目前的方式是我在走进墙壁时卡住了。我试图让我的角色在墙上滑动,但仍然会发生碰撞。

我的角色离开了我使用他所面对的角度创建的矢量。

这是我的碰撞函数:

    private static bool CheckForCollisions(ref Crate c1, ref Player c2,bool direction)
    {
        for (int i = 0; i < c1.model.Meshes.Count; i++)
        {
            // Check whether the bounding boxes of the two cubes intersect.
            BoundingSphere c1BoundingSphere = c1.model.Meshes[i].BoundingSphere;
            c1BoundingSphere.Center += c1.position + new Vector3(2, 0, 2);
            c1BoundingSphere.Radius = c1BoundingSphere.Radius / 1.5f;

            for (int j = 0; j < c2.model.Meshes.Count; j++)
            {
                BoundingSphere c2BoundingSphere = c2.model.Meshes[j].BoundingSphere;
                if (direction)
                    c2BoundingSphere.Center += c2.position + new Vector3(c2.getPlannedDirection().X, 0, 0);
                else if (!direction)
                    c2BoundingSphere.Center += c2.position + new Vector3(0, 0, c2.getPlannedDirection().Y);
                //c2BoundingSphere.Center += c2.position;

                if (c1BoundingSphere.Intersects(c2BoundingSphere))
                {
                    return true;
                }
            }
        }
        return false;
    }

这是我的更新:

for (int x = 0; x <= 29; x++)
        {
            for (int y = 0; y <= 29; y++)
            {
                if (crate[x, y].getType() == 11 && collisionEnabled)
                { 
                    if (CheckForCollisions(ref crate[x, y], ref player,true))
                    {
                        player.clearPlannedDirectionX();
                        //Console.Write(player.getPosition().X + "," + player.getPosition().Y + "," + player.getPosition().Z);
                        //movePlayer = false;
                    }
                    if (CheckForCollisions(ref crate[x, y], ref player,false))
                    {
                        player.clearPlannedDirectionZ();
                        //Console.Write(player.getPosition().X + "," + player.getPosition().Y + "," + player.getPosition().Z);
                        //movePlayer = false;
                    }
                }
            }
        }

【问题讨论】:

  • 您在第一个代码中使用 getPlannedDirection().X 和 getPlannedDirection().Y,但您在第二个代码中使用 clearPlannedDirectionX() 和 clearPlannedDirectionZ()
  • 是的,它所做的是如果它会在 z 轴上发生碰撞,那么它会阻止它发生。与 x 轴相同。这都是在玩家更新其位置之前运行的。这就是为什么它被称为“PlannedDirection”,对不起,我应该在我的问题中澄清这一点。

标签: c# 3d xna collision


【解决方案1】:

这看起来应该在 gamedev 堆栈交换中,我建议切换到射线测试而不是球体。

无论如何,如果您与基于球体的系统结婚,则可以改为将玩家“推”出墙外:

private static bool CorrectCollisions(ref Crate c1, ref Player c2)
{
    for (int i = 0; i < c1.model.Meshes.Count; i++)
    {
        // Check whether the bounding boxes of the two cubes intersect.
        BoundingSphere c1BoundingSphere = c1.model.Meshes[i].BoundingSphere;

        c1BoundingSphere.Center += c1.position + new Vector3(2, 0, 2);
        c1BoundingSphere.Radius = c1BoundingSphere.Radius / 1.5f;

        for (int j = 0; j < c2.model.Meshes.Count; j++)
        {
            BoundingSphere c2BoundingSphere = c2.model.Meshes[j].BoundingSphere;
            c2BoundingSphere.Center += c2.position;

            Vector3 dir=c2BoundingSphere.Center - c1BoundingSphere.Center;
            float center_dist_sq=dir.dot(dir);
            float min_dist=c2BoundingSphere.Radius+c1BoundingSphere.Radius;
            if (center_dist_sq < min_dist*min_dist) {
                    dir.normalize();
                    c2.position += dir*(min_dist-sqrt(center_dist_sq));
            }
        }
    }
    return false;
} 

那么您的更新可能看起来更像:

for (int x = 0; x <= 29; x++) {
    for (int y = 0; y <= 29; y++) {
        if (crate[x, y].getType() == 11 && collisionEnabled) {
            CorrectCollisions(ref crate[x, y], ref player);
        }
    }
}

我不确定 (2,0,2) 向量或 2/3rds 的用途是什么......我只是忽略了它们来表达这个概念

【讨论】:

  • c2.position += (c2BoundingSphere.Center - c1BoundingSphere.Center)-(c2BoundingSphere.Radius - c1BoundingSphere.Radius); “不能将 Vector3 转换为浮动。第二个减号应该是逗号吗?
  • 哎呀,对不起,我应该想到这一点。这是因为我在 1D 中设计了这个想法。我已经编辑了示例以展示如何在 3D 中提取方向矢量。由于数学重叠,我还结合了球体交集,没有用两次。
  • 在这一行:float center_dist_sq=dir.dot(dir); DOT 产品不需要两个 Vector3 吗?
  • @bbdude95 :是的,它们是“dir”和“dir”,注意变量称为中心距离平方。我最初将它写为 =dot(dir,dir) 但意识到您的框架看起来是面向对象的。
  • 哟我试图在没有任何矢量库的 JavaScript 中实现类似的东西,知道如​​何解决这个问题吗? stackoverflow.com/questions/61518457/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-06
  • 2013-01-31
  • 2023-03-25
  • 2016-10-26
  • 1970-01-01
相关资源
最近更新 更多