第 3 章:发射子弹并击败敌人
第 3 章的目标
在第 2 章中,我们完成了以下目标:
在本章中,我们将更进一步,讲解如何实现以下功能:
下面是完成第 3 章后效果的示例视频:
规划“玩家射击并击败敌人”的实现方式
让我们先来思考需要哪些步骤。
- 玩家(Player) 需要新增一个 Shot(射击)状态。
- 为了发射子弹,我们还需要创建一个新的 Bullet(子弹)对象。
- 由于目前还没有敌人,我们也需要创建一个 Enemy(敌人)对象。
因此,在第 3 章中,我们的目标如下:
- 创建 Bullet 对象
- 为 Player 添加 Shot 状态
- 创建 Enemy 对象
最后,为了真正实现击败敌人,
我们还需要实现造成伤害的流程,也就是一个 攻击系统(Attack System)。
ACTION GAME MAKER 提供了一个专门用于处理攻击与伤害的系统。
因此,在正式开始制作之前,
让我们先花一些时间来了解这个系统是如何运作的。
ACTION GAME MAKER 中的“攻击(Attack)”与“伤害(Damage)”
攻击命中(Attack Hits)
你还记得 Player 对象中包含的
HitArea2D / HitCollision
以及
AttackArea2D / AttackCollision
这些节点吗?
在 ACTION GAME MAKER 中,
当来自 AttackArea2D 的 AttackCollision
与来自 HitArea2D 的 HitCollision 发生碰撞时,
系统会自动处理伤害计算。
此外,通过 Godot 自带的
CollisionLayer(碰撞层)
和
CollisionMask(碰撞遮罩)
功能,你还可以精细地控制
“哪些对象可以发生碰撞,哪些不可以”。
CollisionLayer 与 CollisionMask
正如之前在讲解墙体碰撞时所提到的那样,
Godot 是通过 CollisionLayer 和 CollisionMask
这一套系统来控制碰撞关系的。
你可以把它们理解为
为碰撞判定增加了一层“深度”规则。
在设置面板中,它们的含义如下:
- Layer(层) → “这个对象属于哪些层”
- Mask(遮罩) → “这个对象可以与哪些层发生碰撞”
例如:
- 如果一个 AttackCollision 的 Mask 只勾选了 第 1 层和第 2 层,
那么它将无法命中只存在于 第 3 层 的 HitCollision。
这种机制还可以避免一些不合理的情况,
例如角色的攻击判定撞到自己的攻击判定区域。
伤害处理流程(Damage Processing)
当一次攻击成功命中时,
ACTION GAME MAKER 会自动执行以下处理流程:
-
从被攻击对象的 HP 中,
减去攻击对象的 攻击力(Attack Power)
(攻击力数值在 BaseSettings 中设置)。
-
随后,可以启用 无敌时间(Invincibility)
(同样在 BaseSettings 中设置),
使受伤对象在一定时间内不会再次受到伤害。
通过这一套系统,
ACTION GAME MAKER 会自动处理攻击与伤害的核心逻辑,
你只需要正确配置相关的节点与参数即可。
1 Like
创建子弹对象(Bullet Object)
在了解了攻击系统的基本机制之后,
接下来我们就来实际创建一个 子弹(Bullet)。
子弹同样是一个 Game Object(游戏对象),
因此整体流程和创建玩家角色时是类似的:
- 指定图像
- 调整移动速度等设置
- 使用可视化脚本(Visual Script)进行处理
不过,子弹有一个关键的不同点:
子弹并不是由玩家的输入设备直接控制的。
子弹的发射和移动,是通过 “Shoot Bullet(发射子弹)”动作 来完成的,
因此我们不需要为子弹单独编写复杂的移动逻辑。
为子弹创建 Game Object
- 打开一个 新的场景标签页,
在创建根节点时选择 Game Object。
- 在 Create New Object(创建新对象) 窗口中,进行如下设置:
- Object Name:bullet
- Template:bullets
- Type:bullet_base
- 子弹对象模板会被加载完成。
- 右键点击 [unsaved (*)],
将场景保存为 bullet.tscn。
设置子弹的图像
接下来,为子弹指定一张图像。
虽然也可以给子弹制作动画,让效果看起来更酷,
但在本教程中,我们先使用静态图像来保持简单。
- 右键点击下方图片,并将其保存到你的电脑中。

