Godot 4 Buff系统完整实现,支持状态效果管理、持续时间、循环效果、层叠机制等。使用Resource+Component架构。
Scanned 9/12/2026
Install to Claude Code
npx -y skills add 925236118/AlphaAgent --skill godot-buff-system --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Godot Buff System?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/925236118-godot-buff-system)More formats (shields.io, HTML) on the badges page.
---
name: godot-buff-system
description: Godot 4 Buff系统完整实现,支持状态效果管理、持续时间、循环效果、层叠机制等。使用Resource+Component架构。
---
# Godot 4 Buff系统
完整的Buff/状态效果系统,支持增益和减益效果、持续时间、循环触发、层叠管理等。
## 何时使用此技能
- 实现游戏状态效果系统
- 玩家/敌人增益减益管理
- DOT/AOE持续伤害
- 护盾、回复、加速等效果
## 架构设计
### Resource + Component 架构
```
Buff系统
├── Buff Resource(数据层)
│ ├── BuffData - Buff定义数据
│ └── BuffStack - 运行时Buff实例
├── BuffComponent(逻辑层)
│ ├── BuffStore - Buff注册中心
│ └── BuffTimer - 时间管理
└── BuffEffect(效果层)
└── 各种效果实现
```
### 分层职责
- **BuffData**: 定义Buff的静态属性(名称、持续时间、效果类型等)
- **BuffStack**: 管理Buff实例的运行时状态(当前层数、剩余时间等)
- **BuffComponent**: 挂在目标身上,执行Buff逻辑
## Buff数据结构
### BuffData Buff定义资源
```gdscript
# buff_data.gd
class_name BuffData
extends Resource
## Buff唯一标识符
@export var id: StringName
## Buff显示名称
@export var buff_name: String
## Buff描述
@export_multiline var description: String
## Buff图标
@export var icon: Texture2D
## 持续时间(秒),0表示永久
@export var duration: float = 0.0
## 循环间隔(秒),0表示不循环
@export var tick_interval: float = 0.0
## 最大层数
@export var max_stack: int = 1
## 层叠方式
@export_enum("None", "Duration", "Intensity", "Both") var stack_type: int = 0
## 效果类型
@export_enum("Beneficial", "Harmful", "Neutral") var buff_type: int = 0
## 是否可以被驱散
@export var can_be_dispelled: bool = true
## 是否显示在UI上
@export var show_in_ui: bool = true
## 效果生效时调用
@export var effect_script: GDScript
## Buff优先级(高优先级先执行)
@export var priority: int = 0
```
### BuffStack Buff实例
```gdscript
# buff_stack.gd
class_name BuffStack
extends RefCounted
## 所属的Buff数据
var buff_data: BuffData
## 当前层数
var current_stack: int = 1
## 剩余时间
var remaining_time: float
## 是否正在运行
var is_active: bool = false
## 父节点(BuffComponent持有者)
var owner_node: Node
## 内部计时器
var _tick_timer: float = 0.0
signal stack_changed(new_stack: int)
signal buff_ended(buff_id: StringName)
signal tick_elapsed
func _init(data: BuffData, owner: Node) -> void:
buff_data = data
owner_node = owner
remaining_time = data.duration
_tick_timer = data.tick_interval
func start() -> void:
is_active = true
_apply_effect()
func stop() -> void:
is_active = false
_remove_effect()
buff_ended.emit(buff_data.id)
func update(delta: float) -> bool:
if not is_active:
return false
# 更新剩余时间
remaining_time -= delta
# 循环效果
if buff_data.tick_interval > 0:
_tick_timer -= delta
if _tick_timer <= 0:
_tick_timer = buff_data.tick_interval
_on_tick()
tick_elapsed.emit()
# 永久Buff
if buff_data.duration <= 0:
return true
# 时间到则结束
if remaining_time <= 0:
stop()
return false
return true
func add_stack(amount: int = 1) -> void:
var new_stack := mini(current_stack + amount, buff_data.max_stack)
match buff_data.stack_type:
1: # Duration - 刷新持续时间
remaining_time = buff_data.duration
2: # Intensity - 增加层数
current_stack = new_stack
_apply_effect() # 重新应用效果
3: # Both - 刷新时间并增加层数
remaining_time = buff_data.duration
current_stack = new_stack
_apply_effect()
_:
current_stack = new_stack
stack_changed.emit(current_stack)
func _apply_effect() -> void:
if buff_data.effect_script:
# 执行效果脚本
pass
func _remove_effect() -> void:
if buff_data.effect_script:
# 移除效果脚本
pass
func _on_tick() -> void:
# 每次循环时调用
pass
func get_time_percent() -> float:
if buff_data.duration <= 0:
return 1.0
return remaining_time / buff_data.duration
```
## 效果执行机制
### BuffStore 注册中心
```gdscript
# buff_store.gd
class_name BuffStore
extends Node
## 注册所有可用的Buff
@export var registered_buffs: Array[BuffData]
## 全局Buff字典
var _buff_registry: Dictionary = {}
func _ready() -> void:
_register_all_buffs()
func _register_all_buffs() -> void:
for buff in registered_buffs:
_buff_registry[buff.id] = buff
func get_buff_data(buff_id: StringName) -> BuffData:
return _buff_registry.get(buff_id)
func create_buff_stack(buff_id: StringName, owner: Node) -> BuffStack:
var data := get_buff_data(buff_id)
if data == null:
push_error("Buff not found: ", buff_id)
return null
var stack := BuffStack.new(data, owner)
return stack
```
### BuffComponent Buff组件
```gdscript
# buff_component.gd
class_name BuffComponent
extends Node
## 信号:Buff被添加
signal buff_added(buff_id: StringName, stack: BuffStack)
## 信号:Buff被移除
signal buff_removed(buff_id: StringName)
## 信号:Buff层数变化
signal buff_stack_changed(buff_id: StringName, new_stack: int)
## 信号:Buff刷新
signal buff_refreshed(buff_id: StringName)
## 活跃的Buff字典
var active_buffs: Dictionary = {}
## 父节点引用
var _owner: Node
func _ready() -> void:
_owner = get_parent()
func _process(delta: float) -> void:
_update_buffs(delta)
func _update_buffs(delta: float) -> void:
var to_remove: Array[StringName] = []
for buff_id in active_buffs.keys():
var stack: BuffStack = active_buffs[buff_id]
if not stack.update(delta):
to_remove.append(buff_id)
for buff_id in to_remove:
_remove_buff(buff_id)
## 添加Buff
func add_buff(buff_id: StringName, duration: float = -1) -> BuffStack:
# 检查是否已存在
if active_buffs.has(buff_id):
var existing: BuffStack = active_buffs[buff_id]
existing.add_stack(1)
if duration > 0:
existing.remaining_time = duration
buff_refreshed.emit(buff_id)
return existing
# 创建新Buff
var stack := BuffStore.create_buff_stack(buff_id, _owner)
if stack == null:
return null
if duration > 0:
stack.buff_data.duration = duration
active_buffs[buff_id] = stack
stack.start()
buff_added.emit(buff_id, stack)
return stack
## 移除Buff
func remove_buff(buff_id: StringName) -> bool:
if not active_buffs.has(buff_id):
return false
var stack: BuffStack = active_buffs[buff_id]
stack.stop()
active_buffs.erase(buff_id)
buff_removed.emit(buff_id)
return true
## 清除所有指定类型的Buff
func remove_buffs_by_type(buff_type: int) -> void:
var to_remove: Array[StringName] = []
for buff_id in active_buffs.keys():
var stack: BuffStack = active_buffs[buff_id]
if stack.buff_data.buff_type == buff_type:
to_remove.append(buff_id)
for buff_id in to_remove:
remove_buff(buff_id)
## 清除所有可驱散的减益Buff
func dispel_harmful() -> int:
var count := 0
var to_remove: Array[StringName] = []
for buff_id in active_buffs.keys():
var stack: BuffStack = active_buffs[buff_id]
if stack.buff_data.buff_type == 1 and stack.buff_data.can_be_dispelled: # Harmful
to_remove.append(buff_id)
for buff_id in to_remove:
remove_buff(buff_id)
count += 1
return count
## 获取当前层数
func get_buff_stack(buff_id: StringName) -> int:
if active_buffs.has(buff_id):
return active_buffs[buff_id].current_stack
return 0
## 是否有指定Buff
func has_buff(buff_id: StringName) -> bool:
return active_buffs.has(buff_id)
## 获取所有活跃Buff
func get_all_buffs() -> Array[BuffStack]:
return active_buffs.values()
## 获取指定类型的Buff
func get_buffs_by_type(buff_type: int) -> Array[BuffStack]:
var result: Array[BuffStack] = []
for stack in active_buffs.values():
if stack.buff_data.buff_type == buff_type:
result.append(stack)
return result
```
## 时间机制
### 持续时间处理
```gdscript
# 持续时间逻辑
func update(delta: float) -> bool:
remaining_time -= delta
if remaining_time <= 0:
stop()
return false
return true
```
### 循环触发机制
```gdscript
# 循环效果示例 - 持续伤害
class_name DOTBuffStack
extends BuffStack
var damage_per_tick: float
func _init(data: BuffData, owner: Node, damage: float):
super(data, owner)
damage_per_tick = damage
func _on_tick() -> void:
if owner_node.has_method("take_damage"):
owner_node.take_damage(damage_per_tick * current_stack)
```
### 定时器管理
```gdscript
# buff_timer_manager.gd
class_name BuffTimerManager
extends Node
## 全局定时器管理,避免每个Buff单独创建Timer
var _timers: Dictionary = {}
func add_timer(buff_id: StringName, interval: float, callback: Callable) -> void:
if _timers.has(buff_id):
return
var timer := Timer.new()
timer.wait_time = interval
timer.autostart = true
timer.timeout.connect(callback)
add_child(timer)
_timers[buff_id] = timer
func remove_timer(buff_id: StringName) -> void:
if _timers.has(buff_id):
var timer: Timer = _timers[buff_id]
timer.stop()
timer.queue_free()
_timers.erase(buff_id)
func clear_all() -> void:
for timer in _timers.values():
timer.stop()
timer.queue_free()
_timers.clear()
```
## 移除机制
### 手动移除
```gdscript
func remove_buff(buff_id: StringName) -> bool:
if not active_buffs.has(buff_id):
return false
var stack: BuffStack = active_buffs[buff_id]
stack.stop()
active_buffs.erase(buff_id)
return true
```
### 条件移除
```gdscript
# 特定条件触发移除
func check_removal_conditions() -> void:
for buff_id in active_buffs.keys():
var stack: BuffStack = active_buffs[buff_id]
# 示例:生命值低于阈值移除增益
if stack.buff_data.buff_type == 0: # Beneficial
if _owner.health < 10:
remove_buff(buff_id)
```
### 死亡移除
```gdscript
# 死亡时清除减益
func _on_owner_died() -> void:
remove_buffs_by_type(1) # Harmful buffs
```
## 实际效果实现示例
### 护盾效果
```gdscript
# shield_buff.gd
class_name ShieldBuffData
extends BuffData
@export var shield_amount: float = 50.0
func _init():
super()
buff_name = "护盾"
description = "获得临时护盾,吸收伤害"
duration = 10.0
buff_type = 0 # Beneficial
```
```gdscript
# shield_effect.gd
class_name ShieldEffect
extends Node
var shield_component: Node
var shield_amount: float
func apply(target: Node, amount: float) -> void:
if target.has_node("ShieldComponent"):
shield_component = target.get_node("ShieldComponent")
else:
shield_component = Node.new()
shield_component.set_script(load("res://shield_component.gd"))
target.add_child(shield_component)
shield_component.add_shield(amount)
func remove(target: Node) -> void:
if target.has_node("ShieldComponent"):
target.get_node("ShieldComponent").clear_shield()
```
### 攻击加速效果
```gdscript
# attack_speed_buff.gd
class_name AttackSpeedBuffData
extends BuffData
@export var speed_multiplier: float = 1.5
func _init():
super()
buff_name = "攻击加速"
description = "攻击速度提升50%"
duration = 5.0
buff_type = 0 # Beneficial
max_stack = 3
stack_type = 2 # Intensity
```
### 持续伤害效果
```gdscript
# dot_buff.gd
class_name DOTBuffData
extends BuffData
@export var damage_per_tick: float = 5.0
@export var tick_interval: float = 1.0
func _init():
super()
buff_name = "灼烧"
description = "每秒受到伤害"
duration = 5.0
tick_interval = 1.0
buff_type = 1 # Harmful
```
```gdscript
# dot_buff_stack.gd
class_name DOTBuffStack
extends BuffStack
var damage_per_tick: float
func _init(data: BuffData, owner: Node, damage: float):
super(data, owner)
damage_per_tick = damage
func _on_tick() -> void:
if owner_node.has_method("take_damage"):
owner_node.take_damage(damage_per_tick * current_stack)
```
## 使用示例
### 玩家角色
```gdscript
# player.gd
extends CharacterBody2D
@export var buff_component: BuffComponent
func take_damage(amount: float) -> void:
# 检查护盾
if has_node("ShieldComponent"):
var shield: Node = get_node("ShieldComponent")
amount = shield.absorb(amount)
_health -= amount
if _health <= 0:
die()
func _ready() -> void:
buff_component = BuffComponent.new()
add_child(buff_component)
func apply_poison() -> void:
var poison_data := BuffStore.get_buff_data("poison")
if poison_data:
buff_component.add_buff("poison")
```
### 应用Buff
```gdscript
# 使用示例
func use_item(item: InventoryItem) -> void:
match item.id:
"health_potion":
player.buff_component.add_buff("healing", 5.0)
"speed_boost":
player.buff_component.add_buff("speed_up", 10.0)
```
## UI集成
### Buff图标显示
```gdscript
# buff_icon_ui.gd
class_name BuffIconUI
extends Control
@export var icon_texture: TextureRect
@export var time_label: Label
@export var stack_label: Label
@export var duration_bar: ProgressBar
var buff_stack: BuffStack
func set_buff(stack: BuffStack) -> void:
buff_stack = stack
_update_display()
stack.stack_changed.connect(_on_stack_changed)
stack.buff_ended.connect(_on_buff_ended)
func _update_display() -> void:
if buff_stack == null:
return
icon_texture.texture = buff_stack.buff_data.icon
if buff_stack.buff_data.duration > 0:
time_label.text = "%.1f" % buff_stack.remaining_time
duration_bar.value = buff_stack.get_time_percent() * 100
if buff_stack.current_stack > 1:
stack_label.text = "x%d" % buff_stack.current_stack
stack_label.visible = true
func _on_stack_changed(new_stack: int) -> void:
stack_label.text = "x%d" % new_stack
func _on_buff_ended(_buff_id: StringName) -> void:
queue_free()
```
## 最佳实践
1. **Resource存储静态数据** - BuffData作为Resource便于编辑器配置
2. **Component管理运行时** - BuffComponent统一管理生命周期
3. **使用RefCounted** - BuffStack继承RefCounted自动管理内存
4. **优先级处理** - 高优先级Buff先执行
5. **循环池化** - 避免频繁创建Timer节点
6. **信号解耦** - UI通过信号监听变化,不直接查询
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!