草庐IT

Unity | 以附加模式加载场景,实现多场景叠加及注意事项

渡鸦(valiancer) 2023-08-09 原文

1 多场景叠加

Unity 允许多场景叠加,这种叠加包括编辑模式及运行模式

新建两个简单的场景,SampleScene 和 AdditiveScene,设置不同的天空盒及平行光源颜色

SampleScene

AdditiveScene

2 编辑模式

2.1 添加场景

在编辑器中的场景资源右键选择 Open Scene Additive,或者直接拖拽场景资源到层级视图,都可以实现多场景编辑

2.2 层级结构

多场景叠加时,无论编辑模式还是运行模式,每个场景的内容将在 Hierarchy 窗口中单独显示在场景分隔栏下方,该分隔栏会显示场景的名称及其保存状态

场景叠加后,每个场景中的游戏对象都会出现在 Hierarchy 中,因此这些 GameObject 也会同时产生作用,比如 Main Camera 会造成多次渲染,Directional Light 会造成光照效果叠加等,因此一定要根据需求合理规划

2.3 场景特定设置

除了层级视图中的 GameObject,场景也会有一些特定的设置,比如天空盒、导航网格、光照贴图等

单场景烘焙

分别对 SampleScene 及 AdditiveScene 烘焙导航网格及光照贴图,然后将两个场景同时放入编辑器,可以看到导航网格数据及光照贴图会同时出现在场景中,即也会共同生效

「导航网格」

「光照贴图」

「活动场景」
但是可以看到天空盒依然是 SampleScene,并不会产生叠加,毕竟天空只有一个,如果想要使用 AdditiveScene 的天空盒,就需要设置其为当前活动场景,场景右键选择 Set Active Scene

可以看到天空盒更改为 AdditiveScene

多场景烘焙

除了使用已经烘焙好的数据外,Unity 还支持烘焙多场景的导航网格及光照贴图等,在编辑器中打开想要烘焙的场景,点击对应的烘焙按钮即可

「导航网格」
导航网格数据以单个资源(NavMesh.asset)的形式保存在与当前活动场景同名的目录内

该单个资源由所有参与烘焙的场景共享,即每个场景都会引用到该资源,所以单独打开场景时,依然可以看到完整的导航网格数据

SampleScene

AdditiveScene

「光照贴图」
光照贴图数据同样保存在与当前活动场景同名的目录内,但光照计算的输入是所有场景中的静态几何体和光源,因此阴影和 GI 光反弹将适用于所有场景

但是光照贴图和实时 GI 数据拆分为每个场景单独加载/卸载的数据,光照贴图和实时 GI 数据图集在场景之间拆分。这意味着,场景之间的光照贴图永远不会共享,卸载场景时可以放心卸载光照贴图。目前始终会共享光照探针数据,并会同时加载所有烘焙在一起的场景的所有光照探针

SampleScene

右边的图片

更多操作请参考官方中文文档:「https://docs.unity3d.com/cn/2021.2/Manual/MultiSceneEditing.html」

3 运行模式

运行时通过代码动态添加场景,最终表现效果和编辑模式一样,只是在编辑器中的操作需要用代码实现

3.1 添加及卸载场景

  • 同步加载场景

SceneManager.LoadScene("AdditiveScene", LoadSceneMode.Additive);
  • 异步加载场景

SceneManager.LoadSceneAsync("AdditiveScene", LoadSceneMode.Additive);
  • 异步卸载场景

SceneManager.UnloadSceneAsync("AdditiveScene");

运行时控制台会看到下面的警告

There are 2 audio listeners in the scene. Please ensure there is always exactly one audio listener in the scene.
There are 2 event systems in the scene. Please ensure there is always exactly one event system in the scene

这是因为场景中同时存在两个 AudioListener(挂在 Main Camera 对象上) 及 EventSystem,处理方式可以通过编辑器禁用或者删除,也可以通过代码动态控制

3.2 获取及设置场景

通过代码控制,一般也有两种方式,通过全局变量标记需要的 GameObject,或者动态获取指定场景,然后获取需要的 GameObject

  • 根据场景名获取场景

Scene scene = SceneManager.GetSceneByName("AdditiveScene");
  • 根据场景索引获取场景

Scene scene = SceneManager.GetSceneAt(0);
  • 获取当前活动场景

Scene scene = SceneManager.GetActiveScene();
  • 获取场景中的所有根游戏对象

List<GameObject> rootGameObjects = new List<GameObject>();
scene.GetRootGameObjects(rootGameObjects);
GameObject go = rootGameObjects.Find(o => o.name == "Main Camera");
  • 将游戏对象从当前场景移至新场景

SceneManager.MoveGameObjectToScene(go, scene);
  • 设置当前活动场景

SceneManager.SetActiveScene(scene);

Unity 中 new 或者 Instantiate 游戏对象时,默认的 parent 也是当前活动场景,Camera.main 指向的同样是当前活动场景

如果有需要,也可以手动更改天空盒及光照贴图等

  • 更改天空盒

RenderSettings.skybox = this.skyBox;
  • 更改光照贴图

LightmapData data = new LightmapData
{
    lightmapColor = this.lightmapColor
};
LightmapSettings.lightmaps = new LightmapData[1] { data };

更多手记,请扫码领取

有关Unity | 以附加模式加载场景,实现多场景叠加及注意事项的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  4. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  5. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  6. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  7. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  8. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  9. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  10. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

随机推荐