如何实现点击选择场景中的CharacterBody2D并控制其移动
多玩家选中与移动实现方案
1. 玩家选中逻辑(每个CharacterBody2D绑定脚本)
给所有玩家节点添加以下脚本,实现点击/触摸选中并维护唯一选中状态:
extends CharacterBody2D var is_selected: bool = false func _input(event: InputEvent) -> void: # 鼠标点击检测 if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: handle_selection(event.global_position) # 触摸检测(适配移动端) elif event is InputEventScreenTouch and event.pressed: handle_selection(event.position) func handle_selection(click_pos: Vector2) -> void: if get_global_rect().has_point(click_pos): # 取消其他玩家的选中状态 for player in get_parent().get_children(): if player is CharacterBody2D and player != self: player.is_selected = false player.modulate = Color(1,1,1) # 标记自身为选中,添加视觉反馈 is_selected = true modulate = Color(1, 0.5, 0.5)
2. 选中玩家的移动逻辑
方式一:玩家脚本内独立处理
在上面的玩家脚本中补充移动相关逻辑:
var target_position: Vector2? = null var move_speed: float = 200.0 func _physics_process(delta: float) -> void: if is_selected and target_position != null: # 计算移动方向并移动 var direction = (target_position - global_position).normalized() velocity = direction * move_speed move_and_slide() # 到达目标点后停止 if global_position.distance_to(target_position) < 5.0: velocity = Vector2.ZERO target_position = null # 重写_input函数,补充移动指令逻辑 func _input(event: InputEvent) -> void: # 保留之前的选中检测代码... handle_selection(event.global_position if event is InputEventMouseButton else event.position) # 处理移动指令:点击空白处且当前玩家被选中 if (event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed) or \ (event is InputEventScreenTouch and event.pressed): if is_selected and not get_global_rect().has_point(event.global_position if event is InputEventMouseButton else event.position): target_position = event.global_position if event is InputEventMouseButton else event.position
方式二:主节点统一管理(更适合多玩家场景)
在包含所有玩家的父节点(如Node2D)中添加脚本,统一处理选中和移动指令:
主节点脚本:
extends Node2D var selected_player: CharacterBody2D? = null func _input(event: InputEvent) -> void: var click_pos = event.global_position if event is InputEventMouseButton else event.position # 检测点击的玩家 var clicked_player = null for player in get_children(): if player is CharacterBody2D and player.get_global_rect().has_point(click_pos): clicked_player = player break if clicked_player: # 更新选中状态 if selected_player: selected_player.modulate = Color(1,1,1) selected_player = clicked_player selected_player.modulate = Color(1, 0.5, 0.5) else: # 点击空白处,给选中玩家设置移动目标 if selected_player: selected_player.set_move_target(click_pos)
玩家脚本简化:
extends CharacterBody2D var target_position: Vector2? = null var move_speed: float = 200.0 func set_move_target(pos: Vector2) -> void: target_position = pos func _physics_process(delta: float) -> void: if target_position != null: var direction = (target_position - global_position).normalized() velocity = direction * move_speed move_and_slide() if global_position.distance_to(target_position) < 5.0: velocity = Vector2.ZERO target_position = null
问题排查说明
你之前仅单个玩家生效,大概率是因为未处理多玩家的选中状态互斥——没有在选中新玩家时取消其他玩家的选中标记。上面的方案通过遍历父节点下所有玩家,确保同一时间只有一个玩家处于选中状态。
内容的提问来源于stack exchange,提问作者Anirudh S
相关产品推荐
相关产品推荐

