当前位置: 首页 > news >正文

麦田物语学习笔记:创建TransitionManager控制人物场景切换

基本流程

        制作场景之间的切换

1.代码思路

        (1)为了实现不同场景切换,并且保持当前的persistentScene一直存在,则需要一个Manager去控制场景的加载和卸载,并且在加载每一个场景之后,都要将当前的场景Set Active Scene,保证其为激活的场景,在卸载的时候也可以方便调用当前激活的场景,然后把它卸载掉

        (2)每次创建一个新的场景之后都要去Build Settings当中,将所有创建的场景都添加到这个列表当中

        (3)由于游戏的场景是逐一叠加的,那么异步加载的模式就为Additive(在原有的场景当中叠加)

        (4)场景之间切换是通过碰撞触发的,需要指定切换后的场景和坐标

        (5)切换场景需要用一个新的脚本来控制,它所需要的变量有目标场景名,目标坐标,要注意在卸载场景的时候人物是不能被玩家控制的,还需要注意的是,在传送过程中选中物品的情况(举起物品),也就是说要在卸载场景之前,恢复player的基本动画(AnimatorOverride.cs),取消物品的高亮显示(InventoryUI.cs)

2.代码实现

TransitionManager.cs

namespace FuliFarm.Transition
{public class TransitionManager : MonoBehaviour{//游戏开始的场景public string startSceneName = string.Empty;private void Start(){StartCoroutine(LoadSceneSetActive(startSceneName));}private void OnEnable(){EventHandler.TransitionEvent += OnTransitionEvent;}private void OnDisable(){EventHandler.TransitionEvent -= OnTransitionEvent;}private void OnTransitionEvent(string sceneToGo, Vector3 positionToGo){StartCoroutine(Transition(sceneToGo, positionToGo));}/// <summary>/// 卸载一个场景,加载另外一个场景/// </summary>/// <param name="sceneName">目标场景</param>/// <param name="targetPosition">目标位置</param>/// <returns></returns>private IEnumerator Transition(string sceneName, Vector3 targetPosition){//呼叫卸载场景之前要做的事EventHandler.CallBeforeSceneUnloadEvent();yield return SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene());yield return LoadSceneSetActive(sceneName);//移动人物坐标EventHandler.CallMoveToPosition(targetPosition);//呼叫加载场景之后的事件EventHandler.CallAfterSceneLoadedEvent();}/// <summary>/// 加载场景并设置为激活/// </summary>/// <param name="sceneName">场景名</param>/// <returns></returns>private IEnumerator LoadSceneSetActive(string sceneName){//协成当中所有的加载场景都是异步加载yield return SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);Scene newScene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);//序号从0开始,而数量(count)是从1开始的,所以减1SceneManager.SetActiveScene(newScene);}}
}

