【unity】学习制作2D横板冒险游戏-8-

场景加载后的执行逻辑

传送后坐标

场景加载后,重新给变量赋值,将当前场景,方便进行卸载和加载;将坐标更新,使人物到正确的位置

LoadSceneAsync 是一个方法,用于异步加载场景。这个方法需要两个参数:
第一个参数是LoadSceneMode.Additive,表示加载场景的模式是添加式的。这意味着新的场景会被添加到当前已经加载的场景列表中,而不是替换当前场景。
第二个参数是true,表示在加载场景时,是否应该激活场景中的所有对象。在这个上下文中,true意味着加载后场景中的对象将被激活。
loadingOption 是一个变量,用于接收LoadSceneAsync方法返回的AsyncOperation对象。这个对象可以用来追踪加载的进度和状态。

Completed是一个事件,当异步加载操作完成时会被触发。当场景加载完成时,Unity会自动调用OnLoadCompleted方法。

实例化

运行,人物到达了正确的位置

在传送门前时连续按E会导致场景跳转多次发生卡顿
解决思路是创建一个bool值只允许加载一次

已经在加载就return

加载完成后为false

完成,现在传送时狂按E也只会加载一次

传送回去

先复制一下坐标

创建一个GameObject并赋值

添加碰撞体触发器

修改标签

运行测试,完成!实现了两场景直接的互相传送

相机边界修改

在传送到新的场景后,走两步发现摄像机不跟着人物移动了,原因是因为摄像机的边界还是第一场景的边界范围

创建一个事件用来通知摄像机进行范围的修改
在该事件中不含传递的变量,直接使用以前创建的voidSO类型

在场景加载中添加一个广播

场景加载完成后进行播报

在摄像机控制脚本中添加监听

实例化


并给地图设置各自的范围

完成

新的游戏

在游戏开始时,人物应该在正确的位置,并且为后续做开始界面的菜单做准备
创建一个新的函数方法,在开始时加载场景和人物并淡入淡出

调用方法

在该方法中已经有加载场景的代码了,把Awake的删掉

实例化

成功,开局到了正确的位置

淡入淡出效果

场景切换时淡入淡出
创建一个新的UI画布

该画布应该在最上层,以实现黑屏的效果

Canvas组件Sort Order属性,这个值决定了UI元素的渲染顺序。数值越大的Canvas会被后渲染,也就是显示在更前面。

创建一个图片

大小为全屏
按住alt和shift选择右下角的填充全屏

修改颜色为黑色

在该选项中,修改透明度可以实现淡入淡出的效果

取消勾选Raycast Target

控制UI元素是否参与射线检测(点击/触摸事件)
如果有需要点击的UI按钮jiu

创建代码脚本

挂载

想要调用UI就要先调用命名空间

赋值

下载安装一个插件

设置应用

API手册

https://dotween.demigiant.com/

调用插件命名空间

使用插件的方法去修改颜色实现渐变

DOBlendableColor(target, duration) 是 Unity 中 DOTween 插件的一个方法,用于实现颜色混合渐变动画。在指定时间内(duration),将目标对象(target)的颜色从当前值平滑过渡到目标颜色,支持叠加混合(如叠加高光、阴影等)。

还是用事件的方法去完成该函数的调用
创建一个SO文件代码如图所示

在需要淡入淡出的场景加载中广播

注册事件方法

添加事件

实例化

成功淡入淡出

主菜单

创建一个场景用来当作主菜单的背景

绘制场景
先放置如图三个素材

按住V可以进行顶点吸附使其变成一张完整的素材

加上地面和其他装饰,绘制场景如下

TextMeshPro

TextMeshPro (TMP) 是一个专为高效文本渲染设计的插件,旨在替代 Unity 原生的 TextMesh 和旧版 UI Text 组件。它通过更先进的文本处理技术和丰富的功能,解决了传统文本系统在性能、样式和灵活性上的不足

在菜单上应该有开始游戏等文字,因此在画布上添加

导入包

在组件中输入中文会导致报错

因为在自带的字体资产中并没有中文字体

因此需要手动添加字体
下载哔哩哔哩Up主oooooohmygosh的开源字体得意黑

视频链接:https://www.bilibili.com/video/BV1sP411g7PZ/?spm_id_from=333.337.search-card.all.click&vd_source=be497ddee8587e2dfed1d1e65134af32
下载链接:https://atelier-anchor.com/typefaces/smiley-sans

创建一个文件夹用来存放字体

将.ttf文件添加

鼠标右键创建unity的适配字体资源

调用字体

输入游戏名称

成功在画布显示

调整大小

颜色渐变效果

最终演示如图

在添加一个文本newGame

在添加一个文本Continue

在添加一个文本Exit

添加父级Button统一管理

添加组件控制子物体排列

添加button组件使其有按钮功能

经测试无法被检测,调整检测范围与字体相符合

在button中设置被触发的颜色变化

现在,游戏开始时加载的场景应为菜单场景,因此添加一个MenuSO

在Addressables中添加场景

设置SO

设置第一个加载场景为menu

修改人物初始坐标

完成,现在成功显示到了主菜单界面

修改一些菜单的小问题

解决人物场景加载可以移动的问题

在人物控制中进行事件监听,如果场景加载,人物无法移动,加载后,人物才可以移动

注册事件

禁止控制器的方法

监听恢复事件

注册

启动方法

解决菜单面板出现人物血条的问题

还是监听场景加载的事件

如果场景加载是菜单,就不显示血条,如果不是菜单就显示血条

实现新的游戏

first position应该是第一次场景加载时的坐标
因此创建menuposition用来加载菜单的坐标

同理创建菜单场景变量

游戏运行加载menu场景

newgame中加载游戏场景