-
将下载好的 bullet.png
拖拽到编辑器中的 FileSystem(文件系统) 面板内。
-
在 Scene(场景)面板 中,选择 Sprite2D 节点。
- 在 Inspector 中,
将 bullet.png 拖拽到 Texture 属性(当前为 <empty>)上。
调整子弹的 MoveAndJumpSettings
我们希望子弹的速度比玩家更快。
玩家的移动速度是 300,
因此我们将子弹的速度设置为 600。
- 在 Scene(场景)面板 中,选择 MoveAndJumpSettings 节点。
- 在 Inspector 中,将以下数值都设置为 600:
- Horizontal Speed(水平速度)
- Vertical Speed(垂直速度)
至此,我们已经创建了一个
具备图像显示与独立速度设置的基础子弹对象。
调整子弹的攻击判定范围(Attack Hitbox)
在 AttackArea2D 中设置 Collision Layer 与 Mask
默认情况下,这个对象位于 Layer 1,
其 Mask 被设置为 1 和 2。
这意味着它可以命中位于第 1 层和第 2 层的对象。
然而,Player(玩家) 也位于 Layer 1,
并且同样使用 Mask 1、2。
如果保持默认设置,子弹在发射的瞬间就会与玩家发生碰撞。
为了避免这种情况,我们需要将子弹的碰撞设置移动到
Layer 3,并且只与 Layer 3 发生碰撞。
-
在 Scene(场景)面板 中,选择 AttackArea2D。
-
在 Inspector(检查器) 中,展开 Collision(碰撞) 区域。
- 会显示一个用于选择 Collision Layer / Mask 的面板。
- 将 Layer 从 1 → 3
- 将 Mask 从 1, 2 → 仅勾选 3
现在,子弹就不会再与玩家发生碰撞了。
调整 AttackCollision 的大小
目前,子弹的攻击判定范围比子弹的精灵图像要大得多。
我们需要将它缩小,使其更贴合子弹本身。
-
在 Scene(场景)面板 中,选择 AttackCollision。
-
在编辑器视图中,拖动形状四周的橙色控制点来调整大小。
至此,子弹的碰撞设置已经正确完成:
- 子弹不会再命中玩家自身
- 攻击判定范围也与子弹的大小相匹配
设置子弹的脚本(Bullet Script)
子弹的墙体碰撞(CollisionShape2D)尺寸已经合适,因此不需要再调整。
在完成基础设置后,接下来我们为子弹创建脚本。
子弹在以下情况下应该消失:
- 命中 敌人
- 命中 地块(Tile)
- 移动到 摄像机视野之外
为此,我们只需要 两个状态:Move 和 Disappear。
下面来进行设置。
附加脚本
-
选择 Bullet(GameObject) 节点。
-
在 Scene(场景)面板中,点击
+(Attach Script,附加脚本) 按钮。
- 保持默认选项,点击 Create,
创建一个名为 bullet.vs 的新脚本。
设置 “Move” 状态
我们将默认的 State001 作为 Move 状态来使用。
由于子弹的移动是由“射击者(Shooter)”来控制的,
因此这个状态本身不需要额外的动作设置。
-
选择 State001。
-
在 Inspector 中,将 Title 改为 Move。
创建 “Disappear” 状态
-
在 Move 状态右侧 右键点击,选择 Add State(添加状态)。
-
选择新出现的 State001,将 Title 重命名为 Disappear。
-
在 Inspector 中,点击 + Add Executable Action。
- 选择 RemoveSelf,然后点击 Add。
- 这样一来,只要子弹进入 Disappear 状态,
就会立刻从场景中被移除。
连接 Move → Disappear
在以下情况下,子弹都应该进入 Disappear 状态:
- 与 敌人 发生碰撞
- 与 地块 发生碰撞
- 移动到 摄像机范围之外
我们可以在一条链接中,通过 AND(与)/ OR(或)
来组合多个条件。
在这里,我们使用 OR 逻辑:
命中敌人 OR 命中地块 OR 离开摄像机范围
操作步骤如下:
-
右键点击 Move 状态,选择 Add Link(添加链接)。
-
将链接连接到 Disappear 状态。
-
选中新建的链接,在 Inspector 中点击 + Add Condition。
-
选择 ContactWithHitArea。
-
勾选 Select All Sides(选择所有方向),然后点击 Add。
-
再次点击 + Add Condition。
-
这一次选择 ContactWithTile。
-
将方向设置为 All Directions,
并在逻辑条件中选择 OR,然后点击 Add。
-
接着点击 + Add Other Condition,添加第三个条件。
-
向下滚动,选择 Offscreen(离开屏幕)。
-
将 Target Type 设置为 This Node,
并将逻辑设置为 OR,然后点击 Add。
- 确认条件配置如下图所示。
- 如果 AND / OR 设置不正确,
可以点击图标在它们之间进行切换。
说明:为什么 “ContactWithHitArea” 不用 AND?
AND / OR 的设置,表示的是与前一个条件之间的关系。
由于 ContactWithHitArea 是第一个条件,
因此无论设置为 AND 还是 OR,结果都不会受到影响。
但如果你将它移动到其他条件的下面,
AND 就会生效。
为了避免混淆,这里建议保持为 OR。
子弹脚本的设置到此完成!
别忘了 保存场景。
修改 Player 对象以发射子弹
为了让玩家能够发射子弹,我们需要完成 四个步骤:
A. 创建射击动画
B. 添加并配置 BulletsSettings 节点
C. 添加并配置 Connector 节点(发射位置)
D. 在可视化脚本中创建 “Shoot Bullet(射击)” 状态
接下来,我们从第一步开始:添加射击动画。
A. 创建射击动画
首先,我们来思考玩家在什么情况下会进行射击。
由于本教程采用的是 类似《洛克人(Mega Man)》的设计,
直觉上似乎会需要三种射击状态:
不过,我们之前制作的 Move(移动)动画,
本身就是角色一边奔跑、一边将手向前伸出的姿势,
这正好可以直接作为“移动中射击”的动画使用。
也就是说,我们实际上只需要再创建 两个新的动画:
- Ground Shot(地面射击)
- Air Shot(空中射击)
和之前一样,所需的射击姿势已经包含在加载好的精灵表中。
整体流程依然是:
创建动画 → 插入关键帧 → 加载到 Animation Set
创建 “Ground Shot” 与 “Air Shot” 动画
-
将 Scene 标签页 切换到 Player,
并将编辑器视图设为 2D。
-
选择 AnimationPlayer 节点。
-
在底部的 Animation 面板中,点击 Animation,创建一个新动画。
- 将新动画命名为 Ground Shot。
-
选择 Sprite2D,
在 Inspector 中展开 Animation 属性。
-
将 Frame 设置为 1
(角色站在地面上、手向前伸出的帧),
然后点击
+(Add Keyframe,添加关键帧) 按钮。
- 在弹出的窗口中,取消勾选 Create RESET Track,
然后点击 Create。
- 重复步骤 2~3,再创建一个新的动画,
这一次命名为 Air Shot。
- 保持 Sprite2D 处于选中状态,
将 Frame 设置为 2
(角色在空中、手向前伸出的帧),
然后点击
+(Add Keyframe) 按钮插入关键帧。
将动画注册到 Animation Set 中
-
选择 Player(GameObject) 节点。
-
在 Inspector 中,点击 Bulk Load Animations(批量加载动画) 按钮。
- 此时,Ground Shot 和 Air Shot
就会被自动添加到 Animation Set 中。
C. 添加并配置 Connector 节点
Connector 节点用于在可视化脚本中指定一个“位置”,
例如:子弹的发射起点、对象生成的位置等。
这一次,Connector 将作为子弹的发射点,
因此我们需要把它放在射击动画中角色手部前端的位置。
-
选择 Player(GameObject) 节点。
-
点击左上角的 +(Add Child Node,添加子节点) 按钮,
打开 Create New Node(创建新节点) 窗口。
- 选择 Connector,然后点击 Create。
- 选择 AnimationPlayer 节点,
将当前动画切换为 Ground Shot。
-
再次选择 Connector 节点。
-
将编辑器工具切换到 Move Mode(移动模式)。
- 拖动 ✛(连接点标记),
将其放置到角色手部前端的位置。
至此,Connector 的设置就完成了。
1 Like
D. 添加射击状态(Shoot State)
接下来,我们来添加用于发射子弹的状态。
我们需要以下几种射击状态:
- Ground Shot(地面射击)
- Moving Shot(移动中射击)
- Air Shot(空中射击)
不过,空中射击需要一些特殊处理。
如果我们只是简单地从 Air Shot 切回 Jump,
那么每次射击都会再次触发跳跃动作,导致角色越跳越高。
为了解决这个问题,我们需要将 Jump 状态拆分成两个状态:
它们的职责如下:
- Jump 状态只负责“起跳”,并会立刻切换到 Air
- Air 状态表示角色处于空中
- 在 Air 状态下,如果角色脚底接触到地面(下方碰撞到 Tile),则返回 Idle
- Air Shot 在结束后返回 Air,从而避免重复触发跳跃动作
下面我们一步一步来构建。
创建 Ground Shot 与 Moving Shot 状态
-
切换到 Script(脚本) 标签页。
-
在 Idle 状态左侧附近创建一个新的状态。
-
将新建的 State001 重命名为 Ground Shot。
-
在 Select Animation 中,指定动画为 Ground Shot。
-
点击 + Add Execution Action(添加执行动作)。
-
选择 FireBullet 作为执行动作。
-
在 Bullet Data 中,指定之前创建的子弹对象。
-
点击 Connector 右侧的 Assign 按钮。
-
在 Select Node 窗口中,选择之前创建的 Connector 节点。
-
确认 Bullet Data = bullet,Connector = Connector,然后点击 Add。
-
接下来创建 Moving Shot,直接复制 Ground Shot 状态:
- 在 **Move** 状态右侧附近右键,选择 **Paste State**
- 将新状态重命名为 **Moving Shot**
- 勾选 Continue Previous Animation。
因为 Moving Shot 使用的动画与 Move 相同,所以这里不需要切换动画。
连接 Idle ↔ Ground Shot 与 Move ↔ Moving Shot
当角色处于 Idle 或 Move 状态时,
按下 Attack 键即可进入对应的射击状态。
射击 0.3 秒后,再返回原来的状态。
-
右键点击 Idle,添加一条连接到 Ground Shot 的 Link。
-
在属性中勾选 Trigger On Input。
-
展开 Input Operations List(Array[InputCondition])。
-
点击 + Add Input 添加新的输入条件。
-
点击空白项,选择 New Input Condition。
- 展开 Input Condition,设置 Input Key = Attack。
- 右键点击该 Link,选择 Copy。
- 右键点击 Move,选择 Paste Link。
-
将该 Link 连接到 Moving Shot。
-
右键点击 Ground Shot,添加一条返回 Idle 的 Link。
-
在 Inspector 中点击 + Add Condition。
-
选择条件 Elapsed Time。
-
将时间从 1 秒改为 0.3 秒。
-
右键点击这条 Link,选择 Copy。
-
右键点击 Moving Shot,选择 Paste Link,并连接回 Move。
至此,地面射击相关状态就完成了。
测试地面射击
-
点击右上角的 Run Project(F5)。
-
在 Idle 或 Move 状态下按 X,应能发射子弹。
-
如果没有正常工作,请检查:
- 动画不播放 → 检查状态动画设置与 AnimationPlayer
- 动画播放但没有子弹 → 检查 FireBullet 动作设置
- 子弹出现但不移动或方向错误 → 检查 BulletsSettings
确认无误后,关闭测试窗口。
将 Jump 拆分为 Jump 与 Air 状态
-
在 Jump 左侧创建一个新的状态。
-
将 State001 重命名为 Air。
-
将其 Animation 设置为 Jump(用于空中的显示)。
-
右键点击 Jump,添加一条连接到 Air 的 Link。
-
在 Inspector 中,将 Conditions for Switching 设置为 Unconditional
(表示 Jump 会立刻切换到 Air)。
- 剪切原有的 Jump → Idle Link:选中后右键 → Cut。
-
右键点击 Air,选择 Paste Link,并连接到 Idle。
-
这样一来,落地判定就会从 Air 返回 Idle,而不是从 Jump。
- 进行一次测试,确认 跳跃 → 空中 → 落地 的流程是否正确。
创建 Air Shot 并进行连接
由于 Air Shot 与 Ground Shot 的逻辑相同,只是动画不同,
我们可以直接复用已有状态。
-
右键点击 Ground Shot,选择 Copy。
-
将其粘贴到 Air 状态左侧。
-
将 Ground Shot (1) 重命名为 Air Shot。
-
在 Inspector 中,将 Animation 改为 Air Shot。
-
复制 Idle → Ground Shot 的 Link。
-
右键点击 Air,粘贴该 Link,并连接到 Air Shot。
-
复制 Ground Shot → Idle 的 Link。
-
右键点击 Air Shot,粘贴该 Link,并连接回 Air。
最终测试
再次运行项目:
- 在 Idle 或 Move 状态下按 X → 玩家发射子弹
- 用 Z 跳跃后,在空中按 X → 玩家进行空中射击
如果这两种情况都能正常工作,
你的射击系统就已经完成了!
1 Like
创建敌人对象(Enemy Object)
接下来,我们来创建敌人对象。
这次先从最简单的敌人开始——只会左右移动的敌人。
整体流程和创建玩家角色时是一样的:
- 创建一个场景
- 设置图片与动画
- 配置各个节点
- 使用可视化脚本编写行为
创建 enemy GameObject
-
将编辑器视图从 Script 切换回 2D。
-
新建一个场景标签页,在 Create Root Node 中选择 GameObject。
-
在 Create New Object 窗口中,按如下设置:
- Object Name:
enemy
- Template:Character
- Type:2DSprite Character Base
- Object Group:Enemy
- 右键点击 Unsaved,将场景保存为 enemy.tscn。
设置敌人的图片与动画
接下来为敌人设置图片和动画。
与子弹那种左右对称的圆形不同,这个敌人是非对称的角色,
需要根据移动方向进行左右翻转。
由于左右翻转是通过 Animation Set 自动处理的,
这里的流程与玩家角色完全相同:
- 使用 Sprite2D 设置贴图
- 使用 AnimationPlayer 创建动画
- 在敌人(GameObject)节点上配置 Animation Set
配置 Sprite2D
- 右键点击下方图片,将其保存到电脑中。

