如何实现等距点触游戏中CharacterBody2D仅向有效Tile移动并防穿越虚空?
等距点触游戏中限制角色仅在有效Tile上移动的实现方案
我正在学习搭建一款等距点触(Point-and-Click)游戏,目前已经实现了CharacterBody2D向用户点击位置移动的功能,场景中还放置了带有Tile的Tilemap。现在想请教如何编写代码,让玩家仅在点击有效Tile时才触发移动,同时避免角色穿越虚空区域?
以下是我当前的玩家移动脚本:
extends CharacterBody2D @export var speed = 400 var target func _ready(): target = global_position func _input(event): if event is InputEventMouseButton and event.pressed: target = get_global_mouse_position() print(event) func _physics_process(delta): velocity = global_position.direction_to(target) * speed if global_position.distance_to(target) > 10: move_and_collide(velocity * delta)
相关截图:


实现方案
核心思路
通过将鼠标点击坐标转换为Tilemap网格坐标,验证该位置是否存在有效Tile,同时配合Tilemap的碰撞配置,实现仅在有效地面点击时移动、防止角色穿越虚空的效果。
步骤1:配置Tilemap碰撞
先确认Tilemap的碰撞设置正确:
- 在Tile集编辑器中,给可行走的Tile添加碰撞形状(参考你提供的Tilemap检查器截图,确保已关联碰撞)。
- 调整Tilemap的
Collision Layer,并让玩家CharacterBody2D的Collision Mask与之匹配,确保虚空区域能阻挡角色移动。
步骤2:修改玩家脚本
更新脚本,加入Tile有效性检查逻辑:
extends CharacterBody2D @export var speed = 400 # 在编辑器中拖入场景中的Tilemap @export var ground_tilemap: TileMap2D var target func _ready(): target = global_position func _input(event): if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: # 把鼠标全局坐标转成Tilemap本地坐标 var local_pos = ground_tilemap.global_to_local(get_global_mouse_position()) # 获取对应网格坐标 var tile_coords = ground_tilemap.local_to_map(local_pos) # 检查该网格是否有有效Tile(-1代表无Tile) if ground_tilemap.get_cell_source_id(tile_coords) != -1: # 把网格坐标转成全局坐标,调整到Tile中心(适配等距Tile锚点) var tile_global_pos = ground_tilemap.map_to_global(tile_coords) target = tile_global_pos + ground_tilemap.tile_set.get_tile_size() / 2 print("点击有效Tile,设置移动目标:", target) else: print("点击虚空区域,不触发移动") func _physics_process(delta): var direction = global_position.direction_to(target) velocity = direction * speed # 距离目标足够近时停止移动 if global_position.distance_to(target) > 10: move_and_collide(velocity * delta) else: velocity = Vector2.ZERO
补充说明
- 若需要更细致的行走权限控制,可以给Tile添加自定义属性(比如
is_walkable),通过ground_tilemap.get_cell_metadata(tile_coords, "is_walkable")来判断。 - 等距Tile的锚点如果不是中心,需要调整
target的偏移量,确保角色落在Tile的正确位置。 - 只要Tilemap碰撞配置正确,
move_and_collide会自动处理角色与虚空区域的碰撞,防止穿越。
内容的提问来源于stack exchange,提问作者Samuel Shumake
相关产品推荐
相关产品推荐

