Unity场景问题,以及老程序DontDestory问题

Unity 5.3中新增加了多场景编辑功能,允许用户将一个大场景以某种逻辑分割成多个小场景并方便的编辑和管理。这在某些情况下会比较有用,是对Unity编辑器对场景编辑能力的一个重要提升。

什么是多场景编辑

多场景编辑就是允许用户在Unity编辑器中同时打开多个场景,并对它们进行编辑。Unity提供了一系列的UI和Scripting API来管理这些场景。以下就是一个在Unity编辑器中进行多场景编辑的一个实例:



什么是场景在进一步了解多场景编辑之前,我们先了解下什么是场景(Scene)。简而言之场景就是包含了游戏对象的一个文件,比如Game Objects,Components等。不过有一些对象可能一些用户并不会太在意,那就是Scene Game Managers。

Unity中有两类Game Managers:
  • 一类是Global Game Managers。它们是全局的Game Managers,包括AudioManager、InputManager、PhysicsManager等。当在Unity5.3中发布游戏的时候,你会发现在输出目录或者发布包里面会有个globalgamemanagers文件,它包含了所有全局Game Managers。

  • 另一类是Scene Game Managers。如果你将Editor Settings中的Asset Serialization选择为“Force Text”模式,并打开一个已经保存的*.unity场景文件,你会发现前保存在文件最前面的就是SceneSettings、RenderSettings、LightMapSettings和NavMeshSettings,它们就是每个场景都会有的Game Managers。


为什么需要多场景编辑
  • 首先,将大场景分割成多个场景,可以更好的支持场景的流式加载(Scene streaming);

  • 其次,可以更好地支持协同合作,尤其是在有源代码版本管理的时候可以允许多人同时编辑而不会产生冲突;

  • 再者,支持卸载场景(Scene Unloading),在5.3之前用户可以通过Application.LoadLevelAddtive()和Application.LoadLevelAdditiveAsync()动态加载场景,但没有对应的Application.UnloadScene()。而5.3中提供了场景卸载,让用户可以更灵活的管理多个场景


多场景编辑基本功能介绍接下来我们看看Unity在5.3中具体提供了哪些多场景编辑的功能。
Scene结构在5.3之前,Unity中只有概念上的场景,而到5.3中我们引入了真正的Scene结构。它包含了name、path、isLoaded等变量,同时也提供了IsValid()以及GetRootGameObjects()方法。
Active Scene在5.3中,我们引入了Active Scene(当前场景)的概念。引入它的目的在于:
  • 如果有多个场景同时打开,我们会选择Active Scene的Scene Game Managers作为当前的Scene Game Managers。比如在Bake Lightmapping的时候,我们会使用Active Scene的LightMapSettings来Bake当前打开的所有场景。

  • 在创建Game Object的时候,会默认加入到Active Scene。


SceneManagerSceneManager在UnityEngine.SceneManagement之下,它是Runtime中的Scene Manager,提供了以下方法:
LoadScene() /LoadSceneAsync()
它们允许用户通过Name、Build Index来加载场景。用户可以在Build Settings窗口查看Name和Build Index。通过这两个方法加载的场景,要么被加到了Build Settings,要么存在于AssetBundle之中。如果是从AssetBundle中加载场景,则只能通过名字加载
要说明的是,如果有多个场景同名但位于不同的目录之下,可以使用完整的路径(不带.unity后缀名)来加载不同的场景。
用户可以通过LoadSceneMode来指定不同的加载模式。LoadSceneMode.Single在加载之前会卸载其它所有的场景,LoadSceneMode.Additive则是加载的时候不关闭之前的场景。
还有一点很重要,LoadScene()并不是完全同步的,它只能保证在下一帧开始之前加载完毕。所以在此推荐大家使用LoadSceneAsync()这个异步的加载方法
UnLoadScene()
目前5.3中用户只能通过Name和Build Index来同步的卸载一个Scene。在后续的版本中我们会提供通过Scene结构来卸载一个Scene,并且提供异步卸载的方法。

GetActiveScene() /SetActiveScene()
获取和设置Active scene。
GetSceneAt() / GetSceneByName() / GetSceneByPath()
查询Scene的一组方法。
其它

EditorSceneManager


