需要用到的工具
资源打包、远程热更新工具
Addressables工具基本操作
在Window菜单下方,会有Asset Management
,选择Addressables中的Groups
会弹出相关菜单,将其拖入底部工具栏
会提示没有创建Addressables的相关配置,则点击Create Addressables Settings
这时候会在Project中,多出了一个AddressableAssetsData
由于目前需要此工具进行场景管理和打包,所以可以命名为Scenes
现在可以选中场景,在右侧的Inspector
中,能够看到多出了一个可勾选项——Addressable
勾选后,就能够看到Addressable Groups
中,多出了刚才勾选的场景。现在就已经加载到了Addressable中
不过在添加之后,会提示一个警告:一个场景被标记为使用可寻址资源加载程序,它当前已经从构建列表中取消
因为通常操作方式,实在Build Setting中进行构建打包,不过使用了Addressable进行构建的话,就替代了常规的构建方式。通常使用常规构建打包很多场景的话,会使包体占用空间很大。使用Addressable进行构建打包,会有更精巧的包体
预制体(Prefab)
预制体(Prefab)是用来提供跨场景调用、解决频繁复制、能够快速调用、统一修改实体参数的解决方案
在Assets目录中新建Prefabs文件夹
将敌人实体对象拖入到Prefabs文件夹中
这时候能看到敌人实体前的图标变成了蓝色,这时候就已经成为了预制体
那么这时候,无论Hierarchy窗口中的敌人对象有多少个,只要操作Prefabs目录内的对象对参数进行修改,所有被创建的同一个敌人的数据都会进行变动
加载场景和物体
当传送到下一张某个地图时,Teleport需要告诉SceneLoad Manager要加载什么场景。然后需要创建两个脚本,用于记录加载的场景和Addressable的资源
创建SceneLoadEventSO脚本
using UnityEngine;
[CreateAssetMenu(menuName = "Event/SceneLoadEventSO")]
public class SceneLoadEventSO : ScriptableObject
{
}
紧接着再创建一个GameSceneSO脚本,用于调用Addressable资源
using UnityEngine;
using UnityEngine.AddressableAssets;
[CreateAssetMenu(menuName = "Game Scene/GameSceneSO")]
public class GameSceneSO : ScriptableObject
{
public AssetReference assetReference;
}
在Assets目录中,Data SO下创建GameSceneSO,命名为Cave
选中GameSceneSO,在右侧Inspector中,能够看到Asset Reference
的选择框,这里面就是已经加载到Addressable中的资源。选中对应的场景,即可表示这个SO会加载这个场景
打开SceneLoader
代码,添加GameSceneSO和SceneLoadEventSO对象全局变量
[Header("事件监听")]
public SceneLoadEventSO loadEventSO;
public GameSceneSO firstLoadScene;
然后调用Addressable命名空间,异步加载这个场景
private void Awake()
{
// 异步加载
Addressables.LoadSceneAsync(firstLoadScene.assetReference, UnityEngine.SceneManagement.LoadSceneMode.Additive);
}
与此同时,需要选择一个Game Scene SO,来表示需要加载什么场景
启动游戏,这时候就可以加载出需要的场景了
在枚举类中,添加一个枚举类型,用于标记加载的场景类型。因为第一次加载的不一定是一个场景,可能是主菜单页面
public enum SceneType
{
Location, Menu
}
在GameSceneSO中,添加这个枚举类型
public class GameSceneSO : ScriptableObject
{
public SceneType sceneType;
public AssetReference assetReference;
}
打开TeleportPoint传送点的代码,添加一个全局变量,用于标识传送点去往的场景
public class TeleportPoint : MonoBehaviour, IInteractable
{
// 去往的场景
public GameSceneSO sceneToGo;
// 坐标点
public Vector3 positionToGo;
public void PlayFXAudio()
{
}
public void TriggerAction()
{
}
}
在Teleport Point中,Scene To Go选择框选择一个传送目的地的场景,接下来就需要把Scene To Go和Position传入到SceneLoadManager中
在SceneLoadEventSO中,编写加载目的地场景的相关代码
using UnityEngine;
using UnityEngine.Events;
[CreateAssetMenu(menuName = "Event/SceneLoadEventSO")]
public class SceneLoadEventSO : ScriptableObject
{
public UnityAction<GameSceneSO, Vector3, bool> LoadRequestEvent;
/// <summary>
/// 场景加载请求
/// </summary>
/// <param name="gameSceneSO">要加载的场景</param>
/// <param name="position">人物目的地坐标</param>
/// <param name="fadeScreen">是否淡入淡出</param>
public void RaiseLoadRequestEvent(GameSceneSO gameSceneSO, Vector3 position, bool fadeScreen)
{
LoadRequestEvent?.Invoke(gameSceneSO, position, fadeScreen);
}
}
接下来,在Event目录中新建Scene Load Event SO,并在Teleport中,将该SO添加到Load Event SO中
在Teleport的TriggerAction()方法中,编写唤起加载场景的事件
public void TriggerAction()
{
loadEventSO.RaiseLoadRequestEvent(sceneToGo, positionToGo, true);
}
在SceneLoader中,写SceneLoadEventSO的装载和卸载的代码
private void OnEnable()
{
loadEventSO.LoadRequestEvent += onl oadRequestEvent;
}
private void OnDisable()
{
loadEventSO.LoadRequestEvent += onl oadRequestEvent;
}
编写当事件唤起时需要执行的操作,创建三个全局变量,用于临时存储Teleport唤起事件时候传入的参数
private GameSceneSO targetSceneToGo;
private Vector3 targetPositionToGo;
private bool fadeScreen;
private void onl oadRequestEvent(GameSceneSO sceneToGo, Vector3 positionToGo, bool fadeScreen)
{
targetSceneToGo = sceneToGo;
targetPositionToGo = positionToGo;
this.fadeScreen = fadeScreen;
// 卸载当前场景,装载下一个场景
StartCoroutine(UnloadPreviousScene());
}
private IEnumerator UnloadPreviousScene()
{
if (fadeScreen)
{
// TODO:实现淡入淡出
}
// 等待淡入淡出的指定时间
yield return new WaitForSeconds(fadeTime);
// 卸载场景
yield return currentLoadScene.assetReference.UnLoadScene();
LoadNewScene();
}
private void LoadNewScene()
{
// 加载新场景
targetSceneToGo.assetReference.LoadSceneAsync(LoadSceneMode.Additive, true);
}
解决转换场景后报空引用的问题
将Awake()方法中的代码进行调整
private void Awake()
{
// 获取当前场景
currentLoadScene = firstLoadScene;
// 异步加载
currentLoadScene.assetReference.LoadSceneAsync(LoadSceneMode.Additive);
}
标签:场景,void,private,2D,Unity,引擎,GameSceneSO,public,加载
From: https://www.cnblogs.com/xinlindeyu/p/18028090