【发布时间】:2020-10-24 09:28:00
【问题描述】:
我有一个对象,其中包含一个游戏对象列表。我希望在其析构函数中销毁所有这些游戏对象。
但是,当我尝试从析构函数内部调用 GameObject.Destroy() 时,它似乎停止执行(GameObject.Destroy() 之后的行从不执行,但它之前的行执行)
如果我将完全相同的代码复制并粘贴到一个名为 not_a_destructor() 的函数中并调用它,它会完美运行。是什么赋予了?我已经让它工作了,但我真的很想了解发生了什么。
析构函数和 not_a_destructor() 代码:
// Destructor DOES NOT work
~MoveAction(){
for(int i = 0; i < arrows.Count; i++){
Debug.Log("wasd");
GameObject.Destroy(arrows[i]);
Debug.Log("asdf");
}
}
// Identical code, calling not_a_destructor() works perfectly
public void not_a_destructor(){
for(int i = 0; i < arrows.Count; i++){
Debug.Log("PRETEND DESTRUCTOR!");
GameObject.Destroy(arrows[i]);
Debug.Log("GameObject destroyed successfully");
}
}
根据 cmets 的要求,该类的完整副本:
public class Action
{
public int type;
public string debug_string;
public GameObject ui_pill; // Only present for Actions created on the client
}
public class MoveAction : Action
{
public int type = ActionType.MOVE;
public MapHex origin;
public List<MapHex> route; // Intermediate hexes travelled through during the move (includes target_hex)
public Fleet fleet;
private List<GameObject> arrows = new List<GameObject>(); // Arrows for the graphical representation of the pending move on the tactical map
public MapHex target_hex {
get {
return route[route.Count - 1];
}
}
public string debug_string {
get {
return "MOVE ACTION WITH FLEET: " + fleet.name;
}
}
public MoveAction(Fleet _fleet, List<MapHex> _route){
fleet = _fleet;
route = _route;
origin = fleet.planned_position;
update_arrows_from_route();
}
public void update_arrows_from_route(){
Material default_material = new Material(Shader.Find("Sprites/Default"));
// Create one arrow for every hex we will pass through.
MapHex last = fleet.planned_position;
foreach (MapHex hex in route){
// Create arrow from last to hex
GameObject arrow_gameobj = new GameObject();
arrow_gameobj.name = "move_order_arrow";
LineRenderer line_renderer = arrow_gameobj.AddComponent<LineRenderer>();
line_renderer.material = default_material;
line_renderer.SetColors(fleet.owner.color, fleet.owner.color);
line_renderer.positionCount = 2;
arrow_gameobj.layer = layers.tactical_map;
Vector3[] line_points = new Vector3[]{last.position, hex.position};
line_renderer.SetPositions(line_points);
line_renderer.startWidth = 0.1f;
line_renderer.endWidth = 0.1f;
arrows.Add(arrow_gameobj);
last = hex;
}
}
public void not_a_destructor(){
for(int i = 0; i < arrows.Count; i++){
Debug.Log("PRETEND DESTRUCTOR!");
GameObject.Destroy(arrows[i]);
Debug.Log("GameObject destroyed successfully");
}
}
~MoveAction(){
for(int i = 0; i < arrows.Count; i++){
Debug.Log("wasd");
GameObject.Destroy(arrows[i]);
Debug.Log("asdf");
}
}
【问题讨论】:
-
你的 ~MoveAction() 析构函数缺少一个结束的 '}`,这只是一个复制粘贴问题吗?
-
很好,但是是的,只是复制+粘贴问题。我已经更新了问题
-
GameObject.Destroy() 有什么作用?我相信终结器/析构函数是单线程的,可能是死锁..
-
它似乎只是停止,没有错误或任何东西。所以死锁符合症状,但它是我正在破坏的非常简单的游戏对象。它只包含一个 LineRenderer,我不知道如何破坏它会导致死锁。
-
一般来说,除非绝对必要,否则应避免在 C# 中使用终结器。除了不知道它们何时运行之外,它们还可能导致性能下降,因为垃圾收集器必须以不同于常规对象的方式处理具有终结器的对象(有关更多要点,请参阅类似这样的文章:viva64.com/en/b/0437)
标签: c# unity3d destructor