第十一章: 物品制作

1. 本章核心目标

本章的核心任务是为游戏实装一个多样化且功能丰富的可交互物品系统,涵盖了从远程武器到采集工具的多个类别。

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

    • 丰富战斗方式: 为玩家提供包括步枪、火箭筒、弓、矛在内的多种远程武器,每种武器都具备独特的射击、瞄准和装填机制,显著提升了战斗的策略性和趣味性。

    • 建立资源循环: 引入了从基础(石器)到进阶(铁器)的采集工具(石斧、石镐、铁斧、铁镐),使玩家能够高效地与世界资源进行交互,为后续的生存和建造系统奠定基础。

    • 提供初始工具: 玩家默认会生成一个石头(Rock),作为游戏初期的基础工具,引导玩家进行最基本的资源采集。

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

    • 构建可扩展的武器框架: 最大的战略目标是建立一个可复用、可扩展的武器基类(BP_WeaponAimMaster)。通过将通用的瞄准逻辑(如第三人称越肩视角、第一/三人称ADS缩放、瞄准时减速)抽象到父类中,极大地简化了未来新增远程武器的开发流程。

    • 实现模块化的动画系统: 在动画蓝图中利用 Layered blend per bone 技术,实现了上下半身动画的分离与融合。这使得角色可以在执行跳跃、蹲伏等下半身动作的同时,保持上半身的持握与瞄准姿态,提升了动画表现的真实感和流畅度。

    • 深化伤害计算系统: 建立了一个基于物理表面的精准伤害系统,能够根据命中部位(如头部、胸部)应用不同的伤害乘数,并结合护甲进行伤害减免,为游戏后期的PVP/PVE平衡性设计打下了坚实基础。


2. 系统与功能实现

本章实现的核心系统涵盖了武器、动画、伤害及弹药管理,并与前期系统紧密耦合。

实现系统/功能 详细描述 与前期系统的交互与依赖
通用武器瞄准系统 基于BP_WeaponAimMaster实现。提供了通用的第三人称越肩镜头偏移第一/三人称瞄准(ADS)逻辑(通过Timeline平滑过渡镜头FOV和位置)及瞄准时减速 功能。 依赖角色蓝图中的Spring Arm和Camera组件。通过**接口(Interface)调用角色蓝图中的函数来设置镜头偏移和移动速度。
远程武器功能 - 步枪: 实现自动开火、弹夹式装填逻辑。
- 火箭筒: 发射物理弹道抛射物,可对建筑造成范围伤害。
- 弓: 实现了长按蓄力拉弓、松手射击的机制。
- 矛: 具备近战刺击和蓄力投掷两种攻击模式。
交互于库存系统**,在装填弹药时消耗对应的弹药物品。
交互伤害系统,对其他玩家或建筑造成伤害。
依赖动画蓝图来播放特定的攻击、装填动画。
采集工具功能 实现了石头、石斧/镐、铁斧/镐等工具。这些工具继承自统一的工具基类,具备对特定资源(树木、矿石)的采集能力和效率分级。 交互于前期搭建的资源系统 (Harvesting System),根据工具类型和等级决定采集效率和掉落物。
依赖动画蓝图来播放挥砍/敲击动画。
动画混合系统 在动画蓝图中,通过Layered blend per bone节点,以spine_01为分界,将上半身的持械/瞄准动画与下半身的移动/跳跃/蹲伏动画进行混合。 依赖角色蓝图提供的状态变量(如isAiming, isCrouching)作为混合的判断依据。
精准伤害系统 - 客户端射线检测: 从客户端镜头中心发出射线,将命中信息传递给服务器,保证“所见即所得”的射击体验。
- 物理表面判定: 利用物理资产(Physics Asset)和物理材质(Physical Material)为角色不同身体部位(头、胸、四肢)添加标签。
- 伤害计算: 服务器根据射线命中的物理材质,应用不同的伤害乘数(如爆头),并检查玩家是否装备护甲以进行伤害减免。
交互玩家属性系统,最终将计算出的伤害值施加于玩家的生命值上。
依赖于角色的物理资产配置。

3. 关键设计思想

本章的设计体现了面向对象和接口驱动的编程思想,旨在构建一个高内聚、低耦合的系统。

设计原则/模式 应用实例 目的与优势
继承与多态 - 武器层级: BP_EquippableMaster -> BP_WeaponAimMaster -> BP_RifleMaster/BP_Bow
- 工具层级: BP_HatchetMaster -> BP_Rock/BP_IronHatchet
实现了代码的最大化复用。所有可装备物品共享基础逻辑,远程武器共享瞄准逻辑,具体武器只需实现其独特功能,结构清晰,易于管理。
依赖倒置 (接口驱动) 角色蓝图不直接引用任何具体的武器类(如BP_RifleMaster),而是通过BPI_EquippableItem接口与当前装备的物品通信(如调用UseItem, ReloadItem等函数)。 解耦。角色蓝图与具体武器实现完全分离。未来添加任何新武器,只要它实现了该接口,就能被角色蓝图无缝地使用,无需修改任何角色蓝图代码。
单一职责原则 - BP_WeaponAimMaster仅负责瞄准。
- BP_RifleMaster仅负责步枪的开火与装填。
- BP_ArrowProjectile仅负责箭矢的飞行、命中和伤害逻辑。
- 角色蓝图仅负责接收输入和管理玩家状态。
每个类或蓝图的职责清晰明确,使得代码更易于理解、测试和维护。当需求变更时,只需修改相应职责的类。
开放/封闭原则 武器系统对扩展是开放的(可以随时创建BP_WeaponAimMaster的子类来增加新武器),但对修改是封闭的(添加新武器不需要修改BP_WeaponAimMaster或角色蓝图的核心逻辑)。 保证了核心系统的稳定性。在不断迭代和添加新内容的过程中,不易引入新的Bug到现有功能中。

