Gameobject destroy 在析构函数中失败

Gameobject destroy fails inside destructor

我有一个对象,其中包含一个游戏对象列表。我希望在其析构函数中销毁所有这些游戏对象。

然而,当我试图从析构函数内部调用 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");
        }
    }

根据评论中的要求,class:

的完整副本
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");
        }
    }

可能最好使用更多的 Unity 和更少的 C#,有一个很好的回调叫做 OnDestroy(),它是销毁所有箭头的好地方。如果你的统一代码的执行依赖于运行某物的终结器,这是一个非常强烈的代码味道。

除非您使用 IO 的方式要求在终结器中发生操作(可能是释放 IO 资源之类的事情),否则最好将它们留空,并将 Unity 代码放入 Unity 回调中