运行后成功菜单界面

创建一个没有返回值的事件用来新的游戏

在newgame中启动该事件

添加事件监听

注册

经测试成功运行
但是在点击新游戏的瞬间,血条就显示了,应该在卸载完场景黑屏后才进行加载
创建一个事件用来管理场景卸载后的事情

广播

等待场景完全变黑后进行广播

修改UI的监听

经测试成功运行
在点击新的游戏之后,人物的血量也应该恢复到百分百状态
在Character脚本中进行修改

原脚本中血量是在start代码中执行的,现在修改名字为newgame,因为我不希望加载游戏也会重置血条

注册事件

给人物实例化事件

给野猪从Prefeb中添加

存储点

切割素材

添加碰撞体触发器

设置标签

创建代码

逻辑和宝箱打开关闭的逻辑一致

实例化

代码修改如下

经测试无法运行,检查后发现颜色不知道什么时候被修改了导致图片颜色还是黑色

修改成白色后成功

解决存档后还显示互动的问题
思路和箱子思路一样,修改一下标签即可

成功

优化显示

对于存储石头亮起的感觉,并没有那么好看,因此进行画面的后处理和灯光效果
对于石头上的标志创建一个灯光

修改一下灯光的颜色和强度

效果如图

创建一个全局管线

新建一个管线文件

添加光晕效果

在摄像机中启动后处理光效

调整泛光阈值

Threshold:控制触发泛光的亮度阈值(0-1,值越低泛光范围越大)。
Intensity:泛光强度(过高会导致画面发白)。
Diffusion:光晕扩散程度(值越大光晕越散)。
Tint:为泛光添加颜色(如让火焰泛红光)。

但是,只有当激活的时候才有光效会更自然,有一种亮灯的效果
代码如下

实例化

运行,成功

数据结构和坐标的存储加载

创建一个存储接口

代码如下

创建数据的管理类

添加脚本

在单例模式中,instance 是一个静态的全局变量,用于存储该类的唯一实例。通过将它声明为 public static,可以在整个项目的任何地方通过类名直接访问该变量,

if (instance == null):检查当前是否已经有一个实例存在。instance 是一个静态变

量,用于存储该类的唯一实例。

instance = this;:如果当前还没有实例存在(instance 为 null),则将当前对象

(this)赋值给 instance。这样,instance 就持有了当前对象的引用。

else 块:如果instance不为 null,说明已经有一个实例存在了。

Destroy(this.gameObject);:销毁当前的游戏对象。这是因为在 Unity 中,一个场景中可

能存在多个相同的脚本附加到不同的游戏对象上,而我们只希望保留一个实例。通过销毁多余的游戏对象,可以确保场景中只有一个实例。

RegisterSaveData:
检查对象是否已经在列表中,如果不在,则添加。
这样可以确保每个对象只被注册一次。
UnRegisterSaveData:
检查对象是否在列表中,如果在,则移除。
这样可以确保对象在不需要时被正确移除。

观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种对象间的一对多依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。

可以直接在接口中编写注册类,并给类一个默认的接口方法

:在 C# 8.0 及更高版本中,接口可以包含默认实现的方法。这意味着实现该接口的类可以选择使用这些方法的默认实现,也可以重写它们以提供自定义行为。

两种写法都正确,第二种是简写

保存的列表:定义一个名为 saveablelist 的公共列表,该列表用于存储实现了 ISaveable

接口的对象。

List<ISaveable>:List<T> 是 C# 中的一个泛型集合类,用于存储一组特定类型的对象。在

这里,T 被替换为 ISaveable,表示这个列表将存储ISaveable类型的对象。

= new List<ISaveable>();:这部分代码初始化了 List<ISaveable> 对象,并

将其分配给saveablelist变量。这意味着在创建包含这个列表的类的实例时saveablelist 将自动被初始化为一个空列表。

编写加载场景的代码

创建一个脚本用来保存数据类型
用字典保存坐标

在保存坐标前我们还创建了string类型用来区分坐标,如果用名称来区分坐标显然是不可取的的,比如在地图上我们可能会有很多的野猪不可能用野猪1``野猪二等等来改名,因此使用unity自带的GUID是个很好的办法,就像QQ号一样,每个人都不会重复

创建生成GUID的代码
调用 System.Guid.NewGuid() 生成一个新的 GUID。
使用 .ToString() 方法将 GUID 转换为字符串。

返回unity将脚本挂载到Player上,即可发现已经生成了一串字符串
只要不清空字符串,那么就不会生成新的ID,就不用担心ID会改变

接口中调用DataDefination用来返回ID

因为要保存角色的坐标数据,所以Character脚本要继承接口

返回ID

在接口中注册和注销的代码如果添加了方法, 就有了默认接口方法,自动填补代码会自动掠过这两个类,直接在注册和注销中使用默认接口方法

保存的方法
GetSaveData旨在将某个对象的位置数据存储在一个Dictionary中,该字典以 GetDataID().ID 作为键。data.characterPosDirct.ContainsKey(GetDataID().ID) 是一段用于检查字典中是否存在特定键的代码。ContainsKey 方法: Dictionary 类提供的一个方法,用于检查字典中是否存在指定的键。

这是在Character脚本中进行保存数据的方法,在广播到数据管理的脚本后,我们应该接收传递的数据并且保存在列表中
在DataManager中编写保存数据的脚本

并且还要监听数据

在savepoint中进行广播

实例化事件

事件的注册

创建数据容器

保存和加载数据的代码

运行游戏,数据正常输出

为了验证成功保存的数据,设置按L可以回到保存的坐标位置

经测试,成功返回
代码逻辑如图

posted @ 2025-03-29 15:39  plusu  阅读(136)  评论(0)    收藏  举报