2015-09-07 136 views
0

我有一个实例化场景层次结构中的几个统一游戏对象的类。这个类实现了IDisposable。我应该如何管理这些游戏对象,因为它们是托管资源还是非托管资源?Unity游戏对象是托管还是非托管资源?

我正在关注Dispose pattern,所以我应该在哪里放置类似GameObject.Destroy(myGameObject)的调用?

谢谢

编辑: 好吧,让说,我想,当它超出范围摧毁这个类实例化的游戏对象。你将如何继续?

编辑2: 我正在测试处置。我发现解决方案。它不会自动工作,因为GameObject.Destroy(myGameObject)不能从不同的线程调用。它会抛出一个错误CompareBaseObjectsInternal。所以,当不再需要时,我打电话myClass.Dispose()。此外,我是否将Unity GameObject作为托管或非托管来处理似乎并不重要。

myMain() 
{ 
    DisposeTestClass test = new DisposeTestClass(); 
    //... 
    test.Dispose(); 
} 


class DisposeTestClass : System.IDisposable 
{ 

    public GameObject uselessGameobject { get; private set; } 

    public DisposeTestClass() 
    {   
     uselessGameobject = new GameObject("Useless gameobject"); 
    } 

    #region IDisposable 
    private bool _disposed; 

    ~DisposeTestClass() 
    { 
     Debug.Log("~DisposeTestClass()"); 

     this.Dispose(false); 
    } 

    public void Dispose() 
    { 
     Debug.Log("Dispose()"); 

     this.Dispose(true); 
     System.GC.SuppressFinalize(this); 

    } 

    protected virtual void Dispose(bool disposing) 
    { 
     Debug.Log("Dispose(bool)"); 

     if(_disposed) 
     { 
      Debug.Log("Disposed. Return."); 
      return; 
     }   

     if(disposing) 
     { 
      Debug.Log("Disposing of managed resources..."); 

      // clean up managed resources 
      /* 
      if(uselessGameobject != null) 
      { 
       GameObject.Destroy(uselessGameobject); 
       Debug.Log("Game object destroyed."); 
      } 
      else 
      { 
       Debug.Log("Game object is null."); 
      }*/ 

     } 

     Debug.Log("Cleaning up unmanaged resources..."); 
     // clean up unmanaged resources 

     if(uselessGameobject != null) 
     { 
      GameObject.Destroy(uselessGameobject); 
      Debug.Log("Game object destroyed."); 
     } 
     else 
     { 
      Debug.Log("Game object is null."); 
     } 

     // set the flag 
     Debug.Log("Setting the disposed flag."); 
     this._disposed = true; 
    } 
    #endregion 

} 

}

回答

2

不,你不应该实现IDisposable。但是你可以 :)。

“所以我应该把调用GameObject.Destroy(myGameObject)”,当你想要你的对象被销毁?实际上,无论您调用myContainer.Dispose()还是GameObject.Destroy(gObj)都无关紧要。

来实现IDisposable你的唯一原因是为了写“无限便捷”这样的代码:

using(var container = new MyContainer()) 
using(var somethingElse = new MyObject()) 
{ 
    \\Logic for container and somethingElse 
} 

但在团结这个是没有意义的。我很难想象在Update GameObjects被创建并销毁时的情况。

+0

那实际上这个类不是一个容器。它只是引用场景中的游戏对象。甚至在班级不再这样的情况下,他们仍然存在。看我的编辑。 – rluks

+0

我刚刚使用“容器”,因为缺乏上下文。在Unity中销毁使用GameObject.Destroy。即使在那之后,除非GC收集它,内存可能仍然会被gameobject占用。无论是IDisposable都不会帮助您完全删除对象。它的目的是释放非托管资源。 GameObject不是非托管资源,因此它不需要IDisposable。 继续存在意味着在现场可见? –

+0

是的,这些gameobjects留在层次结构的场景中。 – rluks

1

呵呵,我想你有点误解了IDisposableusing声明是用来做什么用的。你不应该在任何地方实现IDisposable来摆脱一个对象 - 这是垃圾收集器的角色,它更清楚何时丢弃对象。

IDisposableusing语句被用作try/finally语句(当然它更加复杂),并确保在不再使用该对象之后立即删除/解析该对象。它并不总是一个托管/非托管资源问题。

使用using声明不会确保您的游戏对象将被丢弃。这一切都取决于是否有其他物体指向它。由于它看起来像一个根对象,我相信它会尽可能地由GC保持。请注意,即使GC在对象上调用了Dispose(),只要它被引用,它就会保留在特殊队列中,直到它被释放。

在另一方面,如果你GameObject是少Game,更多的Object,你不应该考虑使用IDisposable只要它不以某种方式与一些连接/文件/外部资源连接配置它。只要你的对象被认为是垃圾,GC就会声称记忆。只要考虑到,IDisposable是CLR对待有点不同,并不总是要走的路。

编辑

据编辑你的问题 - 基本上当一个对象超出范围时,你什么都不做 - 如果GC认为垃圾,它会与发生的最接近的GC集合中删除。这就是C#被认为是托管语言的原因,以及为什么你不能自行释放内存。

+0

我明白你对垃圾收集器有何看法,请参阅我的编辑。 – rluks

+0

@ Pan.student看我的编辑。 – Kamo

+0

那么,即使在类的实例超出范围之后,该类创建的gameobjects仍然存在于场景中。我可以编写名为类似于Cleanup或MyDispose的方法,它可以销毁gameobjects并在我不打算使用该类的实例后手动调用它。但是Distroys在Dispose中处理会很方便。 – rluks