Unity 四叉树动态加载

目录

效果演示 

代码部分 

定义类

Tree部分 

逻辑部分 

启动逻辑

操作部分


效果演示 

代码部分 

定义类

public class ObjData 
{
    public string uid;
    public GameObject prefab;
    public Vector3 pos;
    public Vector3 ang;
    public ObjData(GameObject prefab,Vector3 pos,Vector3 ang)
    { 
        this.uid=System.Guid.NewGuid().ToString();
        this.prefab = prefab;
        this.pos = pos;
        this.ang = ang;
    }
}

Tree部分 

using UnityEngine;

public class Tree 
{
    public Bounds Bounds;
    private Node root;
    public int maxDepth = 6;
    public int maxChildCount = 4;
    public Tree(Bounds bound)
    {
        this.Bounds = bound;
        this.root = new Node(bound, 0, this);
    }
    //插入数据
    public void InserData(ObjData data)
    {
        root.InserData(data);
    }
    public void DrawBound()
    {
        root.DrawBound();
    }
    public void TriggerMove(Plane[] planes)
    {
        root.TriggerMove(planes);
    }
}

逻辑部分 

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 InserData(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].InserData(data);
                    break;
                }
            }
        }
        else
        {
            datas.Add(data);
        }
    }

    private 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 UnityEngine;

public class CreatCube : MonoBehaviour
{
    public GameObject cube;

    public Bounds mainBound;
    Tree tree;//树
    bool startEdnd = false;//是否初始化完毕
    public Camera cam;//相机
    Plane[] planes;//视椎体的6个面
    void Start()
    {
        planes= new Plane[6];//开辟内存
        //初始化场景最大分块
        Bounds bounds = new Bounds(transform.position, new Vector3(100, 0, 100));
        //创建树
        tree = new Tree(bounds);
        for (int x = -50; x < 50; x++)
        {
            for (int z = -50; z < 50; z++)
            {
                if(Random.Range(0,10)<1)
                {
                    GameObject c=Instantiate(cube,transform);
                    c.transform.position=new Vector3(x,0,z);
                    c.transform.eulerAngles = new Vector3(0, Random.Range(0, 360), 0);
                    //将预制体数据存入树
                    tree.InserData(new ObjData(c,c.transform.position,c.transform.eulerAngles));
                }
            }
        }
        startEdnd = true;
    }

    void Update()
    {
        if(startEdnd)//判断初始化结束后
        {
            //给6个面赋值
            GeometryUtility.CalculateFrustumPlanes(cam, planes);
            //通过树判断是否显示
            tree.TriggerMove(planes);
        }
    }
    private void OnDrawGizmos()
    {
        if(startEdnd)//判断初始化结束后
        {
            //通过树绘制包围盒
            tree.DrawBound();
        }
        else
        {
            Gizmos.DrawWireCube(mainBound.center, mainBound.size);
        }
    }
}

操作部分

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值