Unity引擎2D游戏开发,场景加载后的执行逻辑

非强专业性文章,本文仅供学习与交流使用

判断场景是否加载完毕

加载新场景的返回值中,有一个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);
}
相关推荐
北冥没有鱼啊8 天前
UE 像素和线框盒子 材质
c++·ue5·游戏开发·虚幻·材质
大飞pkz8 天前
【Unity】使用XLua进行热修复
unity·c#·游戏引擎·lua·游戏开发·xlua·lua热修复
工藤新一¹10 天前
C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 19)
开发语言·c++·游戏引擎·游戏开发·sdl
大飞pkz12 天前
【Unity】使用XML进行数据读存的简单例子
xml·unity·c#·游戏引擎·游戏开发·数据读写
大飞pkz13 天前
【Unity】如何解决UI中的Button无法绑定带参数方法的问题
ui·unity·游戏引擎·游戏开发·开发记录·button绑定
大飞pkz13 天前
【Unity】使用LitJson保存和读取数据的例子
unity·游戏引擎·游戏开发·数据保存和读取·游戏中的数据处理·类似jsonunility
大模型铲屎官14 天前
Unity C# 与 Shader 交互入门:脚本动态控制材质与视觉效果 (含 MaterialPropertyBlock 详解)(Day 38)
c语言·unity·c#·交互·游戏开发·材质·shader
Thomas游戏开发15 天前
Unity3D Timeline扩展与自定义事件处理
前端框架·unity3d·游戏开发
龙智DevSecOps解决方案16 天前
CI/CD解决方案TeamCity在游戏开发中的应用价值与优势分析
ci/cd·游戏开发·jetbrains·持续集成·teamcity
工藤新一¹16 天前
C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 14)
开发语言·c++·游戏引擎·游戏开发·sdl·实践项目