学业行迹 | 游戏编程1项目报告

游戏概述

这是一款简单有趣的游戏,玩家需拾取各类物品并将其投掷向敌人。你需要探索不同房间,找到进入最终房间的途径,击碎水晶并消灭所有敌人!

游戏分析

我选取《Doungeonball》作为参考对象,将按类别逐一描述各部分的特征,并阐述我重制这些部分所采用的技术手法。

1. 玩家控制的角色
1.1. 角色控制

1.1.1. 玩家通过W/A/S/D四个按键控制角色移动,移动时手臂会呈现跟随摆动的动画效果。

重制概述:
首先为对应角色对象添加 CharacterController 组件,随后通过 characterController.Move() 实现角色移动。对于手臂跟随效果,我运用 Vector3.Lerp()Quaternion.Slerp() 平滑处理移动手臂的位移与旋转,实现延迟跟随效果。针对移动中手臂的摆动,则通过 Mathf.Sin(Time.time * swingSpeed) * swingAmount * moveInput 计算摆动角度,将其作为偏移量叠加至跟随摄像机的平滑旋转中。

1.1.2. 玩家可拾取摄像机所指的物品,拾取时对应手臂将触发伸展动画:手臂伸向物品所在位置,将物品稳稳握入手掌,随后手臂收回。

重制概述:
首先通过 Physics.Raycast(playerCamera.transform.position, playerCamera.transform.forward, out hit, interactDistance) 获取摄像机指向的物体,再使用 GetComponent<>() 检测该物体是否包含特定组件以判断是否可拾取。若可拾取,则通过协程处理拾取动画。在协程中,机械臂通过 Vector3.Lerp() 平滑缩放Z轴以实现伸缩动作。伸展完成后,它会调用目标物体Item脚本中的拾取函数完成拾取。

1.2. 角色受伤

1.2.1. 角色受到攻击时会损失生命值。

重制概述:
武器类道具对象内写入了攻击造成的伤害值,当这些道具对象发生碰撞时,会检测碰撞对象是否使用生命值脚本。若使用,则调用该脚本中的函数,将伤害值从玩家的生命值中扣除。随后系统判定角色当前生命值是否小于等于0,若满足则调用死亡函数。此外,我添加了粒子特效和音效,以便在角色受伤时向玩家发出清晰提示。

2. 敌对角色
2.1. 史莱姆

2.1.1. 当玩家操控的角色进入特定范围时,史莱姆将通过AI导航向前跳跃攻击玩家。

重制概述:
为实现AI导航,所有敌方角色均已添加 NavMeshAgent 组件。游戏启动时,敌方角色对象将通过 GameObject.FindGameObjectWithTag(‘Player’) 自动搜索玩家对象,并使用 Vector3.Distance() 计算玩家与敌方角色间的距离。若该距离小于探测距离且大于停止距离,敌方角色将通过 agent.SetDestination(player.position) 移动至玩家位置。当距离小于停止距离时,敌方角色调用攻击函数对玩家发动攻击。原版中史莱姆采用跳跃动画移动,但因动画系统掌握不足,本次重制未还原其跳跃动画。

2.1.2. 当靠近玩家时,史莱姆会跳跃并攻击玩家。

重制概述:
当攻击函数被调用时,首先判断当前时间是否大于上次攻击时间加上冷却时间,以及当前是否处于晕眩状态。若满足攻击条件,史莱姆会调用玩家生命值脚本中的受损函数,随后通过协程处理攻击动画。在协程中,史莱姆还使用 Vector3.Lerp() 实现位移动画效果。

2.1.3. 被击中时死亡,并触发粒子特效。

重制概述:
敌方角色的受伤代码与玩家相同,详见1.2.1章节。在敌方角色的死亡函数中,通过 Instantiate() 生成对应死亡状态的粒子特效和音效预制件。

2.1.4. 玩家可拾取史莱姆并将其作为武器投掷。史莱姆在被投掷并发生碰撞后死亡。

重制概述:
此部分实现方式与其他物品类似(参见3.1.1节)。主要有两点差异:首先,额外禁用了史莱姆的攻击、移动和导航网格代理组件,确保其被拾取后无法移动;其次,史莱姆在最终触发碰撞后,会调用自身生命值脚本中的死亡函数,而非直接使用 Destroy() 方法。

2.2. 幽灵

