实例化对象时Resource未独立?塔防游戏资源共享问题求助
问题
我正在开发一款塔防游戏,每个塔实例都包含一个名为Upgrade的Resource数组,用于记录升级成本和等级,本该每个实例独立,但目前所有实例的资源处于共享状态;同时用于提升攻击范围的Collision Shape也存在共享问题。
经排查,脚本变量已正常复制,但Resource资源未独立。
Upgrade资源代码
class_name Upgrade extends Resource @export var Name : String @export var Inital_Cost : float @export var Upgrade_Value : float = 10 var Cost : int = 0 var Level : float = 1 @export var Max_Level : int = 30 var Growth_Factor : float = 2 var Slot : Array func Calculate_Cost() -> void: var calculated_cost : float = Inital_Cost * pow(Growth_Factor,Level) Cost = calculated_cost
塔实例化脚本
extends Node @export var Basic_Tower : PackedScene @export var Building_Mode : bool = false var Current_Tower : Node3D @export var Raycast : RayCast3D func _process(_delta): if Input.is_action_just_pressed("Interact"): Building_Mode = !Building_Mode # Check which mode we are in and we either clear the hand or we give a tower Check_Mode() # Upgrade code where you can select the tower and upgrade them if not Building_Mode and Input.is_action_just_pressed("Left_Click"): if Raycast.is_colliding(): var Obj = Raycast.get_collider() if Obj.is_in_group("Tower"): EventSystem.Emit_Event("Set_Upgrade_Target",[Obj]) if Current_Tower == null: return # This bit allows to place the tower onto the ground var Collision_Point = Raycast.get_collision_point() if Raycast.is_colliding() and Input.is_action_just_pressed("Left_Click"): Current_Tower.global_position = Collision_Point Current_Tower.set_process_mode(0) Current_Tower = null elif Raycast.is_colliding(): Current_Tower.global_position = Collision_Point func Check_Mode(): if Building_Mode and Current_Tower == null and Raycast.is_colliding(): var Instance = Basic_Tower.instantiate() Current_Tower = Instance Instance.process_mode = 4 get_tree().get_root().add_child(Instance) elif not Raycast.is_colliding() and Current_Tower != null: Current_Tower.queue_free() Current_Tower = null elif not Building_Mode and Current_Tower != null: Current_Tower.queue_free() Current_Tower = null
请问如何让每个塔实例的Resource资源不共享?
解决方案
在Godot中,Resource默认是引用类型,多个实例会共享同一个Resource对象,要实现每个塔实例独立拥有Resource,核心是为每个实例创建Resource的副本,以下是两种可行方案:
方案1:实例化塔时复制Upgrade资源
修改塔实例化逻辑,在创建塔实例后,遍历并复制其Upgrade数组中的每个资源:
# 修改Check_Mode函数中的实例化代码 if Building_Mode and Current_Tower == null and Raycast.is_colliding(): var Instance = Basic_Tower.instantiate() # 假设塔节点有一个名为upgrades的Upgrade数组变量 if Instance.has_variable("upgrades"): var new_upgrades = [] for upgrade in Instance.upgrades: # 复制Resource实例,确保每个塔拥有独立副本 var upgrade_copy = upgrade.duplicate() new_upgrades.append(upgrade_copy) Instance.upgrades = new_upgrades Current_Tower = Instance Instance.process_mode = 4 get_tree().get_root().add_child(Instance)
方案2:在塔的脚本中初始化独立资源
在塔的脚本中,通过基础配置资源生成实例独立的Upgrade资源,避免直接共享预制体中的资源:
# 塔的核心脚本示例 extends Node3D @export var base_upgrades : Array[Upgrade] # 预制体中配置的基础参数模板 var upgrades : Array[Upgrade] # 实例专属的升级资源 func _ready(): upgrades = [] for base_upgrade in base_upgrades: var new_upgrade = base_upgrade.duplicate() new_upgrade.Calculate_Cost() # 初始化实例的初始成本 upgrades.append(new_upgrade)
关于Collision Shape共享问题
Collision Shape共享的原因和Resource一致——多个实例引用了同一个Shape资源,解决思路相同:
# 在塔的_ready函数中复制Shape资源 func _ready(): var collision_shape_node = $CollisionShape3D # 创建Shape副本,确保每个塔的碰撞形状独立 collision_shape_node.shape = collision_shape_node.shape.duplicate()
内容的提问来源于stack exchange,提问作者Dragon20C
相关产品推荐
相关产品推荐

