高级属性系统实现
本文最后更新于39 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

将本来定义在character_data脚本里的人物各种属性分离,用单独的资源类“skillAttribute”来实现角色的每一个属性,然后将人物拥有的属性实例化给人物

SkillAtrribute实现说明:

变量名类型作用默认值
attribute_nameStringName属性唯一标识名&""
display_nameString属性显示名称""
descriptionString属性详细描述""
base_valuefloat属性基础值0.0
min_valuefloat属性允许最小值-INF
max_valuefloat属性允许最大值INF
can_be_negativebool属性是否可为负false
current_valuefloat属性当前值(运行时计算)0.0
_active_modifiersArray[SkillAttributeModifier]当前激活的修改器列表[]
_owner_setSkillAttributeSet所属的属性集引用
@export var base_value: float = 0.0:
	set(value):
		var old_value = base_value
		base_value = value
		base_value_changed.emit(old_value, value)

在 GDScript 中, set(value): 是 属性访问器(setter) 的定义语法,用于 自定义属性赋值时的行为 。当你给一个变量赋值时,不是直接修改变量,而是自动调用这个 setter 方法,执行其中的逻辑。比如:

var health: float = 100:
    set(value):
        # 确保生命值在 0-100 之间
        health = clamp(value, 0, 100)

信号

  • current_value_changed(old_value, new_value) :属性当前值变化时触发
  • base_value_changed(old_value, new_value) :属性基础值变化时触发

主要函数

函数名作用参数返回值
_init构造函数p_owner_set: SkillAttributeSet = null, p_base_value_override: float = -1.0void
get_active_modifiers获取当前激活的修改器Array[SkillAttributeModifier]
add_modifier_internal添加修改器并触发重算modifier: SkillAttributeModifiervoid
remove_modifier_internal移除修改器并触发重算modifier: SkillAttributeModifiervoid
set_base_value_internal设置基础值并触发重算new_base_value: floatvoid
get_current_value获取当前计算值float
get_base_value获取基础值float
set_owner_set设置所属的属性集owner: SkillAttributeSetvoid
_recalculate_current_value重新计算当前值bool(值是否变化)

属性值重算步骤

  • 初始化变量
  • 步骤 1:计算固定值增减 (Additive)
  • 步骤 2:计算百分比修改 (Multiplicative)
  • 步骤 3:处理覆盖型修改器 (Override)
  • 步骤 4:应用最终钳制 (Clamping)
  • 更新值并返回变化状态

SkillAttributeModifier设计

变量名类型默认值作用数据流向
attribute_idStringName&""目标属性的唯一标识符从修改器流向 SkillAttribute(指定修改哪个属性)
magnitudefloat0.0修改幅度值从修改器流向 SkillAttribute(影响计算结果)
operationModifierOperationADD_ABSOLUTE修改操作类型从修改器流向 SkillAttribute(决定计算方式)
source_idString""修改器来源标识从修改器流向 SkillAttributeSet(用于批量移除)

补充说明:

  1. attribute_id:通常对应属性的唯一名称,如”Strength”、”Health”等
  2. magnitude:数值大小,可正可负,表示属性的修改量
  3. operation:常见操作类型可能包括:
    • ADD_ABSOLUTE:绝对值相加
    • ADD_PERCENTAGE:百分比相加
    • MULTIPLY:乘法叠加
    • OVERRIDE:覆盖
  4. source_id:用于标识修改器的来源,如”装备剑”、”技能火球术”等,便于通过来源统一移除修改器

SkillAttributeSet实现

  • 属性实例管理 :从属性模板创建独立实例,确保每个角色/实体拥有自己的属性副本
  • 属性值计算 :协调基础值和修改器的应用,计算最终属性值
  • 状态同步 :处理属性间的依赖关系(如当前生命值与最大生命值的同步)
  • 事件通知 :通过信号机制广播属性变化,支持外部系统响应
  • 钩子系统 :提供扩展点,允许子类定制行为

属性初始化流程:

  1. 调用 initialize_set()
  2. 清空现有属性实例
  3. 遍历 attributes_to_initialize 配置数组
  4. 对每个模板创建深拷贝实例
  5. 设置属性实例的所有者引用
  6. 初始化基础值和当前值
  7. 连接属性实例的信号到集合的信号
  8. 处理属性间初始化依赖关系
  9. 标记初始化完成

属性值计算流程

当基础值改变或应用/移除修改器时:

  1. 属性基础值改变 -> set_base_value_internal()
  2. 添加/移除修改器 -> add_modifier_internal()/remove_modifier_internal()
  3. 触发 _recalculate_current_value()
    a. 计算固定值增减 (ADD_ABSOLUTE)
    b. 计算百分比修改 (ADD_PERCENTAGE)
    c. 处理覆盖型修改器 (OVERRIDE)
    d. 应用最终钳制 (Clamping)
    e. 更新当前值并发出信号
  4. 集合接收信号并广播给外部系统(比如角色UI界面)

Character修改

所有属性不再能直接进行修改了,而是通过get方法获取以及通过修改器修改

var current_hp: float:
	get: return active_attribute_set.get_current_value(&"CurrentHealth") if active_attribute_set else 0.0

	# 链接AttributeSet到Character
	active_attribute_set.current_value_changed.connect(_on_attribute_current_value_changed)
	active_attribute_set.base_value_changed.connect(_on_attribute_base_value_changed)

#处理生命值/最大生命值/魔法值/最大魔法值改变
func _on_attribute_current_value_changed(attribute_instance: SkillAttribute, old_value: float, new_value: float):
	if attribute_instance.attribute_name == &"CurrentHealth":
		health_changed.emit(new_value, max_hp, self)
		_update_health_display()
		if new_value <= 0.0 and old_value > 0.0: # 从存活到死亡
			_die()
	elif attribute_instance.attribute_name == &"MaxHealth":
		# MaxHealth变化也需要通知UI更新,并可能影响CurrentHealth的钳制(已在AttributeSet钩子中处理)
		health_changed.emit(current_hp, new_value, self)
		_update_health_display()
	elif attribute_instance.attribute_name == &"CurrentMana":
		mana_changed.emit(new_value, max_mp, self)
		_update_mana_display()
	elif attribute_instance.attribute_name == &"MaxMana":
		mana_changed.emit(current_mp, new_value, self)
		_update_mana_display()

注意生命值魔法值的改变(血条收到伤害/治疗,魔法值消耗/回复)是直接改变基础值,其他buff或者debuff是改变当前值

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