-
将下载好的图片拖拽到编辑器的 FileSystem 中进行导入。
-
在 Scene 面板中选择 Sprite2D 节点。
-
在 Inspector 中,将 enemy.png 拖拽到 Texture 属性上。
由于该图片不需要拆分成多帧,到此 Sprite 的设置就完成了。
使用 CollisionShape2D 调整碰撞形状
当前的碰撞区域明显比角色图片要小,因此需要调整大小。
-
在 Scene 面板中选择 CollisionShape2D 节点。
-
拖动碰撞框四角的橙色控制点,
将其调整为与角色图片大小大致一致。
配置 AnimationPlayer 并创建 Animation Set
为了使用 Animation Set,必须至少存在一个动画。
这个敌人不需要切换帧,因此只创建一个简单的动画即可。
-
选择 AnimationPlayer 节点。
-
在底部的动画窗口中,点击 Animation → New。
- 将新动画命名为 Move 并创建。
由于不需要添加任何轨道,这个动画此时已经完成。
-
选择 enemy(GameObject) 节点。
-
在 Inspector 中点击 AnimationPlayer。
-
确认已指定正确的 AnimationPlayer,然后点击 OK。
-
在 Inspector 中点击 Bulk Load Animations(批量加载动画) 按钮。
-
展开 Animation Set,确认 Move 动画已正确注册。
调整敌人的 BaseSettings(基础设置)
为了让敌人能够真正被击败,我们需要配置它的 HP(生命值) 和 无敌时间 等设置。
设置生命值(HP)
-
选择 BaseSettings 节点。
-
在 Inspector 中,将 HP 和 Max HP 都从 1 改为 3。
- 这表示敌人在受到 3 点伤害 后,HP 会降为 0。
设置无敌时间(Invincibility)
无敌时间 用于防止对象在受到一次伤害后,在极短时间内连续扣除多次 HP。
如果没有这个机制,敌人可能会在同一瞬间被多颗子弹同时命中而瞬间死亡。
由于玩家的射击间隔设置为 0.3 秒,
将无敌时间设置为 约 0.2 秒 是一个比较合适的数值。
- 如果设置为 0.4 秒,敌人可能会无视快速连射中的第二发子弹。
- 如果设置为 正好 0.3 秒,在近距离射击时,第二发子弹有可能无法正确判定命中。
此外,无敌系统还自带一个 闪烁效果,
角色在无敌状态下会周期性闪烁。
在无敌时间为 0.2 秒 的情况下,
将闪烁间隔设为 0.1 秒,闪烁效果会比较容易被观察到。
-
在 Inspector 中,将 Invincibility Duration 从 1.0 改为 0.2。
-
紧接着,将 Blink Duration 从 1.0 改为 0.1。
调整敌人的受击判定(Hitbox)
接下来配置敌人的 受击判定区域。
由于我们之前将子弹对象的碰撞层设置为 Layer 3,
敌人也必须位于 Layer 3,才能正确地与子弹发生交互。
在 HitArea2D 中配置 Collision Layer 与 Mask
-
选择 HitArea2D 节点。
-
在 Inspector 中展开 Collision 区域。
-
将 Layer 和 Mask 都设置为 3。
- 这样可以确保敌人的受击判定能够正确地与子弹的攻击碰撞发生作用。
调整 HitCollision 的大小
目前的 HitCollision 区域过大,需要进行调整。
-
在 Scene 面板中选择 HitCollision 节点。
-
拖动碰撞框四角的橙色控制点,
将其调整为略大于敌人可见图片的大小。
调整敌人的攻击判定(Attack Collision)
接下来配置敌人的攻击判定区域。
与子弹不同,敌人的攻击判定只需要与玩家发生交互即可。
由于玩家的碰撞层(Collision Layer / Mask)保持的是默认设置,
因此这里不需要修改任何层或遮罩设置,
只需调整攻击判定的大小即可。
-
在 Scene 面板中选择 AttackCollision 节点。
-
拖动攻击碰撞框四角的橙色控制点,
将其调整为与敌人受击判定(Hitbox)大小一致或接近。
设置敌人的脚本(Enemy Script)
敌人只需要左右移动,并在 HP 变为 0 时消失即可。
理论上可以用 Move Left(向左移动)、Move Right(向右移动)、Vanish(消失) 三个状态来实现,
但这里我们可以利用 Template Movement(模板移动) 动作,它可以自动处理简单的巡逻移动。
因此,这里只需要创建 两个状态:
当敌人的 HP 变为 0 时,从 Template Move 切换到 Vanish,使敌人消失。
绑定可视化脚本(Visual Script)
-
选择 enemy(GameObject) 节点。
-
点击 Attach Script(绑定脚本) 按钮。
- 保持默认名称
enemy.vs,点击 Create。
创建 “Template Move” 与 “Vanish” 状态
-
将默认的 State001 重命名为 Template Move。
-
在 Inspector 中,将 Animation Category 设置为 Move。
-
点击 + Add Executable Action(添加执行动作)。
-
选择 MovementTemplate。
-
将 Move Time 设置为 3,并勾选 Can’t Fall Off Ledges(不会从边缘掉落)。
- 这表示敌人会向一个方向行走 3 秒,
或在遇到悬崖时自动转向。
-
点击 Add。
-
在 Template Move 状态右侧的空白区域右键,选择 Add State。
-
将新建的 State001 重命名为 Vanish。
-
点击 + Add Executable Action。
- 选择 RemoveSelf 并添加。
如果状态结构与下图一致,则说明状态创建完成。
连接 Template Move → Vanish
-
右键点击 Template Move 状态,选择 Add Link,并连接到 Vanish。
-
在 Inspector 中点击 + Add Condition。
-
选择 HPIsZero。
-
保持默认设置(TargetType:This Node),点击 Add。
如果连接状态与示例一致,则设置完成。
将敌人放置到 Stage1 场景中
敌人已经准备就绪,接下来将其放入 stage1 场景,与玩家一起进行测试。
-
将编辑器视图从 Script 切换回 2D。
-
切换到 stage1 场景标签页。
-
在 Scene 面板中选择 Player 节点。
-
在 Player 被选中的状态下,将 enemy.tscn 从 FileSystem 拖拽到场景中,
放置在 Player 的右侧。
- 运行游戏进行测试。
如果一切设置正确:
- 敌人会每 3 秒 左右来回巡逻
- 被 3 发子弹 命中后会消失
故障排查清单(Troubleshooting Checklist)
-
敌人不左右移动
→ 检查 Template Move 状态中的设置
-
敌人转向时没有翻转朝向
→ 检查敌人节点的 Animation Set,并确认 Template Move 状态指定了正确的动画
-
敌人被 1 发子弹击中就消失
→ 检查敌人的 BaseSettings 中的 HP、Max HP、Invincibility 设置
-
子弹无法命中敌人
→ 检查敌人的 HitArea Collision Layer / Mask
以及子弹的 AttackArea Collision Layer / Mask
-
子弹命中后没有消失
→ 检查子弹脚本中的 Move → Disappear 链接,
并确认 Disappear 状态中已设置 RemoveSelf 动作
1 Like
为玩家添加受伤处理(Damage Handling)
到目前为止,我们已经完成了这一部分的目标:
“玩家可以通过射击来击败敌人。”
不过,现在还存在一个问题:
- 敌人已经拥有攻击判定(Attack Hitbox),
但玩家在受到攻击时没有任何反应。
- 此外,由于玩家自己也有攻击判定,
目前玩家只要与敌人发生碰撞,就能直接击败敌人。
接下来,我们需要调整玩家的设置,使其行为更加合理:
- 玩家在受到伤害时会产生反应
- 播放一个**“受伤(Damage)动画”**
- 受到攻击后会进入无敌时间(Invincibility)
- 正确调整玩家的 受击判定(Hitbox) 与 攻击判定(Attack Box)
- 最后,在 可视化脚本(Visual Script) 中添加对应的受伤处理逻辑
在 BaseSettings 中调整无敌时间(Invincibility Time)
接下来,我们来配置玩家的无敌时间。
由于这是玩家角色,给他们稍微长一点的无敌时间会更合适。
这里我们将无敌时间设为 1 秒,并将闪烁间隔设为 0.2 秒。
此外,在无敌期间我们还需要禁用受击判定(Hitbox)。
即使在无敌状态下玩家不会减少 HP,
如果不禁用 Hitbox,系统仍然会判定与攻击发生碰撞。
设置步骤
-
选择 BaseSettings 节点。
-
在 Inspector 中,将 Blink Duration 从 1.0 改为 0.2。
-
在 Blink Duration 下方,展开 Disabled Hit Collision List(Array…),
然后点击 + Add Element。
-
点击出现的空白项,并将其设置为 New DisableCollisionData。
-
当项目变为 DisableCollisionData 后,点击它以展开设置。
-
点击 Assign 按钮。
-
在弹出的节点选择窗口中,选择 HitCollision,然后点击 OK。
完成以上设置后:
- 当玩家受到伤害时
- 将进入 1 秒的无敌状态
- 在此期间角色会以 0.2 秒间隔闪烁
- 同时 HitCollision 会被禁用,避免再次触发受击判定
调整攻击判定与受击判定(Attack / Hit Collisions)
首先,我们来调整 HitCollision(受击判定) 的大小。
目前它的尺寸过大,需要缩小一些。
另外,由于本教程采用的是 洛克人(Mega Man)风格 的系统,
玩家角色本身并不需要攻击判定(Attack Hitbox)。
(如果是制作近战攻击角色,这个判定会很重要;
但在本教程中我们不会加入近战攻击。)
因此,这里我们将 完全删除 AttackArea2D。
调整 HitCollision 的大小
-
选择 HitCollision 节点。
-
拖动碰撞框四角的控制点,
将其调整为略大于墙体碰撞(CollisionShape2D) 的大小。
删除 AttackArea2D
-
右键点击 AttackArea2D 节点。
-
在菜单底部选择 Delete(删除)。
- 会弹出一个确认窗口,询问是否要删除
AttackArea2D 以及其子节点 AttackCollision。
点击 OK 即可完成删除。