📜  如何统一检测碰撞 - C# (1)

📅  最后修改于: 2023-12-03 15:09:14.004000             🧑  作者: Mango

如何统一检测碰撞 - C#

在游戏开发中,检测碰撞是一个常见的需求。C#提供了多种检测碰撞的方法,但是在不同的场景下,需要使用不同的方法来实现。本文主要介绍如何通过代码实现统一的碰撞检测系统。

定义碰撞体

首先需要定义碰撞体的数据结构。碰撞体通常由一个形状和位置组成。C#提供了Unity提供的多种形状,比如BoxCollider、SphereCollider、CapsuleCollider等等。这里为了简单起见,我们只考虑二维矩形碰撞体,定义如下:

public struct RectCollider
{
    public Vector2 position;
    public float width, height;

    public Vector2 min
    {
        get { return position - new Vector2(width, height) * 0.5f; }
    }

    public Vector2 max
    {
        get { return position + new Vector2(width, height) * 0.5f; }
    }

    public bool Intersects(RectCollider other)
    {
        return !(max.x < other.min.x || min.x > other.max.x || max.y < other.min.y || min.y > other.max.y);
    }
}

上述代码中的RectCollider包含一个position字段表示碰撞体位置,width和height表示碰撞体的宽度和高度。还包含了min和max方法返回碰撞体左下角和右上角的坐标,用于后面的碰撞检测。最后还有Intersects方法用于检测两个碰撞体是否相交,如果相交则返回true。

定义碰撞事件

接下来需要定义碰撞事件,即当两个碰撞体相交时所触发的事件。该事件需要携带被碰撞的物体的信息,因此需要定义一个包含碰撞体和物体信息的结构体,如下:

public struct CollisionInfo
{
    public RectCollider collider;
    public GameObject gameObject;

    public CollisionInfo(RectCollider collider, GameObject gameObject)
    {
        this.collider = collider;
        this.gameObject = gameObject;
    }
}

对于碰撞事件的处理方法,可以采用委托来实现。定义一个委托类型CollisionHandler和一个调用该委托的方法HandleCollision,如下:

public delegate void CollisionHandler(CollisionInfo info);

public static void HandleCollision(CollisionInfo info, CollisionHandler handler)
{
    handler?.Invoke(info);
}

该方法接受一个CollisionInfo参数和一个CollisionHandler委托,如果委托非空,则调用该委托并传递CollisionInfo参数。

碰撞检测系统

现在可以定义一个碰撞检测系统来实现统一的碰撞检测。定义一个静态类CollisionDetection,包含一个碰撞检测方法CheckCollisions和一个委托类型CollisionHandler,如下:

public static class CollisionDetection
{
    public delegate void CollisionHandler(CollisionInfo info);

    public static void CheckCollisions(RectCollider[] colliders, CollisionHandler handler)
    {
        for (int i = 0; i < colliders.Length; i++)
        {
            for (int j = i + 1; j < colliders.Length; j++)
            {
                if (colliders[i].Intersects(colliders[j]))
                {
                    HandleCollision(new CollisionInfo(colliders[i], null), handler);
                    HandleCollision(new CollisionInfo(colliders[j], null), handler);
                }
            }
        }
    }
}

该方法接受一个RectCollider数组和一个委托类型CollisionHandler。它遍历所有的碰撞体,并检测它们之间是否相交,如果相交则调用HandleCollision方法触发碰撞事件。

使用碰撞检测系统

在游戏中,可以通过添加碰撞体和注册碰撞事件来使用碰撞检测系统。例如,在场景中添加一个矩形碰撞体并注册碰撞事件:

public class ExampleObject : MonoBehaviour
{
    public RectCollider collider;

    void Update()
    {
        CollisionDetection.HandleCollision(new CollisionInfo(collider, gameObject), OnCollision);
    }

    void OnCollision(CollisionInfo info)
    {
        Debug.Log("Collision detected with " + info.gameObject.name);
    }
}

在Update方法中,通过调用HandleCollision方法来检测当前物体的碰撞事件。如果有碰撞事件发生,则会调用OnCollision方法。事实上,也可以将碰撞检测放置到FixedUpdate中,以便更精准地控制碰撞检测的时间。

总结

本文介绍了如何通过C#实现统一的碰撞检测系统,包括定义碰撞体、碰撞事件和碰撞检测系统。使用这个碰撞检测系统能够简化游戏开发中的碰撞检测流程,而不用针对每个物体都实现繁琐的碰撞检测逻辑。