  Teleport.cs

namespace FuliFarm.Transition
{public class Teleport : MonoBehaviour{public string sceneToGo;public Vector3 positionToGo;private void OnTriggerEnter2D(Collider2D other){if (other.CompareTag("Player")){//把目标位置和目标场景传给TransitionManager中,然后调用协成Transition,就去到了对应的场景EventHandler.CallTransitionEvent(sceneToGo, positionToGo);}}}
}

新增事件

//切换场景
public static event Action<string, Vector3> TransitionEvent;
public static void CallTransitionEvent(string sceneName,Vector3 pos)
{TransitionEvent?.Invoke(sceneName,pos);
}//卸载场景之前的事件
public static event Action BeforeSceneUnloadEvent;
public static void CallBeforeSceneUnloadEvent()
{BeforeSceneUnloadEvent?.Invoke();
}//加载场景之后的事件
public static event Action AfterSceneLoadedEvent;
public static void CallAfterSceneLoadedEvent()
{AfterSceneLoadedEvent?.Invoke();
}//传送到所在位置
public static event Action<Vector3> MoveToPosition;
public static void CallMoveToPosition(Vector3 targetPosition)
{ MoveToPosition?.Invoke(targetPosition);
}

修改SwitchBounds.cs

public class SwitchBounds : MonoBehaviour
{//注册事件private void OnEnable(){EventHandler.AfterSceneLoadedEvent += SwitchConfinerShape;}private void OnDisable(){EventHandler.AfterSceneLoadedEvent -= SwitchConfinerShape;}private void SwitchConfinerShape(){PolygonCollider2D confinerShape = GameObject.FindGameObjectWithTag("BoundsConfiner").GetComponent<PolygonCollider2D>();CinemachineConfiner confiner = GetComponent<CinemachineConfiner>();confiner.m_BoundingShape2D = confinerShape;//Call this if the bounding shape's points change at runtimeconfiner.InvalidatePathCache();}
}

 修改ItemManager.cs

public class ItemManager : MonoBehaviour
{public Item itemPrefab;private Transform itemParent;private void OnEnable(){EventHandler.InstantiateItemInScene += OnInstantiateItemInScene;EventHandler.AfterSceneLoadedEvent += OnAfterSceneLoadedEvent;}private void OnDisable(){EventHandler.InstantiateItemInScene -= OnInstantiateItemInScene;EventHandler.AfterSceneLoadedEvent -= OnAfterSceneLoadedEvent;}private void OnAfterSceneLoadedEvent(){itemParent = GameObject.FindWithTag("ItemParent").transform;}private void OnInstantiateItemInScene(int ID, Vector3 pos){var item = Instantiate(itemPrefab, pos, Quaternion.identity, itemParent);item.itemID = ID;}
}

新增Player.cs中的函数以及变量,并修改Update

    private bool inputDisable;private void OnEnable(){EventHandler.BeforeSceneUnloadEvent += OnBeforeSceneUnloadEventd;EventHandler.AfterSceneLoadedEvent += OnAfterSceneLoadedEvent;EventHandler.MoveToPosition += OnMoveToPosition;}private void OnDisable(){EventHandler.BeforeSceneUnloadEvent -= OnBeforeSceneUnloadEventd;EventHandler.AfterSceneLoadedEvent -= OnAfterSceneLoadedEvent;EventHandler.MoveToPosition -= OnMoveToPosition;}private void OnMoveToPosition(Vector3 targetPosition){transform.position = targetPosition;}private void OnAfterSceneLoadedEvent(){inputDisable = false;}private void OnBeforeSceneUnloadEventd(){inputDisable = true;}private void Update(){if(inputDisable == false)PlayerInput();SwitchAnimation();}

 AnimatorOverride.cs新增注册事件以及具体实现

private void OnEnable()
{EventHandler.ItemSelectedEvent += OnItemSelectedEvent;EventHandler.BeforeSceneUnloadEvent += OnBeforeSceneUnloadEvent;
}private void OnDisable()
{EventHandler.ItemSelectedEvent -= OnItemSelectedEvent;EventHandler.BeforeSceneUnloadEvent -= OnBeforeSceneUnloadEvent;
}private void OnBeforeSceneUnloadEvent()
{holdItem.enabled = false;SwitchAnimator(PartType.None);
}

新增InventoryUI.cs注册事件以及实现

private void OnEnable()
{EventHandler.UpdateInventoryUI += OnUpdateInventoryUI;EventHandler.BeforeSceneUnloadEvent += OnBeforeSceneUnloadEvent;
}private void OnDisable()
{EventHandler.UpdateInventoryUI -= OnUpdateInventoryUI;EventHandler.BeforeSceneUnloadEvent -= OnBeforeSceneUnloadEvent;
}private void OnBeforeSceneUnloadEvent()
{UpdateSlotHightlight(-1);
}

最终效果

可以通过门来回切换场景,在举着东西的状态下,切换场景后,人物动画以及UI的选中高亮将会被重置

补充知识点

1.协程

这个视频讲得很好,听一遍就会

2.unity代码执行顺序

图片来源

http://www.lryc.cn/news/526218.html

相关文章:

  • 后端SpringBoot学习项目-用户管理-增删改查-service层
  • 机器学习11-学习路径推荐
  • [ACTF2020 新生赛]Upload1
  • 【PyTorch】0.初识:从吃货角度理解张量
  • 医学图像分析工具09.1:Brainstorm安装教程
  • springboot基于Spring Boot的智慧养老服务系统的设计与实现
  • Linux内核中IPoIB驱动模块的初始化与实现
  • WPS计算机二级•幻灯片的基础操作
  • .NET9增强OpenAPI规范,不再内置swagger
  • 基于微信小程序的民宿预订管理系统
  • 网络(三) 协议
  • 【深度解析Java 20天速成】04_IDEA的安装与使用
  • gitlab处理空文件夹的提交或空文件夹提交失败
  • 计算机网络之链路层
  • Arduino大师练成手册 -- 读取红外接收数据
  • 【Efficient AIGC】SiTo: Similarity-based Token Pruning (AAAI-2025)
  • 数据标注开源框架 Label Studio
  • MyBatis最佳实践:MyBatis 框架的缓存
  • 基于LangGraph、Groq和Tavily打造可以调用外部搜索引擎工具的对话机器人(核心代码 万字详解)
  • 衡量算法性能的量级标准:算法复杂度
  • PHP校园助手系统小程序
  • 如何在Spring Boot项目中高效集成Spring Security
  • 【PostgreSQL内核学习 —— (WindowAgg(一))】
  • PAT甲级-1020 Tree Traversals
  • LVGL+FreeRTOS实战项目:智能健康助手(Max30102篇)
  • 人脸识别【python-基于OpenCV】
  • redis常用命令和内部编码
  • UI操作总结
  • 数据结构——实验八·学生管理系统
  • 力扣hot100-->滑动窗口、贪心