EditorSceneManager在UnityEditor.SceneManagement之下,它是Editor中的Scene Manager,提供了以下方法:
OpenScene()
它是一个同步的方法,用户只能通过path来打开场景。不同于LoadScene() / LoadSceneAsync(),它可以直接打开一个存在于Assets目录下的场景,不管它是否被添加到Build Settings
用户可以通过OpenSceneMode来指定不同的打开模式,相比较LoadSceneMode,它多了一个AdditiveWithoutLoading模式,允许用户增加一个场景但并不真正加载它
CloseScene()
顾名思义,它可以关闭一个场景,同时它提供了一个bool参数来指定关闭的时候是否将场景从Scene Manager中移除。
SaveScene() / SaveScenes()
通过它们可以保存一个或多个Scene。
MarkSceneDirty() / MarkAllScenesDirty()
通过它们可以将某个指定的场景或者所有场景标记为Dirty。大部分情况Unity内部通过Undo系统来实现场景的Dirty跟踪,但是有些模块并没有完全支持Undo,比如Terrain在设置某些参数的时候就不支持Undo。所以我们提供了这两个方法支持直接将场景设置为Dirty。
API的使用限制在Editor Mode下,UnityEngine.SceneManagement.SceneManager的某些方法是不能使用的:
  • LoadScene()

  • LoadSceneAsync()

  • CreateScene()

  • UnloadScene()


同样在Play Mode下,UnityEditor.SceneManagement.EditorSceneManager的某些方法也不能使用:
  • OpenScene()

  • NewScene()

  • CloseScene()

  • SaveScene() / SaveScenes() / …

  • MarkSceneDirty() / MarkAllScenesDirty()/…


如果用户在不同的模式下使用了错误的方法,我们会在Console输出对应的错误信息引导用户使用正确的方法。
DontDestroyOnLoad场景在Unity 5.3中,如果用户通过Object.DontDestroyOnLoad()方法将某个Game Object标记成DontDestroyOnLoad,在进入Play Mode的时候会发现Hierarchy窗口中多出一个DontDestroyOnLoad场景,它包含了之前标记成DontDestroyOnLoad的Game Object。

为什么需要DontDestroyOnLoad场景在Unity 5.3中,所有的Game Object必须隶属于某一个场景。这样我们就必须有一个特别的场景来管理这些被标记为DontDestroyOnLoad的Game Objects,否则在Unload这些Game Objects所属的场景的时候,这些Game Objects也会被删除掉。这显然不是我们想要的结果。
因此我们引入了DontDestroyOnLoad场景,当进入Play Mode时候,我们会把所有标记为DontDestroyOnLoad的Game Objects从所属的场景移入到这个特别的场景之中。
DontDestroyOnLoad场景的特点DontDestroyOnLoad场景仅仅存在于Runtime,或者是Play Mode下。它不能从外部访问,仅仅是Unity内部用于管理标记为DontDestroyOnLoad的Game Objects。
事实上从Unity 5.3开始,我们并不推荐用户使用DontDestroyOnLoad这一功能,它使得我们内部的代码逻辑复杂度增加了不少。5.3之前因为没有多场景的支持,所以并没有很好地办法绕开它并实现相同的功能。而从5.3开始我们推荐用户创建一个Manager场景,由它负责加载/卸载其它所有的游戏场景。它从游戏开始便存在一直到游戏退出,这样所有需要被标记为DontDestroyOnLoad的Game objects都应该属于这个场景。
多场景编辑的进阶接下来我们介绍一些关于多场景编辑的进阶以及一些小技巧。

1Scene Manager Setup

Scene Manager Setup可以用来保存并恢复当前的Scene Hierarchy。EditorSceneManager上提供了GetSceneManagerSetup() / RestoreSceneManagerSetup()来获取和恢复Scene Hierarchy。


我们可以通过ScriptableObject来保存Scene Hierarchy,代码如下所示:




以下的代码展示了如何保存以及读取Scene Manager Setup:

2Lightmap & NavMesh Baking

在Unity 5.3中,Lightmap和NavMesh的烘焙都同时支持多个场景,它们之间的不同之处在于如何管理和划分烘焙的结果


对于Lightmap Baking,我们会根据Scenes划分Lightmaps和Realtime GI数据 。每个场景都只会加载和自己相关的那部分数据。
对于NavMesh Baking,因为它烘焙的结果很小,所以我们将NavMesh的数据保存在一个asset当中 ,每个场景都会引用到这个asset并能够找到自己所关联的那部分数据。
另外用户也可以通过脚本进行Baking,Lightmapping.BakeMultipleScenes()和NavMeshBuilder.BuildNavMeshForMultipleScenes()都支持一次烘焙多个场景。

3Scene Dirty Track

Unity内部大多通过Undo系统来实现Scene Dirty追踪。Unity 5.3为了支持多场景编辑,我们通过在Undo操作中保存Scene Handles来扩展Undo系统。


