一、引言:
场景的组织与管理是3d游戏开发中重要的一环,unity3d引擎中,只提供了最基本的场景组织,当我们加载场景时,会将场景中的物件及其依赖的资源全部加载出来,这对于较为庞大的场景显然是不合理的。可以考虑在进入场景时预先将可见范围内的物体加载,之后的其它物件也全部在当进入可见区域时加载,但如何才能快速索引到进入某区域的物体?因此,我们需要考虑一种层次化的场景管理机制,可以快速的索引出指定空间区域内的物体,以实现这种效果。
二、几何剖分技术:
几何剖分技术是一种能将场景中的几何物体通过层次性机制组织,使用时可以快速剔除层次树的整个分支,从而加快索引几何体的过程。四叉树(quad tree)和八叉树(octree)是一种常用的空间剖分方法,它将已知的空间分成四/八个子空间作为节点,每个节点又划分成四/八个子空间,依此递归,直到达到指定深度。
四叉树:
八叉树:
三、原理:
四叉树/八叉树的数据结构不算复杂,其节点主要包含如下成员:数据成员Data,节点的包围盒信息Bounds,用于确定节点的空间信息(对于2D情况的四叉树,也可以是Rect),子节点引用。其中树的根节点拥有最大的Bounds,其子节点的Bounds将其分割成四/八个子Bounds。这样每次我们需要查找某点附近的数据时,可以根据节点的Bounds快速的剔除掉大量不需要查找的物体。
注意,由于插入的数据成员本身也包含空间位置和大小信息,可能出现数据刚好处于节点的边界上,如下:
如图中右上角的星星图案,其刚好位于两个节点的边界上,此时的处理方法有:
1.两个节点同时包含该数据
2.由父节点包含该数据(这样意味着不仅仅只有叶子节点可以存储数据)
第一种方式尽管相对精确,但如果存在特别大的物体可能覆盖多个节点,那就需要同时被这些节点引用,不容易管理。
本文的实现采用了第二种方式,一些很小的物体也可能出现没有插入到叶子节点而导致范围过大,特别的,如果该物体恰巧位于四叉树区域的正中心,则其只能被四叉树的根节点所包含。
另外还可以通过实现松散四叉树的方式,不在本文讨论范围内,可以查阅相关的文档或博客。
四、实现:
1.检索进入指定区域的物体
抽象出了一个检测器接口:
/// <summary>
/// 检测器接口,用于检测和场景物件的触发
/// </summary>
public interface IDetector
{/// <summary>/// 是否检测成功/// </summary>/// <param name="bounds">包围盒</param>/// <returns></returns>bool IsDetected(Bounds bounds);/// <summary>/// 触发器位置/// </summary>Vector3 Position { get; }
}
对于场景树中存储的节点和节点下的物体数据,其全部包含了一个Bounds数据,用于确定该节点或该场景物体的包围盒区域,这样每次进行检索时,实际上就是调用具体Detector的IsDetected接口,并传入Bounds,以判断该节点或该场景物体是否可以被检索。
我目前实现了两种形式的Detector,一种通过简单的设置Detector周围指定范围的六面体区域作为可见区域,另一种则是基于相机视锥体的判断,两种效果如下:
基于简单的六面体区域:
/// <summary>
/// 该触发器根据六面体包围盒区域触发
/// </summary>
public class SceneTransformDetector : SceneDetectorBase
{public Vector3 detectorSize;private Bounds m_Bounds;public override bool IsDetected(Bounds bounds){m_Bounds.center = Position;m_Bounds.size = detectorSize;return bounds.Intersects(m_Bounds);}
}

基于相机视锥体:
/// <summary>
/// 该触发器根据相机裁剪区域触发
/// </summary>
public class SceneCameraDetector : SceneDetectorBase
{private Camera m_Camera;void Start(){m_Camera = gameObject.GetComponent<Camera>();}public override bool IsDetected(Bounds bounds){if (m_Camera == null)return false;return bounds.IsBoundsInCamera(m_Camera);}
}

2.删除区域外的物体
对于场景物体,为每个物体初始化一个权重数据,每次物体被检索,权重进行累加,超出区域的物体则被推入一个优先级队列,该优先级队列根据权重排序,权重越大,表示在场景中滞留的时间越久,说明该物体出现的几率比较频繁,则删除的时机越靠后。一旦物体销毁,权重归零。
未完善的地方
由于待加载的物体是预先计算其包围盒并插入四叉树/八叉树中,如果涉及到物体的变换,考虑到需要更新物体的包围盒,这将影响原始物体在树中的信息,例如更新后的包围盒超出了物体所在节点的包围盒,导致不得不重新计算物体在树中的位置,因此该demo中暂时不涉及被加载物体会动态变换的情况,即目前仅适用于静态物体的加载。(当然如果物体的变换不会导致包围盒更新,例如播放一些原地不动的动画,则是可以支持的)

