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

Godot中正确删除数组元素方法及重复删除异常排查

游戏单位随机放置功能重复删除数组元素问题

开发游戏单位随机放置功能时出现异常:循环中已删除的数组元素有时会被重复删除,即便该元素已不在数组中。相关代码及输出日志如下:

问题代码

func update_avaliable_positions(pos):
     #remover posição das disponiveis
     var mob_pos = tilemap.world_to_map(pos)
     var index = avaliable_positions.find(mob_pos)
     #avaliable_positions.erase(mob_pos)
     avaliable_positions.remove(index)
     print('erase: ', mob_pos)
     walkable_map.set_cellv(mob_pos, -1)


func populate(total):
   randomize()
   for n in range(total):
       print('mob: ', n)
       print('avaliable: ', avaliable_positions)
       var rand_pos = randi() % avaliable_positions.size() #walkable_map.get_used_cells().size()
       var mob = MonsterDatabase.add_mob('orc')
       mob.position = tilemap.map_to_world(walkable_map.avaliable_cells[rand_pos]) + tilemap.cell_size/2
       mobs_list.add_child(mob)
       update_avaliable_positions(mob.position - tilemap.cell_size/2)
       yield(get_tree().create_timer(3), "timeout" )

输出日志

player
avaliable: [(0, 4), (1, 4), (2, 4), (3, 4), (12, 4), (13, 4), (14, 4), (15, 4), (2, 5), (13, 5), (2, 6), (0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7), (8, 7), (9, 7), (10, 7), (11, 7), (12, 7), (13, 7), (14, 7), (15, 7)]
erase: (15, 4)
mob: 0
avaliable: [(0, 4), (1, 4), (2, 4), (3, 4), (12, 4), (13, 4), (14, 4), (2, 5), (13, 5), (2, 6), (0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7), (8, 7), (9, 7), (10, 7), (11, 7), (12, 7), (13, 7), (14, 7), (15, 7)]
erase: (13, 7)
mob: 1
avaliable: [(0, 4), (1, 4), (2, 4), (3, 4), (12, 4), (13, 4), (14, 4), (2, 5), (13, 5), (2, 6), (0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7), (8, 7), (9, 7), (10, 7), (11, 7), (12, 7), (14, 7), (15, 7)]
erase: (9, 7)
mob: 2
avaliable: [(0, 4), (1, 4), (2, 4), (3, 4), (12, 4), (13, 4), (14, 4), (2, 5), (13, 5), (2, 6), (0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7), (8, 7), (10, 7), (11, 7), (12, 7), (14, 7), (15, 7)]
erase: (15, 4) ---> 此处可见(15,4)已不在可用数组中
mob: 3
avaliable: [(0, 4), (1, 4), (2, 4), (3, 4), (12, 4), (13, 4), (14, 4), (2, 5), (13, 5), (2, 6), (0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7), (8, 7), (10, 7), (11, 7), (12, 7), (14, 7), (15, 7)]
erase: (2, 7)
mob: 4
avaliable: [(0, 4), (1, 4), (2, 4), (3, 4), (12, 4), (13, 4), (14, 4), (2, 5), (13, 5), (2, 6), (0, 7), (1, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7), (8, 7), (10, 7), (11, 7), (12, 7), (14, 7), (15, 7)]
erase: (2, 7) ---> 此处可见(2,7)已不在可用数组中

问题原因

  1. 数据源不统一:生成怪物时从walkable_map.avaliable_cells读取随机位置,但删除操作是对avaliable_positions数组执行的,两个数组未同步。当avaliable_positions已删除某位置时,walkable_map.avaliable_cells中仍保留该位置,导致重复选中已失效的位置。
  2. 未做索引有效性检查:当尝试删除的位置不在avaliable_positions中时,find方法返回-1,而GDScript中remove(-1)会删除数组最后一个元素,而非报错。这就造成了“重复删除不存在元素”的假象,实际是误删了其他元素。

修复方案

方案1:统一数据源

将populate函数中获取随机位置的代码,从walkable_map.avaliable_cells[rand_pos]改为avaliable_positions[rand_pos],确保使用同一维护中的数组:

func populate(total):
   randomize()
   for n in range(total):
       print('mob: ', n)
       print('avaliable: ', avaliable_positions)
       var rand_pos = randi() % avaliable_positions.size()
       var mob = MonsterDatabase.add_mob('orc')
       # 改为从avaliable_positions取位置
       mob.position = tilemap.map_to_world(avaliable_positions[rand_pos]) + tilemap.cell_size/2
       mobs_list.add_child(mob)
       update_avaliable_positions(mob.position - tilemap.cell_size/2)
       yield(get_tree().create_timer(3), "timeout" )

方案2:增加索引有效性校验

在update_avaliable_positions中先判断索引是否有效,避免误删:

func update_avaliable_positions(pos):
     var mob_pos = tilemap.world_to_map(pos)
     var index = avaliable_positions.find(mob_pos)
     # 仅当索引有效时执行删除
     if index != -1:
         avaliable_positions.remove(index)
         print('erase: ', mob_pos)
         walkable_map.set_cellv(mob_pos, -1)
     else:
         print('Warning: 尝试删除不存在的位置 ', mob_pos)

内容的提问来源于stack exchange,提问作者Filipe Amaral

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:46:15