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

2023-11-02

一、引言:
场景的组织与管理是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下载地址请浏览我的博客原文: 点击打开链接

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • Unity WebGL错误集锦

    ips 0 Unity的PlayerSettings的otherSettings或者Publish Settings里面的Enable Exceptions里面选择Full StackTrace 可以在打出的包中的浏览器的webgl打印出错
  • 蒙特卡洛积分、重要性采样、低差异序列

    渲染公式 渲染的目标在于计算周围环境的光线有多少从表面像素点反射到相机视口中 要计算总的反射光 每个入射方向的贡献 必须将他们在半球上相加 为入射光线 与法线 的夹角 为方便计算可以使用法线向量和入射向量 单位化 的乘积表示 对于基于图像的
  • 【Unity&C#&随机数】随机数

    一个简单的随机数获得 0或1 使用了这样的代码 想要获得0或者1 if Input anyKeyDown float i 1 if i 1 i Random Range 0 Rang i i lt 0 5 0 1 Debug Log Cou
  • unity制作一个可以自由滑动收缩的历史记录功能。

    公司在做一款模拟经营类的卖车游戏 需要一个简单的历史记录功能 放在左上角 记录最近20条的收入 支出记录 超过2秒不动则收起 收起时展示最近的一个消息记录 用到的组件是ScrollView 使用方法可以参考我写过的一篇博客 ScrollVi
  • Unity中级客户端开发工程师的进阶之路

    上期UWA技能成长系统之 Unity高级客户端开发工程师的进阶之路 得到了很多Unity开发者的肯定 通过系统的学习 可以掌握游戏性能瓶颈定位的方法和常见的CPU GPU 内存相关的性能优化方法 UWA技能成长系统是UWA根据学员的职业发展
  • FBX导入Unity中模型没有材质的处理

    一 3dMax导出FBX时的注意事项 导出时 确保maps文件存在 里面放着fbx用到的image 二 在Unity中的设置 1 文件拖入Unity的Assets文件夹中 2 查看模型的材质是否存在 如下所示 材质为None 此时拖入sce
  • Unity3d 插件 系列——DoTweenPro介绍(图文详细+案例)

    Unity3d 插件 系列 DoTweenPro介绍 图文详细 案例 前言 一 DoTweenPro简介 二 DoTweenPro安装 三 DoTweenPro主要组件 1 DoTweenAnimation 2 DoTweenPath 3
  • Unity与Android的Back键冲突解决

    Unity与Android的Back键冲突解决 上一篇的最后留下了两个问题 Unity视图下横屏闪退 Unity视图下Android无法响应back返回上一activity 对于第一个问题 应该是Unity横屏下视图的某些设置跟Androi
  • mac下搭建cocos2d-x3.2开发环境

    1 软件 Xcode Ant apache ant 1 9 4 bin tar gz Jdk jdk 8u45 macosx x64 dmg 有的mac系统上没有自带 Ndk android ndk r10d darwin x86 64 b
  • 【Unity】按Esc进入操作菜单

    本文章是基于如下视频的自我总结 https www youtube com watch v JivuXdrIHK0 步骤如下 1 在Canvas 界面添加一个Panel Panel中添加一个按钮 调整按钮的大小为合适大小 调整字体的大小为合
  • Unity打包WebGL的优化常用操作?

    1 贴图部分优化 如果贴图格式时2048 在不影响画面效果的情况下 改成1024或者5 12 还可以缩小包体 2 压缩和解压缩问题 WebGL打包的时候分三种压缩情况 gzip 比Brotli文件打 但打包快 http和https都支持 B
  • unity实现鼠标右键控制视角

    主要实现的功能是相机跟随主角 鼠标右击移动后 相机的视角会旋转 思路 在主角里创建空的子物体 把相机绑在空物体上 通过旋转空物体来实现视角的旋转 要把相机调整到适当位置 代码如下 public float rotateSpeed 100 设
  • unity3d image组件不显示

    需要将UI组件放到画布下面
  • 【原神游戏开发日志1】缘起

    原神游戏开发日志1 缘起 版权声明 本文为 优梦创客 原创文章 您可以自由转载 但必须加入完整的版权声明 文章内容不得删减 修改 演绎 相关学习资源见文末 大家好 最近看到原神在TGA上频频获奖 作为一个14年经验的游戏开发行业的老兵 我就
  • 【Unity】如何让Unity程序一打开就运行命令行命令

    背景 Unity程序有时依赖于某些服务去实现一些功能 此时可能需要类似打开程序就自动运行Windows命令行命令的功能 方法 using UnityEngine using System Diagnostics using System T
  • Unity学习笔记

    一 旋转欧拉角 四元数 Vector3 rotate new Vector3 0 30 0 Quaternion quaternion Quaternion identity quaternion Quaternion Euler rota
  • Unity中URP下的指数雾

    文章目录 前言 一 指数雾 雾效因子 1 FOG EXP 2 FOG EXP2 二 MixFog 1 ComputeFogIntensity 雾效强度计算 2 lerp fogColor fragColor fogIntensity 雾效颜
  • 游戏开发常见操作梳理之NPC任务系统

    多数游戏存在任务系统 接下来介绍通过NPC触发任务的游戏制作代码 using System Collections using System Collections Generic using UnityEngine
  • 游戏开发常见操作梳理系列之——玩家信息的显示系统

    在游戏中 有不少游戏在左上角会出现玩家的头像和等级以及血量 这就是玩家的信息显示系统 那么这些是如何制作的呢 接下来我将讲讲代码的操作 其它操作我会在其它笔记中一一说明 敬请期待 信息的显示相当简单就是控制一些UI 然后在其它系统里面填写相
  • 游戏开发常见操作系列之敌人系统的开发一(U3D)

    在开发游戏的过程中 我们常常会出现一些敌人攻击我们玩家 并且实现掉血以及死亡的现象 敌人还会源源不断地生成 这是怎么制作的呢 接下来为大家提供方法 其中使用了NGUI 后续会更新其它方法 敬请期待 使用HUDText实现扣血时显示文本 直接

