之前的疑惑

现在看起来客户端大一统啊!哈哈哈

因为游戏的UI界面和玩家很有可能跨了很多层(不管是平层还是父子层,总之你很难在节点树的层面找到他们的关系)但是又需要让他们联动,这个时候一般就会使用事件总线EventBus来做。

这里也有一个通用的生命组件来掺和~

因为游戏中,不只是玩家,每个敌人也是有生命值的,所以我们抽离一个单独的节点来对生命值做管理

extends Node2D

class_name HealthComponent;

signal on_health_changed(current_health: float)
signal on_dead
var current_health: float;
var max_health: float;

# setup 组件初始化
func setup(value: float)->void:
	max_health = value
	current_health = value

# take_damage 受伤
func take_damage(value: float):
	if current_health <= 0:
		return
	
	# 保证current 最少只能为0
	current_health = max(current_health - value,0)
	on_health_changed.emit(current_health) 
	if current_health <= 0:
		on_dead.emit()
	EventBus.on_player_health_updated.emit(current_health,max_health)

简版的:一个初始化函数,一个受伤函数(里面通过事件总线触发值的改变)

然后把这个节点挂载到你想用这个组件管理的节点就行了!

其实eventBus里面就是定义各种事件信号,多个节点监听就可以互相通信了

extends Node


# on_player_health_updated health_updated的时候
signal on_player_health_updated(current:float,max:float)

然后你可以在里面初始化要管理的血量值

# 引入使用
@onready var health_component: HealthComponent = %HealthComponent

# 初始化组件的值
health_component.setup(max_health)


# 模拟受伤
func _input(event: InputEvent) -> void:
	if event.is_action_pressed(&"ui_accept"):
		health_component.take_damage(1)

然后来打其他场景让UI组件去使用

town.gd

@onready var health_bar: ProgressBar = %HealthBar


func _ready() -> void:
   # 信号监听
	EventBus.on_player_health_updated.connect(_on_player_health_updated)

# 在这里面就可以监听到Player受到HealComponent管理的最新的血条了!
func _on_player_health_updated(current_health:float, max_health:float) -> void:
	health_bar.value = current_health/max_health

看看效果: