非强专业性文章,本文仅供学习与交流使用
判断场景是否加载完毕
加载新场景的返回值中,有一个Completed事件方法。可以创建一个方法去注册这个事件方法,即可在加载完毕后进行一系列的操作
c#
private void LoadNewScene()
{
// 加载新场景
var loadingOperation = targetSceneToGo.assetReference.LoadSceneAsync(LoadSceneMode.Additive, true);
loadingOperation.Completed += OnLoadComplete;
}
将首次转换的目的场景复制到当前场景,并将目的地坐标赋予给玩家的坐标位置
c#
// 玩家坐标
public Transform playerTrans;
private void OnLoadComplete(AsyncOperationHandle<SceneInstance> handle)
{
currentLoadScene = targetSceneToGo;
playerTrans.position = targetPositionToGo;
if (fadeScreen)
{
// TODO:淡出
}
}
将Player拖入到PlayerTrans
中,获取玩家坐标
防止传送过程中,反复点击反复加载
添加一个全局变量,用于标识是否在加载中
c#
private bool isLoading;
在OnLoadRequestEvent()
方法中,添加几行代码用于判断是否正在加载
c#
private void OnLoadRequestEvent(GameSceneSO sceneToGo, Vector3 positionToGo, bool fadeScreen)
{
// 如果正在加载,则不执行加载过程中的任何操作
if (isLoading)
{
return;
}
isLoading = true;
targetSceneToGo = sceneToGo;
targetPositionToGo = positionToGo;
this.fadeScreen = fadeScreen;
// 卸载当前场景,装载下一个场景
StartCoroutine(UnloadPreviousScene());
}
在UnloadPreviousScene()方法中,关闭人物
c#
private IEnumerator UnloadPreviousScene()
{
if (fadeScreen)
{
// TODO:实现淡入
}
// 等待淡入淡出的指定时间
yield return new WaitForSeconds(fadeTime);
// 非空判断
yield return currentLoadScene.assetReference.UnLoadScene();
// 关闭人物
playerTrans.gameObject.SetActive(false);
LoadNewScene();
}
在OnLoadComplete()
方法的末尾,将标识置为false,并启动人物
c#
private void OnLoadComplete(AsyncOperationHandle<SceneInstance> handle)
{
currentLoadScene = targetSceneToGo;
playerTrans.position = targetPositionToGo;
// 启动人物
playerTrans.gameObject.SetActive(true);
if (fadeScreen)
{
// TODO:淡出
}
// 加载完毕,则把标识置为false
isLoading = false;
}
解决传送后,头顶仍旧有按键提示的问题
在ButtonSign中,添加OnDisable()
方法,将触发标识置为false
c#
private void OnDisable()
{
canPress = false;
}
传送回第一个场景
在第二个场景中,添加Empty Object,并绑定上Teleport Point脚本,注意调整传送点的坐标
添加Box Collider 2D,调整碰撞体边界,并调整Tag为Interactable
解决摄像机边界的问题
在CameraControl中的Start()方法内,需要做一些场景切换后的工作。需要创建一个事件,作为场景加载后需要执行的事件,来通知所有注册的方法
在Events文件夹中,新建一个VoidEventSO
在SceneLoader
脚本中,添加一个广播,用于发出传送后的处理事件
c#
[Header("广播")]
public VoidEventSO afterSceneLoadedEvent;
在OnLoadComplete()
方法的末尾处,添加一行代码,用于唤起事件
c#
// 场景加载完成后的事件
afterSceneLoadedEvent.RaiseEvent();
在CameraControl脚本中,添加一个监听
c#
[Header("事件监听")]
public VoidEventSO afterSceneLoadedEvent;
进行注册和销毁
c#
private void OnEnable()
{
cameraShakeEvent.OnEventRaised += OnCameraShakeEvent;
afterSceneLoadedEvent.OnEventRaised += OnAfterSceneLoadedEvent;
}
private void OnDisable()
{
cameraShakeEvent.OnEventRaised -= OnCameraShakeEvent;
afterSceneLoadedEvent.OnEventRaised -= OnAfterSceneLoadedEvent;
}
在OnAfterSceneLoadedEvent()
方法中,调用获取摄像机边界的方法
c#
private void OnAfterSceneLoadedEvent()
{
GetNewCameraBounds();
}
/// <summary>
/// 切换场景时,获取新的摄像机边界
/// </summary>
private void GetNewCameraBounds()
{
var obj = GameObject.FindGameObjectWithTag("Bounds");
if (null == obj)
{
return;
}
confiner2D.m_BoundingShape2D = obj.GetComponent<Collider2D>();
// 清除边界缓存
confiner2D.InvalidateCache();
}
解决刚开始没有摄像机边界的问题
在目前的代码内,加载场景并没有触发创建摄像机边界的事件,只有在创建场景结束后才触发
创建NewGame()方法,新建人物初始化坐标变量。在方法内调用OnLoadRequestEvent()场景加载事件请求方法,将目标场景和人物的初始化坐标变量传入进去即可解决
c#
public Vector3 firstPosition;
private void NewGame()
{
targetSceneToGo = firstLoadScene;
OnLoadRequestEvent(targetSceneToGo, firstPosition, true);
}