Godot背包物品拖拽功能卡顿故障求助
Godot背包拖拽卡顿问题修复方案
问题根源分析
拖拽逐渐变慢甚至卡死的核心原因有三个:
- 重复资源加载:循环内反复调用
preload("res://2D/Inventory/SelectedSlot.png"),每帧都重复加载同一份资源,导致内存占用持续攀升,拖慢程序运行。 - 频繁节点查找:每帧循环中多次执行
get_node(),这是开销极高的操作,重复调用会快速消耗性能。 - 冗余逻辑执行:选中槽位纹理赋值、拖拽跟随鼠标等操作,不需要在每个槽位的循环里重复执行,完全可以只运行一次。
修复方案
1. 提前缓存资源与节点
在脚本初始化阶段预加载静态资源、缓存所有槽位按钮,避免每帧重复执行高开销操作:
var slot_buttons = {} # 缓存所有槽位按钮节点 var selected_texture = preload("res://2D/Inventory/SelectedSlot.png") # 预加载选中槽位纹理 var tex_selected = 0 var holding_item = false var last_slot_selected = -1 var ist = null # 拖拽物品的显示节点(假设已在场景中创建) func _ready(): ist.hide() # 遍历inventory缓存所有槽位按钮 for slot_id in inventory: slot_buttons[slot_id] = get_node("Inventory/Slot" + slot_id + "/Button")
2. 重写优化后的inventory_up函数
将冗余逻辑移出循环,拆分功能模块,减少不必要的重复执行:
func inventory_up(): if not can_call_inventory_up: return # 1. 检测鼠标悬停的槽位(仅执行一次遍历) var hovered_slot_id = -1 for slot_id in slot_buttons: if slot_buttons[slot_id].is_hovered(): hovered_slot_id = slot_id break # 更新选中槽位 if hovered_slot_id != -1: tex_selected = int(hovered_slot_id) # 2. 更新选中槽位的纹理(仅执行一次) var selected_slot = get_node("Inventory/Slot" + str(tex_selected)) selected_slot.texture = selected_texture # 3. 处理拖拽逻辑(独立于槽位循环) if Input.is_action_pressed("UseItem"): if not holding_item and hovered_slot_id != -1: # 开始拖拽 var target_slot = get_node("Inventory/Slot" + hovered_slot_id) ist.position = target_slot.position ist.texture = inventory[hovered_slot_id]["image"] ist.show() last_slot_selected = int(hovered_slot_id) holding_item = true elif holding_item: # 拖拽跟随鼠标(仅执行一次) ist.global_position = get_viewport().get_mouse_position() else: # 松开鼠标放置物品 if holding_item and hovered_slot_id != -1 and int(hovered_slot_id) != last_slot_selected: swap_slots(str(last_slot_selected), hovered_slot_id) holding_item = false ist.hide() # 辅助函数:交换两个槽位的物品数据 func swap_slots(slot_a: String, slot_b: String): # 临时存储A槽位物品 var temp_item = { "name": inventory[slot_a]["name"], "max_store": inventory[slot_a]["max_store"], "current_store": inventory[slot_a]["current_store"], "image": inventory[slot_a]["image"], "object": inventory[slot_a]["object"] } # 将B槽位物品移至A inventory[slot_a] = inventory[slot_b].duplicate() # 将临时物品移至B inventory[slot_b] = temp_item # 若目标槽位原本为空,清空原槽位(根据需求调整) if inventory[slot_b]["name"] == "": inventory[slot_a] = { "name": "", "max_store": 1, "current_store": 0, "image": null, "object": null }
关键优化点说明
- 资源预加载:选中槽位纹理仅在初始化时加载一次,彻底避免重复加载导致的内存泄漏。
- 节点缓存:槽位按钮节点提前存入字典,每帧无需重复查找节点,大幅降低性能开销。
- 逻辑精简:悬停检测、拖拽跟随等操作仅执行一次,不再遍历每个槽位重复运行。
- 代码复用:用辅助函数
swap_slots处理物品交换,减少冗余代码,提升可读性。
内容的提问来源于stack exchange,提问作者Charles Dev
相关产品推荐
相关产品推荐

