前言
在游戏制作过程中会经常遇到碰撞检测,假设在二维平面上有n个物体,那么检测每个物体的碰撞都要检测n-1次,如果要检测所有物体的碰撞,那么需要计算n*(n-1)/2次,时间复杂度为n的平方,四叉树算法可以将物体分到不同的区域,从而减少计算次数。关于四叉树 的概念可以参考文章四叉树与八叉树
四叉的实现
下面是用C#代码实现的四叉树算法,需要注意的是构造函数的pBounds参数,不能直接使用RectTransform.rect,这里使用的rect的参数x和y需要特殊处理,具体可以看末尾函数public static Rect GetRect(RectTransform rectTransform)。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class QuadTree
{
//节点内允许的最大对象
private int MAX_OBJECTS = 1;
//最大层级
private int MAX_LEVELS = 3;
//当前层级
private int level;
//当前层级内的对象
public List<RectTransform> rectTrans;
//rect范围
private Rect bounds;
//子节点
private List<QuadTree> childs;
public QuadTree(Rect pBounds, int pLevel = 0, int maxObjs = 1, int maxLevel = 3)
{
level = pLevel;
rectTrans = new List<RectTransform>();
bounds = pBounds;
childs = new List<QuadTree>();
MAX_OBJECTS = maxObjs;
MAX_LEVELS = maxLevel;
}
/// <summary>
/// 清理四叉树
/// </summary>
public void Clear()
{
rectTrans.Clear();
for (int i = 0; i < childs.Count; i++)
{
childs[i].Clear();
}
}
/// <summary>
/// 分割四叉树
/// </summary>
public void Split()
{
float halfWidth = bounds.width / 2;
float halfHeight = bounds.height / 2;
float x = bounds.x;
float y = bounds.y;
childs.Add(new QuadTree(new Rect(x, y + halfHeight, halfWidth, halfHeight), level + 1, MAX_OBJECTS, MAX_LEVELS));
childs.Add(new QuadTree(new Rect(x + halfWidth, y + halfHeight, halfWidth, halfHeight), level + 1, MAX_OBJECTS, MAX_LEVELS));
childs.Add(new QuadTree(new Rect(x, y, halfWidth, halfHeight), level + 1, MAX_OBJECTS, MAX_LEVELS));
childs.Add(new QuadTree(new Rect(x + halfWidth, y, halfWidth, halfHeight), level + 1, MAX_OBJECTS, MAX_LEVELS));
//对象下沉
for (int i = 0; i < rectTrans.Count; i++)
{
Insert(rectTrans[i]);
}
rectTrans.Clear();
}
/// <summary>
/// 寻找对象所在节点列表
/// </summary>
/// <param name="rect">对象的rect</param>
/// <returns></returns>
public List<QuadTree> GetIndexes(Rect rect)
{
List<QuadTree> ret = new List<QuadTree>();
FindQuad(rect, ret);
return ret;
}
/// <summary>
/// 插入对象
/// </summary>
/// <param name="go"></param>
public void Insert(RectTransform go)
{
Rect rect = GetRect(go);
List<QuadTree> tempList = GetIndexes(rect);
for (int i = 0; i < tempList.Count; i++)
{

最低0.47元/天 解锁文章
5545

被折叠的 条评论
为什么被折叠?