另外我们增加了 Undo.MoveGameObjectToScene()方法来支持场景之间Game Object移动的Undo 。同时Scene结构上面也有一个Scene.isDirty属性用于查询某个Scene是否被修改。

4“Ctrl + S”的行为

在这里有一个问题想跟大家讨论的是“Ctrl + S”的行为。在5.3以前,无论场景是否Dirty,只要用户按下”Ctrl + S”,我们一定会保存该场景。而在5.3中,因为多场景编辑的引入,我们改变了这一行为。


从5.3开始,”Ctrl + S”只会保存Dirty的场景 。试想如果用户打开了上百个场景,只修改了其中某一个场景,如果“Ctrl + S”还是保存非Dirty的场景,保存速度会受到比较大的影响。
这个改动会影响到一些Editor的工具 。比如某个Editor的工具创建了一个Game Object,由于没有使用Undo系统(Undo.RegisterCreatedObjectUndo),使得场景未标记成Dirty。这样当在保存的时候,Unity并不会去真正保存这个场景。
在此 推荐大家使用Undo系统来注册Undo操作,从而能够正确的将受影响的场景标记为Dirty 。我们也乐于听到大家的反馈,来看看我们是否有办法更好的处理这个问题。

5Scene加载的延迟Awaking

在多场景的使用中,一个比较有意思的地方就是Scene加载过程中的Delay Awaking。在介绍它之前我们来看看Unity内部加载一个Scene所需的步骤。


6Scene加载的两个步骤 Unity内部场景的加载分为两步:
  • Loading。是指从文件、内存(主要是Streamed scene AssetBundle)中加载Scene的内容,创建并读取所有相关的Game objects、Assets以及Scene game managers。所有的IO操作都在这一步完成,所以它是比较耗时的过程。当这一步完成的时候,我们内部会将加载进度标记为90%。

  • Awaking。主要是一些轻量级的操作,比如在Transform的Awaking的时候,我们会将Game objects加入到它所属于的Scene。我们这里所说的Scene加载过程中的Delay awaking就是指第二步。


比如用户有一个大场景划分成了若干个子场景,在所有场景加载完毕我们才会开始Game play。这时我们就可以推迟所有子场景的Awaking。当所有的加载第一步完成了,我们才进行所有场景的Awaking。

用户可以通过将AsyncOperation.allowSceneActivation设置成false来阻止Scene的Awaking,示例如下:




当加载进度AsyncOperation.progress到达90%的时候,就可以将allowSceneActivation设置成true来允许Scene awaking。


原文链接
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Unity 场景下载是指下载其他开发者制作的 Unity 场景,以便在自己的项目中使用。在互联网上,有很多网站和社区提供了丰富的 Unity 场景资源供开发者免费或付费下载。 主要的下载方式有以下几种: 1. Unity Asset Store:这是 Unity 官方提供的资源商店,提供了丰富的可以直接在 Unity 编辑器中导入的资源,包括场景模型、材质、音频、代码脚本等。 2. 第三方网站:如 CGTrader、TurboSquid、Sketchfab 等,这些网站提供了广泛的 3D 模型,在其中寻找合适的场景模型、特效动画、音频背景是不错的选择。 3. Unity 官网社区:它提供了一个交流分享的平台,许多开发者会在其中免费分享自己开发的场景,或者提供下载链接。 无论是哪种下载方式,都需要开发者根据自己的需求进行筛选和选择,保证下载的资源符合项目需求和使用规范。同时,确保资源下载的合法性,防止恶意软件的入侵。在使用场景时,还需适当调整和修改,以保证流畅的合理的使用体验。 ### 回答2: Unity场景下载是指从Unity Asset Store或者其他网络资源中下载其他开发者创建的Unity场景文件。Unity场景是游戏开发中的基本元素之一,它是一种包含了游戏中所有元素和物体的三维环境,包括场景内的地图、地形、建筑、道具等等。 通过下载其他开发者创建的Unity场景文件,我们可以快速地获取并使用他们创建的游戏环境,加快我们的开发速度。而且,下载的Unity场景文件也可以作为学习资源,让我们学习其他游戏开发者的制作技巧和经验,从而提高自己的创作能力。 当我们下载Unity场景文件后,通常需要进一步编辑和调整其内容,以适应我们自己的需求。例如,我们可以添加自己的游戏元素或者再次修改地图和道具等等。同时,我们还可以将自己创建的Unity场景文件发布到网络资源中,以分享给其他开发者和游戏爱好者。 总之,Unity场景下载是游戏开发中常见的操作之一,它可以帮助我们快速地获取资源并学习他人的经验,同时也可以将自己的作品分享给其他人。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值