2.2.1. 当玩家操控的角色进入特定范围时,幽灵将通过AI导航系统向玩家方向移动。

重制概述:
本节代码与史莱姆相同,详见2.1.1节。

2.2.2. 当幽灵与玩家距离缩短至特定范围后,将投掷球体。

重制概述:
幽灵发动攻击时,通过 GetComponentInChildren<Item>() 获取其子对象(所持道具)的Item脚本,随后调用该脚本中的投掷函数。

2.2.3. 投掷球体后,幽灵会搜索周围物品并拾取。

重制概述:
当幽灵手中无球时,它将通过 Physics.OverlapSphere(transform.position, itemDetectionRadius, itemLayer) 函数搜索特定层级范围内所有物体,并根据结果创建物体列表。幽灵随后遍历该列表,计算每个物体与自身的距离,最终找到最近的物体。之后幽灵将使用 agent.SetDestination() 移动至最近物体,当移动至特定距离时,会调用该物体Item脚本中的拾取函数完成拾取。

2.2.4. 被击中时死亡并触发粒子特效。

重制概述:
与史莱姆相同,详见2.1.3和1.2.1。

2.3. 蝙蝠

2.3.1. 当玩家操控的角色进入特定范围时,蝙蝠将通过AI导航系统向玩家方向移动。

2.3.2. 接近玩家时,蝙蝠会撞击并攻击玩家。

2.3.3. 被击中后死亡,并触发粒子特效。

2.4. 火焰怪物

2.4.1. 当玩家操控的角色进入特定范围时,火焰怪物将通过AI导航系统向玩家推进。

2.4.2. 在接近玩家至特定距离后,火焰怪物将发射火球。

2.4.3. 中弹后死亡并触发粒子特效。

重制述:
蝙蝠与火焰怪因制作时间有限未予重制。制作过程中发现蝙蝠与史莱姆存在相似性,火焰怪则与幽灵相似,故为节省时间仅重制了史莱姆与幽灵。

3. 物品
3.1. 球与钥匙

3.1.1. 可被拾取。

重制概述:
被拾取后,球体碰撞体将被禁用,随后作为角色手部对象的子对象,重置位置、旋转和缩放,最后将其 isKinematic 属性设为true以防止移动。

3.1.2. 碰撞角色可造成伤害。

重制概述:
球体通过碰撞体生成伤害。发生碰撞时,球体首先检测碰撞对象是否使用生命值脚本,若使用则调用该脚本中的受损函数。

3.1.3. 投掷后可实现弹跳效果,弹跳时带有粒子特效并发光。

重制概述:
为实现弹跳效果,为球体赋予物理材质并设置弹跳系数为1。每次球体碰撞发生后,通过 collision.contacts 获取碰撞点位置,并在该位置生成粒子特效。

3.2. 药剂

3.2.1. 可拾取。

重制概述:
原理与球体相同。

3.2.2. 使用后恢复生命值。

重制概述:
恢复生命值的功能写在生命值脚本中,并在液体使用时调用。

3.3. 其他物品(石头、罐子、书籍等)

3.3.1. 可拾取。

重制概述:
与球体遵循相同原理。

3.3.2. 碰撞角色可造成伤害。

重制概述:
与球体遵循相同原理。

3.3.3. 被投掷后经一次碰撞即损毁。

重制概述:
控制道具损伤的脚本包含一个布尔变量,用于决定道具是否可造成伤害并被摧毁(防止游戏初始时道具因与地面碰撞而损毁)。当玩家或敌人投掷这些道具时,该变量将设为true,使道具在下次碰撞时既能造成伤害又能被摧毁。

3.4. 炸弹(新玩法)

3.4.1. 可拾取。

重制概述:
原理与球体相同。

3.4.2. 投掷后发生碰撞时,对范围内所有敌人造成伤害,并影响范围内所有物体。

重制概述:
原理与其他物品类似,详见3.3.3节。区别在于:炸弹投掷碰撞时,会通过 Physics.OverlapSphere() 检测爆炸范围内的所有物体,遍历检查是否含有生命值脚本,若存在则调用其受损函数。遍历过程同时检测物体是否含有刚体组件,若存在则使用 AddExplosionForce() 对物体施加冲击力。

4. 场景

4.1. 场景的程序化生成

