第二十二章:附加内容

1. 本章核心目标

本章的核心在于为游戏项目增加四个独立的系统,旨在深化游戏的可玩性和提升项目的完整性与可维护性。

  • 显性目标 (玩家体验):

    1. 可配置服务器: 允许服务器管理员(通常也是玩家)通过外部文件自定义服务器名称、地图、玩家上限及游戏倍率,提升了多人游戏的个性化和管理便捷性。

    2. 游泳系统: 玩家角色现在可以在水体中游泳,增加了世界的探索维度和真实感。

    3. 地表脚步系统: 玩家在不同材质(如草地、沙地、木板)上移动时,会产生对应的脚步声和粒子特效,增强了环境的沉浸感和反馈。

    4. 种植系统: 玩家可以放置种植盆,播种、施肥并等待作物分阶段生长,最终收获,丰富了生存和资源管理的玩法。

  • 隐性目标 (技术与战略):

    1. 解耦配置与逻辑: 将服务器配置从蓝图的硬编码中分离出来,便于非开发人员调整,是产品化和长期运营的重要一步。

    2. 扩展物理与动画系统: 引入物理材质和动画通知(Anim Notify)的联动,探索更精细的物理-动画交互实现。

    3. 设计模式复用与数据驱动: 复用并扩展了类似“熔炉”的“处理站”设计模式,并引入数据表(Data Table)来管理作物生长阶段的网格体,强化了数据驱动设计的思想。

    4. 补全核心生存玩法循环: 种植系统为游戏后期的资源循环提供了新的维度,使生存体验更加完整。

目标关系图:

显性目标 (玩家层面) 隐性/战略目标 (开发/项目层面)
1. 可配置服务器 解耦配置与逻辑,提升项目可维护性与运营便利性。
2. 游泳系统 增强角色控制器,解决引擎特定模式的局限性。
3. 地表脚步系统 扩展物理与动画系统的综合应用,提升环境交互的实现深度。
4. 种植系统 复用设计模式,实践数据驱动设计,补全核心玩法循环。

2. 系统与功能实现

本章实现了以下四个核心系统,并与前期系统进行了深度交互。

系统/功能 描述 与前期系统的交互/依赖
专用服务器配置文件系统 通过启用 JSON Blueprint Utilities 插件,在 GameInstance 中实现了在创建会话前读取外部 server-config.json 文件的功能。 系统能解析服务器名、地图、最大连接数及各项倍率(如采集、经验),并为监听服务器提供了备用方案,即从UI获取倍率设置。 - 修改了 GameInstance 中的 Create Advanced Session 流程。
- 依赖于 GameMode 来区分专用服务器和监听服务器。
- 影响了 角色经验获取 (Add Experience) 和资源采集 (Add Resources) 的最终数值计算。
游泳系统 BP_OceanSwimming 蓝图中使用盒体碰撞器触发角色进入/离开游泳状态。 角色通过接口调用进入游泳状态后,会切换动画状态机至游泳姿态,并将其移动模式设置为Flying(飞行)以规避原生Swimming模式的Bug。 移动输入逻辑被修改,以允许玩家通过视角朝向控制上浮和下潜。 - 依赖于 动画蓝图中的状态机来切换动画。
- 修改了 角色蓝图中的移动输入逻辑。
- 扩展了 角色控制器的状态管理(通过新增 isSwimming 布尔值)。
地表脚步系统 定义了一系列物理材质(沙、草、水、木、石、金属),并将它们分配给场景中的不同对象(如地貌、建筑部件)。 在行走/奔跑动画中添加Footstep动画通知,在动画蓝图中捕获此通知,并向下发射射线检测,根据检测到的物理表面类型,播放对应的声音和Niagara粒子特效。 - 深度依赖 UE的物理材质(Physical Material)系统。
- 依赖于 动画蓝图的动画通知(Anim Notify)机制。
- 扩展了 游戏中几乎所有可供行走的静态网格体和地貌的资产设置。
作物种植系统 通过复制和修改“熔炉”蓝图实现。 这是一个基于定时器和状态机(使用isSeeded, isGrowing, isFruiting等布尔值)的系统。 它根据配方检查库存中的种子和肥料,在不同生长阶段通过异步加载并切换不同的植物网格体。 当作物成熟后,系统会周期性地将产物添加到库存中。 - 复用并修改了“熔炉”系统(一个处理站)的逻辑框架。
- 物品系统(Data Asset)、库存系统、配方系统紧密耦合。
- 引入了 数据表(Data Table)来管理与物品ID关联的生长阶段网格体,实践了数据驱动。

3. 关键设计思想

本章的实现体现了多种重要的设计原则和模式,提升了代码的灵活性和可扩展性。