4. 核心技术点与难点

本章涉及多个网络同步和动画融合的关键技术,并解决了一些实现过程中的难点。

技术点/难点 描述与解决方案
核心技术: 客户端权威的射击 为了解决网络延迟导致的射击偏差(服务器与客户端所见的玩家位置不一致),采用了客户端先行的射线检测方案。实现方法: 在客户端获取摄像机精确的旋转角度,通过RPC(远程过程调用)将该角度传递给服务器。服务器以此角度为基准进行射线检测,从而确保射击结果与玩家瞄准的位置一致。
核心技术: 上下半身动画融合 为了让角色在移动或跳跃时仍能自然地持握和瞄准武器,使用了动画蓝图中的Layered blend per bone节点。实现方法: 以脊椎骨骼(spine_01)为界,将上半身的武器姿态动画和下半身的移动动画进行分层混合,实现了流畅、自然的全身动作表现。
难点1: 第一人称瞄准位置校准 问题: 在第一人称模式下瞄准时,武器的瞄具没有精确对准屏幕中心。
解决方案: 这是一个两步校准过程。首先,直接修改武器的站立动画 (Rifle_Idle),微调spine_03骨骼的旋转,使武器在静止时就与镜头方向大致对齐。然后,在武器蓝图(BP_WeaponAimMaster)中,通过微调第一人称瞄准镜头位置变量 (FP_AimDownSights_Location),将镜头精确移动到瞄具后方,最终实现完美对齐。
难点2: 客户端抛射物生成位置不同步 问题: 在客户端视角下,武器发射的抛射物(如火箭、曳光弹)生成在玩家脚底,而非枪口位置。这是因为服务器获取的附属组件(武器)位置信息存在网络同步延迟。
解决方案: 对于这种主要影响视觉表现的问题,采用了信任客户端位置的策略。在开火时,由客户端获取武器枪口的准确世界坐标,并通过RPC将这个位置向量传递给服务器。服务器在生成抛射物时,直接使用客户端发来的这个坐标,从而保证了视觉上的准确性。
难点3: 切换视角时瞄准状态残留 问题: 如果玩家在按住右键瞄准时切换第一/第三人称视角,镜头的FOV和偏移会卡在瞄准状态,无法复位。
解决方案: 创建了一个名为ResetCameraPosition的接口函数。在角色蓝图的切换视角逻辑中调用此接口。武器的父类BP_WeaponAimMaster实现了该接口,其功能是强制将镜头的Spring Arm组件和FOV重置为默认值,从而解决了状态残留问题。

5. 自我批判与重构

本章的实现过程并非一帆风顺,暴露出一些设计上的不足和可以优化的空间。

遇到的问题 (‘坑’) 反思与修正 如果重来一次 (优化方案)
重复的抛射物逻辑 矛和箭的抛射物蓝图(BP_ArrowProjectile, BP_SpearProjectile)中存在大量重复逻辑,如命中检测、附加到目标身上、伤害计算等。这违反了DRY (Don’t Repeat Yourself) 原则。 提取基类: 创建一个BP_BaseProjectile基类,将所有通用的逻辑(如事件命中、伤害接口、附加到Actor)在基类中实现。然后让BP_ArrowProjectileBP_SpearProjectile继承自这个基类,各自只需定义独特的属性(如模型、速度、重力),从而消除代码冗余,提高可维护性。
硬编码的资源效果 采集工具(如石斧、石头)命中不同资源(树、矿)时产生的粒子特效和音效是硬编码在各自的蓝图中的。这导致每次新增资源类型或想修改效果时,都需要去修改工具蓝图。 数据驱动设计: 创建一个数据表 (Data Table),用于映射物理材质命中效果(粒子特效、音效)。工具在命中物体时,获取其物理材质,然后去数据表中查询对应的效果进行播放。这样,设计师就可以通过修改数据表来配置所有命中效果,完全无需修改蓝图代码。
不一致的属性管理 武器的部分属性(如伤害值、弹药ID)定义在蓝图中,而另一部分定义在数据资产(Data Asset)中。这种分散的管理方式增加了平衡性调整的难度和出错的风险。 数据资产中心化: 将所有与武器数值相关的属性(伤害、射速、弹药ID、后坐力、可破坏的建筑等级等)全部集中到数据资产中。蓝图本身只负责实现逻辑功能,所有数据均从数据资产中读取。这使得数值策划可以独立地进行游戏平衡调整,而无需接触复杂的蓝图逻辑。
网络变量的初始值问题 在UE 5.4版本中,新创建的布尔变量默认值为true,导致isUsingItem等逻辑判断在初次执行时失败,需要手动修正。此外,忘记勾选Actor的**“Replicates”**选项也是一个常见且致命的失误。 建立开发规范: 团队应建立严格的开发检查清单(Checklist)。对于所有新建的网络功能蓝图,必须检查:1) Actor是否勾选"Replicates";2) 所有作为状态机的布尔变量初始值是否正确设置。通过流程来避免这类低级但影响严重的问题。