重制概述:
目前场景的程序化生成对我而言重制难度较大。但我尝试实现了场景部分元素的随机化。我专门编写了一个脚本,可在指定范围内随机生成预制件,其生成范围、数量和角度均可自由控制。未来若持续更新,该脚本可用于调整关卡内装饰物、道具和敌人的数量,从而实现难度变化。目前脚本仅应用于游戏中的装饰物和道具,因场景内的敌人需与通用门关联才能实现通用门的功能。

4.2. 最终门,被钥匙击中时开启

重制概述:
最终门脚本中加入 OnCollisionEnter 事件,当碰撞对象带有“钥匙”标签时,通过 Vector3.Lerp() 移动最终门,随后销毁碰撞对象。

4.3. 普通门,受攻击时碎裂消失

重制概述:
原版游戏中普通门受攻击后会碎裂。该效果实现难度较高。为确保游戏性,我将普通门与敌人关联:普通门脚本遍历所有关联敌人对象,当对象清空(即敌人全灭)时,门体移动开启。

4.4. 终极水晶:被击中时生成大量敌人,消灭所有敌人即可通关。

重制概述:
为实现水晶受击时生成敌人的效果,我将生命值脚本与前述预制件生成脚本附加至水晶,其中预制件生成脚本处于禁用状态。水晶拥有1点生命值,受击即“死亡”。其死亡函数中激活的预制件生成脚本将生成敌人。该脚本还包含实时遍历所有生成对象的代码,当所有敌人死亡时会自动销毁自身。所有水晶对象均在场景管理脚本中被引用,该脚本同样遍历所有水晶对象,并在对象清空(即所有水晶被摧毁)时显示通关菜单。当前游戏关卡仅使用最终水晶,但基于上述脚本架构,未来可轻松为关卡添加更多水晶以提升难度。

游戏测试

我使用收集表汇总了游戏测试的结果,以下是一些反馈:

优化建议主要集中在提示信息方面。多数玩家认为游戏中提示信息不足,难以掌握道具使用方法。这或许也是“钥匙”评分偏低的原因——玩家不了解如何用钥匙开门。为解决此问题,我在屏幕手臂下方新增提示文本,说明双臂对应的操作按钮,并告知手持道具的使用方式及效果。

有玩家反馈拾取道具时幽灵会出现异常,这实为正常现象。当前游戏中敌方AI尚未具备躲避球体移动的能力,因此会主动撞击球体并承受伤害。其余两个小错误已修复。

相较于原版,本次玩家可能因提示信息不足而未意识到双臂皆可操作。现已新增教程指引与提示文本,新玩家将能轻松掌握双臂操控方式。

已知问题

1.当前幽灵拾取物品的逻辑仍存在漏洞。幽灵在投掷球体后,会检测最近的物品并朝其移动。若此时玩家拾取幽灵的目标物品并朝幽灵投掷,该物品会被幽灵直接拾取且不会造成任何伤害。这是因为幽灵的拾取逻辑在物品距离达到特定值时会直接执行拾取动作,不会进行其他判断(幽灵无法区分物品是被玩家投掷还是原本在地面)。目前尚未设计出更优的拾取逻辑。我曾尝试为道具添加布尔变量标记“玩家投掷”或“地面拾取”状态,但变量切换时机又衍生出新问题,故暂且放弃该方案。

2. 当前敌方AI导航系统也存在若干小问题。场景需预先烘焙导航网格,但部分场景装饰(如桌子、木桶)在游戏启动后生成,导致敌人使用AI导航时无法绕过这些障碍物。虽然此问题不影响游戏性,但可能出现敌人撞向装饰物或投掷的球弹回装饰物伤及自身的状况。目前尚未找到解决此问题的方案。

3. 幽灵角色被击中时,存在概率被击飞后卡在角落持续旋转。问题根源尚未查明,推测可能因被击出导航网格区域所致。

可及性与影响

我的游戏场景光线较暗,对比度不够鲜明,这可能导致部分弱视患者和色盲人士难以适应。针对这些群体,可通过新增色彩模式、调整光照设置及增强色彩对比度来改善体验。此外,由于缺乏音频提示,本游戏亦不适用于所有视障群体。解决此问题可能需要增加更多提示音效,并以空间音频格式呈现。

游戏视频

在线游玩

要发表一条评论吗?

您的电子邮箱地址不会被公开。 必填项已标注