设计思想 描述与应用实例
设计原则
配置优于硬编码 应用: 服务器配置系统。 将服务器名、倍率等易变数据从蓝图逻辑中移至外部JSON文件,使非程序员也能轻松修改服务器设置,提高了灵活性和可维护性。
数据驱动设计 应用: 脚步系统和种植系统。使用物理材质定义地表属性,使用数据表定义作物各阶段的视觉表现(网格体)。这使得添加新的地表类型或新作物时,只需修改数据资产,而无需更改核心蓝图逻辑。
单一职责原则 应用: 各系统职责分离。例如,脚步声和特效的触发逻辑被封装在动画蓝图中,因为它直接响应动画事件(AnimNotify),职责清晰。
设计模式
状态模式 (State Pattern) 应用: 作物种植系统。通过 isSeededisGrowingisFruiting 等一系列布尔变量,清晰地定义了作物从“空地”到“播种”、“生长”、“结果”再到“枯萎”的完整生命周期状态,并根据不同状态执行不同逻辑(如切换模型、产出物品)。
观察者模式 (Observer Pattern) 应用: 脚步系统。动画系统作为“被观察者”,通过 AnimNotify (“通知”),在特定时间点(脚落地时)通知动画蓝图这个“观察者”去执行特定逻辑(播放声效和特效)。
策略模式 (Strategy Pattern) 应用: 脚步系统。Select 节点根据输入的物理表面类型(EPhysicalSurface),选择并执行不同的“策略”(播放哪种声音、生成哪种特效)。这是策略模式的一种简化实现,将算法的选择与执行分离开。

4. 核心技术点与难点

本章的开发过程涉及多个具体的技术挑战,并通过特定方法得以解决。

核心技术点/难点 描述 解决方案与实现
启用C++插件与项目重新编译 服务器配置功能需要 JSON Blueprint Utilities 插件,而启用这类含C++代码的插件,要求从IDE (Visual Studio) 中手动重新编译整个游戏项目。 1. 在UE编辑器中启用插件并重启。
2. 关闭UE编辑器,在Visual Studio中打开项目的 .sln 文件。
3. 在解决方案资源管理器中,右键点击项目并选择“生成”(Build)来完成编译。
规避引擎内置游泳模式的Bug 开发过程中发现,引擎默认的 Swimming 移动模式存在问题(被描述为 “buggy”)。 使用 Flying (飞行) 移动模式作为替代方案。 同时,重写了部分移动输入逻辑,将玩家的视角俯仰(Pitch)与角色的Z轴移动关联起来,从而实现了通过抬头和低头来控制上浮和下潜。
动态异步加载资源 在种植系统中,当作物进入下一个生长阶段时,需要切换其静态网格体。如果同步加载,可能会导致游戏瞬间卡顿,影响体验。 使用 Async Load Asset (异步加载资产) 节点来加载下一阶段的植物网格体。 加载完成后,通过其 Completed 回调引脚来执行设置网格体的逻辑,从而避免了对游戏主线程的阻塞。
物理材质与动画通知的联动 脚步系统的核心是精确地在脚接触不同地面时触发相应的效果。 1. 材质定义: 利用UE的物理材质系统为不同表面(地貌层、建筑模型)打上“标签”。
2. 事件触发: 在动画序列的精确帧(脚落地时)添加 AnimNotify 作为事件触发点。
3. 信息获取: 在动画蓝图中响应通知,并从角色脚下进行向下射线检测,从命中结果中获取表面的物理材质信息。

5. 自我批判与重构

本章的实现虽然功能完整,但也暴露出一些设计和实现上的问题,为未来的优化提供了方向。

  • 遇到的“坑”与关键问题:

    1. 繁琐的手动操作: 脚步系统要求为每一个行走/奔跑相关动画手动添加多个动画通知,这是一项重复性高且容易出错的工作。

    2. 资产准备流程复杂: 种植系统的植物模型需要通过 Quixel Bridge 插件获取,并涉及到引擎重启、项目重新编译和手动合并Actor等多个步骤,流程繁琐且对不熟悉的用户不友好。

    3. 设计迭代中的局限: 种植系统的逻辑最初在函数内实现,后因需要使用 Async Load 节点(该节点不能在函数中使用)而被迫迁移到事件图表中,这反映了初期设计的局限性。

    4. 对引擎Bug的妥协: 游泳系统直接放弃了原生的 Swimming 模式,转而使用 Flying 模式作为权宜之计,这并非一个根本性的解决方案。

  • 反思与重构建议:

问题点 如果重来一次的优化方案
脚步动画通知繁琐 放弃使用 AnimNotify。改为在角色蓝图的 Tick 事件中,实时检测脚部骨骼插槽(Socket)与地面的距离。当距离小于某个阈值时,触发一次脚步效果检测。这种方法与具体动画解耦,无论更换或新增何种移动动画,脚步系统都能自动生效。
种植系统状态管理 当前使用多个布尔值(isSeeded, isGrowing等)来管理状态,当状态增多时容易出错。 优化方案: 使用**枚举(Enum)**类型(如 E_GrowthState)来定义作物的状态(Empty, Seeded, Growing, Fruiting, Dead)。这样状态管理更清晰、更安全,且易于扩展。
游泳系统的实现 深入研究原生 Swimming 移动模式的问题根源并尝试修复它,或者构建一个更完整的自定义移动组件(Custom Movement Component),而不是简单地复用 Flying 模式,以获得更精确和可控的游泳物理表现。
数据耦合问题 当前生长所需时间、肥料消耗等逻辑数值部分硬编码在蓝图中。 优化方案: 将这些参数也移到数据资产(如 RecipeCrop Plot 的数据表)中,实现完全的数据驱动。这将使得平衡性调整和添加新作物变得极为高效,无需再修改蓝图。