unity四叉树视锥体剔除

文章介绍了在Unity3D游戏开发中,利用四叉树数据结构进行场景对象管理,通过插入数据、创建子节点以及绘制包围盒来组织场景。同时,结合视锥体剔除技术,提高渲染效率,仅对相机视野内的对象进行处理,降低计算量。
摘要由CSDN通过智能技术生成

节点代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Node
{
    public Bounds bound;
    public int myDepth;//当前层数
    public Tree tree;
    public List<ObjData> datas = new List<ObjData>();//数据
    public Node[] childs;//子节点      
    public Vector2[] bif = new Vector2[]
    {
        new Vector2(-1,1),
        new Vector2(1,1),
        new Vector2(-1,-1),
        new Vector2(1,-1)
    };
    public Node(Bounds bound, int myDepth, Tree tree)
    {
        this.bound = bound;
        this.myDepth = myDepth;
        this.tree = tree;
    }
    public void InsertData(ObjData data)
    {
        //层级没到上限 且 没有子节点 可以创建子节点
        if (myDepth < tree.maxDepth && childs == null)
        {
            CreatChild();
        }
        if (childs != null)
        {
            for (int i = 0; i < childs.Length; i++)
            {
                //判断数据的位置是否归属于该子节点的区域
                if (childs[i].bound.Contains(data.pos))
                {
                    //继续去下一层查找
                    childs[i].InsertData(data);
                    break;
                }
            }
        }
        else
        {
            datas.Add(data);
        }
    }
    public void CreatChild()
    {
        //创建树指定的节点
        childs = new Node[tree.maxChildCount];
        for (int i = 0; i < tree.maxChildCount; i++)
        {
            //计算相对坐标
            Vector3 center = new Vector3(bif[i].x * bound.size.x / 4, 0, bif[i].y * bound.size.z / 4);
            //计算大小
            Vector3 size = new Vector3(bound.size.x / 2, 0, bound.size.z / 2);
            //设置矩阵
            Bounds childbound = new Bounds(center + bound.center, size);
            //给子节点赋值
            childs[i] = new Node(childbound, myDepth + 1, tree);
        }
    }

    public void DrawBound()
    {
        //有数据画蓝色框框
        if (datas.Count != 0)
        {
            Gizmos.color = Color.blue;
            Gizmos.DrawWireCube(bound.center, bound.size - Vector3.one * 0.1f);
        }
        else//没数据画绿色框框
        {
            Gizmos.color = Color.green;
            Gizmos.DrawWireCube(bound.center, bound.size - Vector3.one * 0.1f);
        }
        //有子物体让子物体去画
        if (childs != null)
        {
            for (int i = 0; i < childs.Length; ++i)
            {
                childs[i].DrawBound();
            }
        }

    }

    public void TriggerMove(Plane[] planes)
    {
        //有子物体让子物体去判断是否重叠
        if (childs != null)
        {
            for (int i = 0; i < childs.Length; ++i)
            {
                childs[i].TriggerMove(planes);
            }
        }
        for (int i = 0; i < datas.Count; i++)
        {
            //判断矩阵与视锥体6个面是否重叠
            datas[i].prefab.SetActive(GeometryUtility.TestPlanesAABB(planes, bound));
        }
    }
}

 树代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tree
{
    public Bounds bound;
    private Node root;//根
    public int maxDepth = 6;//最多层数
    public int maxChildCount = 4;//最多分块

    public Tree(Bounds bound)
    {
        this.bound = bound;
        this.root = new Node(bound, 0, this);
    }
    //插入数据
    public void InsertData(ObjData data)
    {
        root.InsertData(data);
    }
    public void DrawBound()
    {
        root.DrawBound();
    }
    public void TriggerMove(Plane[] planes)
    {
        root.TriggerMove(planes);
    }
}

四叉树的使用与视锥体剔除

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreatCube : MonoBehaviour
{
    public GameObject cube;
    public int n = 10;
    public Bounds mainBound;
    Tree tree;//树
    bool startEnd = false;//是否初始化完毕
    public Camera cam;//相机
    Plane[] planes;//视锥体的6个面
    // Start is called before the first frame update
    void Start()
    {
        Init();
    }
    public void Init()
    {
        planes = new Plane[6];//开辟内存
        //初始化场景最大分块
        Bounds bounds = new Bounds(transform.position, new Vector3(2 * n, 0, 2 * n));
        //创建树
        tree = new Tree(bounds);
        //创建预制体
        for (int x = -n; x < n; x++)
        {
            for (int z = -n; z < n; z++)
            {
                if (Random.Range(0,10) < 1)
                {
                    GameObject c = Instantiate(cube, transform);
                    c.transform.position = new Vector3(x, 0, z);
                    //将预制体数据存入树
                    tree.InsertData(new ObjData(c, c.transform.position, c.transform.eulerAngles));
                }
            }
        }
        startEnd = true;
    }

    // Update is called once per frame
    void Update()
    {
        if (startEnd)//判断初始化结束后
        {
            //给视锥体的6个面赋值
            GeometryUtility.CalculateFrustumPlanes(cam, planes);
            //通过树判断是否显示
            tree.TriggerMove(planes);
        }
    }

    private void OnDrawGizmos()
    {
        if (startEnd)//判断初始化结束后
        {
            //通过树绘制包围盒
            tree.DrawBound();
        }
        else
        {
            Gizmos.DrawWireCube(mainBound.center, mainBound.size);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值