随机推荐

  • 重装系统蓝屏,电脑开机蓝屏解决方法记录

    电脑开机就kmode exception not handled 并且重装系统进不了pe 出现错误代码 unexpected kernel mode trap 电脑问题详细描述 开机就蓝屏 进不了系统 进不了安全模式 并且电脑会循环开机关机
  • GPT模型系列

    文章目录 1 Mask Multi head Attentiion 2 Generative Pre Traning GPT 3 GPT2 4 GPT3 1 Mask Multi head Attentiion Mask Multi hea
  • php数据库判断登录用户,【判断用户登录】PHP这样判断流程是否正确?每次都查询数据库 存COOKIE...

    我自己来做的PHP判断用户是否登录 流程 1 先判断有没有cookie uid cookie uid 如果没有跳出循环检测 2 如果有 连接数据库查询该uid对应的记录 如果没有改记录则跳出循环检测并且注销所有用户cookie 3 如果有
  • 前k个高频单词

    不要害怕前方的未知和困难 因为它们都是你成长的机会 不要过于在意别人的眼光和评价 因为唯有你的内心才知道自己真正的价值 珍惜当下 享受生活的点滴 让自己变得更加坚强 自信 成熟 作者 不能再留遗憾了 专栏 Java学习 本文章主要内容 前k
  • 星星之火-52:6G十大领域关键技术

    目录 1 6G超宽带通信系统的网络架构 2 6G超宽带通信系统的软件架构 3 太赫兹通信技术 4 6G 信道仿真技术及射线跟踪 5 超大带宽与全频谱协作 6 轨道角动量调制技术 7 宽带太赫兹硬件元器件技术 8 太赫兹天线技术 9 太赫兹射
  • 国产系统有了,芯片有了,编译器有了,那编程语言呢?

    国产操作系统一直在发展 市面上也早有了多款基于Linux内核的操作系统 各大OS厂商也都有自己的市场和拥趸 而芯片这块 虽然我们起步晚 商业市场也显得浮躁纷繁 但依旧有务实的IT科研工作者 工程师为主的企业或团队默默无闻十年磨一剑 苦心孤诣
  • (十三)MySQL数据库安装——从0开始大数据开发实战:电影推荐系统(scala版)

    执行一下命令 安装MySQL sudo apt get update sudo apt get install mysql server 安装过程中会提示设置MySQL数据库root用户的密码 本案例设置密码为hadoop 安装完成后默认启
  • 常用英语缩写

    Abandon简写为ABAN Abandoned简写为ABD Abbreviate简写为ABBR Abbreviated简写为ABR Abbreviation简写为ABR Ability简写为ABL Abundance简写为ABUND Ac
  • 虚幻4学习笔记(4)光照、游戏角色、上下车、冲刺瞬移多段跳、打包

    光照 光照 光照分类 光的移动性 自动曝光 指数级高度雾 生成光束 使用体积雾创建光束 使用天空球制造夜晚 设置玩家角色 设置玩家切换 镜头过度 上下车 上车 下车 下车减速 人物冲刺和瞬移 冲刺 瞬移 多段跳设置 打包 B站UP谌嘉诚课程
  • LinkedList工作原理及实现

    以双向链表实现 链表无容量限制 但双向链表本身使用了更多空间 也需要额外的链表指针操作 按下标访问元素 get i set i e 要悲剧的遍历链表将指针移动到位 如果i gt 数组大小的一半 会从末尾移起 插入 删除元素时修改前后节点的指
  • Qt编写自定义控件大全

    最新版可执行文件 https pan baidu com s 1Y z4GT4kslgsb4f46yLILA 不定期增加控件及修正BUG和改进算法 目前已超过90个控件 总图 总图 1 动画按钮 1 可设置显示的图像和底部的文字 2 可设置
  • jenkins部署jeecg-boot3.1(前后端)自动化

    tip 我是使用我的腾讯云轻量应用服务器做的本次实战 操作系统 CentOS 7 6 64bit 主机规格 CPU 4核 内存 4GB 这个配置起前端有点带不动 建议8G内存 这个问题我反复测试很多次 一跑npm 就开始疯狂占资源 然后操作
  • 联想服务器开机引导,联想服务器怎么进入bios

    联想电脑设置起来比较麻烦 除了快捷启动菜单比较方便 如果要用传统的方式进行设置 会有很多项要设置 那么你知道联想服务器怎么进入bios吗 接下来 学习啦小编跟你分享联想服务器进入bios的设置步骤图解 联想服务器进入bios的设置步骤图解
  • word文档 文字变网址 解决办法

    word文档中文字变网址解决办法 问题描述 打开word文档发现其中有些文字变成了网址 解决办法 Alt F9 联想键盘 Alt Fn F9 这是因为直接按F9是功能键
  • n对括号的匹配方式(卡特兰数)

    4对 括号有多少种可能的合法 匹配方式 n对 括号呢 此题是卡特兰数的一个通常应用 相似的还有出栈顺序等 关于卡特兰数的具体内容 请参阅百度百科或Wiki http baike baidu com view 2499752 htm 网络上可
  • 泛型与正则表达式在Java编程中扮演着重要的角色

    泛型与正则表达式在Java编程中扮演着重要的角色 泛型提供了一种在编译时期检查类型安全性的机制 而正则表达式则允许我们以模式匹配的方式进行字符串的处理 本文将详细介绍Java中泛型和正则表达式的基础知识 并提供相应的源代码示例 泛型 什么是
  • 笔记:springboot-admin 整合spring security应用注册失败问题

    问题描述 原本正常的springboot admin 在整合了spring security之后就无法正常注册应用了 查看打印 Failed to register application as Application name admin
  • Android 中Activity和Fragment生命周期的具体变化详解

    博主前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住也分享一下给大家 点击跳转到网站 前言 一个MainActivity中装载了两个Fragment 在MainActivity中的onCreate 方法中进行了Fragme
  • ​ 输入一个字符串,将其中所有的大写和小写字母改成该字母的下一个字母,z 的下一个字母为 a。JAVA

    import java util Scanner public class Main public static void main String args Scanner scanner new Scanner System in Str
  • 【Unity】四叉树/八叉树管理和动态加载场景物件

    一 引言 场景的组织与管理是3d游戏开发中重要的一环 unity3d引擎中 只提供了最基本的场景组织 当我们加载场景时 会将场景中的物件及其依赖的资源全部加载出来 这对于较为庞大的场景显然是不合理的 可以考虑在进入场景时预先将可见范围内的物