Почему обьекты проходят сквозь стены и пустоту, помеченные для AStarGrid как непроходимые?
Создал map.gd
скрипт, который создает и размечает AStarGrid2D
, перебирая все тайлы и помечая Void и Wall, как непроходимые (astar.set_point_solid(coords, true)
)
В goblin.gd
и enemy_warrior.gd
(просто 2 разных персонажа, код у них одинаков) обращаюсь к $'../Map'.astar.get_id_path(start, end)
, затем просто перемещаю персонажей на одну клетку.
Не могу понять почему обьекты игнорируют непроходимость. В рабочем варианте обьекты должны обходить препятствия. Залил на гитхаб упрощенный код, только с затронутыми проблемными участками.
Вот код: map.gd
extends TileMapLayer
var astar = AStarGrid2D.new()
# Проблемный момент 1. Инициализация AStarGrid и отметка Wall и Void как непроходимые
func _ready() -> void:
var tilemapSize = get_used_rect().end - get_used_rect().position
var mapRect = Rect2i(-20, -10, 70, 70)
var tileSize = tile_set.tile_size
astar.region = mapRect
astar.cell_size = tileSize
astar.default_compute_heuristic = AStarGrid2D.HEURISTIC_MANHATTAN
astar.default_estimate_heuristic = AStarGrid2D.HEURISTIC_MANHATTAN
astar.diagonal_mode = AStarGrid2D.DIAGONAL_MODE_NEVER
astar.update()
for i in tilemapSize.x:
for j in tilemapSize.y:
var coords = Vector2i(i, j)
var tileData = get_cell_tile_data(coords)
if tileData and tileData.get_custom_data('Type') == 'Wall':
astar.set_point_solid(coords, true)
elif tileData and tileData.get_custom_data('Type') == 'Void':
astar.set_point_solid(coords, true)
И код goblin.gd
:
extends CharacterBody2D
@onready var tilemap = $"../Map"
var currentPath: Array[Vector2i]
var target_position: Vector2
var is_moving
# Проблемный момент 2. Запрос get_id_path и последующее перемещение обьекта по карте
func make_turn():
var start = tilemap.local_to_map(position)
var end = tilemap.local_to_map(get_enemy().position)
currentPath = tilemap.astar.get_id_path(start, end)
if currentPath.size() > 2:
currentPath.pop_front()
target_position = tilemap.map_to_local(currentPath[0])
is_moving = true
func _physics_process(delta):
if is_moving == true:
if position.distance_to(target_position) > 1:
position = position.move_toward(target_position, 100 * delta)
else:
is_moving = false
$"../../Dungeon".turn_completed()
func get_enemy():
var closest_enemy = null
var shortest_distance = INF
for enemy in get_tree().get_nodes_in_group("adv"):
if not is_instance_valid(enemy):
continue
var distance = position.distance_to(enemy.position)
if distance < shortest_distance:
shortest_distance = distance
closest_enemy = enemy
return closest_enemy
А также global.gd
:
extends Node
var turn
var entities = {
'monsters': [],
'adv': []
}
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
turn = 'prepare'
и enemy_warrior.gd
:
extends CharacterBody2D
@onready var tilemap = $"../Map"
var currentPath: Array[Vector2i]
var target_position: Vector2
var is_moving
signal turn_completed
func _ready():
target_position = position
# Проблемный момент 2. Запрос get_id_path и последующее перемещение обьекта по карте
func make_turn():
var start = tilemap.local_to_map(position)
var end = tilemap.local_to_map(get_enemy().position)
currentPath = tilemap.astar.get_id_path(start, end)
if currentPath.size() > 2:
currentPath.pop_front()
target_position = tilemap.map_to_local(currentPath[0])
is_moving = true
func _physics_process(delta):
if is_moving == true:
if position.distance_to(target_position) > 1:
position = position.move_toward(target_position, 100 * delta)
else:
is_moving = false
turn_completed.emit()
func get_enemy():
var closest_enemy = null
var shortest_distance = INF
for enemy in get_tree().get_nodes_in_group("monsters"):
if not is_instance_valid(enemy):
continue
var distance = position.distance_to(enemy.position)
if distance < shortest_distance:
shortest_distance = distance
closest_enemy = enemy
return closest_enemy