Demo下载地址请浏览我的博客原文:点击打开链接

【Unity】四叉树/八叉树管理和动态加载场景物件相关推荐

  1. (转)Unity 导出XML配置文件,动态加载场景

    参考:http://www.xuanyusong.com/archives/1919 http://www.omuying.com/article/48.aspx 主要功能: 1.导出场景的配置文件 ...

  2. Unity动态加载场景

    不用在build setting中设置,使用ab包动态加载场景 1.把场景打成ab包 2.加载ab资源,然后加载场景 demo链接 链接:https://pan.baidu.com/s/1dP9ihT ...

  3. 【Unity】光照贴图动态加载

    一般情况下对场景进行烘焙后,其实不用关心光照贴图的加载问题,Unity会自动帮我们处理好的,比如这个测试场景,烘焙结束后,关掉烘焙灯光,运行,直接运行得到的效果就是预期这样,没有写任何代码,光照贴图就 ...

  4. unity游戏开发入门-Resources动态加载图片

    问题:unity的Resources动态加载就不必多说了,这里出现的问题是当我把图片放入Resources文件夹后,使用Resources.Load(datapath)却并没有出现图片. 分析:由于你 ...

  5. 铵钮提交事件PostBack之后,一些动态加载的物件丢失

    今早起来,发现skype有网友留言,情况大约如下,不过Insus.NET还是先感谢网友的测试. http://www.cnblogs.com/insus/p/3193619.html  如果你有看此篇 ...

  6. Unity动态加载和内存管理(三合一)

    原址:http://game.ceeger.com/forum/read.php?tid=4394#info 最近一直在和这些内容纠缠,把心得和大家共享一下: Unity里有两种动态加载机制:一是Re ...

  7. Unity3D的坑系列:动态加载dll

    Unity3D的坑系列:动态加载dll 我现在参与的项目是做MMO手游,目标平台是Android和iOS,iOS平台不能动态加载dll(什么原因找乔布斯去),可以直接忽略,而在Android平台是可以 ...

  8. vue动态加载路由的实现

    动态加载路由的实现 vue后台管理之动态加载路由 vue路由动态加载

  9. Unity3D游戏开发之使用AssetBundle和Xml实现场景的动态加载

    各位朋友,大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是http://qinyuanpei.com/. 引言 今天我想和大家聊聊在Unity3D中关于场景的动态加载的问题.众所周知在Unit ...

  10. Unity学习笔记(5):动态加载Prefab

    第一种方法,从Resources文件夹读取Prefab Assets/Resources文件夹是Unity中的一个特殊文件夹,在博主当前的认知里,放在这个文件夹里的Prefab可以被代码动态加载 直接 ...

最新文章

  1. Idea debugger 无法启动-unable to open debugger port , java.net.SocketException socket closed
  2. 笔记-项目管理基础知识-项目组织结构
  3. 排序算法复习—希尔排序
  4. 服务器u8系统数据库不存在,用友u8服务器端数据库不装
  5. 简易数字时钟软件详细制作过程
  6. feign获取outstream_Spring Cloud Feign接口返回流
  7. 20100921 学习记录:关于sqlserver2005与ASP中 转换日期格式
  8. [一个简单的.NET逆向工程]给没有源代码的.NET程序打补丁
  9. java中关于x轴翻转和y轴翻转如何计算_如何避免这8个常见的深度学习/计算机视觉错误?
  10. EDA技术实用教程 | 复习七 | 异步清零和同步清零的时序设计
  11. 计算机机房网络布线方案,计算机机房布线方案与机房的环境要求
  12. windows10如何查看硬盘序列号
  13. 卡方检验的统计量推导_解释相关性的卡方检验的所有统计量 - Minitab
  14. android studio adb 连接mumu 模拟器
  15. JavaScript笔试题(一)
  16. 光学神经网络 Optical neural network
  17. Git:git-merge的--ff和--no-ff
  18. 我的京东管理生涯随想
  19. html字符串导出word
  20. windows下解压.bz文件

热门文章

  1. 4g内存php一般开多少个进程,Linux_4G内存服务器epoll并发量最大能达到多少?,按照题主的意思 是根据内存去 - phpStudy...
  2. 【新手入门】自己动手搭建云服务器
  3. 运筹帷幄决胜千里,Python3.10原生协程asyncio工业级真实协程异步消费任务调度实践
  4. Android之路——第一个上线 APP项目总结
  5. 西门子免授权CNC数控系统数据采集c#、C、python都支持,可支持再各种操作系统上运行,无须西门子OPC,支持828D 840dsl 808 802dsl 840d 810d 西门子数控DNC程序
  6. 利用jsPDF把图片转成pdf格式保存本地指定目录
  7. python实现词语填空_Python实践练习:疯狂填词
  8. 机械师笔记本电脑屏幕使用过程中忽然变暗
  9. GIF 字节格式介绍
  10. python3 数独解法 深度遍历