You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现点击选择场景中的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 22:08:26