【问题标题】:Can we unload a specific texture? MonoGame我们可以卸载特定的纹理吗?单人游戏
【发布时间】:2015-11-26 00:34:57
【问题描述】:

我知道您可以卸载单游戏项目中的所有内容,但我想知道是否可以卸载特定纹理,例如在关卡之后。

我有一个使用 .GetData 和 .SetData 修改的纹理,我在其他关卡以及玩家死亡时重用此纹理,但是当我在另一个重复关卡中使用它时,或者当我重新启动当前关卡时,纹理保持其修改状态,而不是其原始状态。如果我卸载所有内容,则纹理会在关卡开始时被修改并重置,但是我会丢失一些其他内容。

所以真正的问题是,您能否在不卸载所有内容的情况下卸载特定纹理?

任何帮助将不胜感激:)

【问题讨论】:

  • 您是否考虑过尝试复制原始纹理而不是对其进行修改?这样你就可以修改副本并在完成后将其丢弃。

标签: c# monogame


【解决方案1】:

简单地释放对象的问题在于,代码的其他部分无法知道对象是否已被释放。 ContentManager 仅提供 Unload() 方法,该方法卸载和处置所有资源,您不能简单地创建自己的派生实现,因为它的可处置资产的内部列表是private(不是protected )。如果您实现了自己的 Unload(string asset) 方法,则此私有列表仍将保存对您资产的引用,然后在处置 ContentManager 时尝试再次处置它(如果已实施,处置两次应该工作资源类正确,但如果没有别的,您正在阻止 GC 回收此内存)。

因此,实现 ContentManager.Unload(string assetName) 方法的唯一方法是直接更改 MonoGame 源。

常用方法稍微简单一些:只需使用多个ContentManager 实例,即Game 类中的一个共享ContentManager 实例,以及每个ContentManager 中的一个单独的私有ContentManager 实例@ (或您正在使用的任何实例)来组织你的游戏),它会在你切换场景时被释放。

对于异步内容加载,我还为我的应用程序实现了一个自定义异步内容管理器,它在首次访问时将加载作业排队到一个单独的线程中,并在后续调用中返回 null,直到资源完全加载。

【讨论】:

    【解决方案2】:

    要回答您的问题而不是处置整个内容管理器,您可以处置纹理对象本身。

    Texture2D MyTexture = Content.Load<Texture2D>("Texture.png");
    

    您的内容管理器(“Content”)现在已加载此纹理。

    MyTexture.Dispose();
    

    通过释放纹理对象而不是整个内容管理器,只会“释放”指定的纹理。虽然只会卸载纹理,但不会删除内容管理器中的引用。

    正如 craftworkgames 所指出的,对纹理对象的引用将保留在内容管理器中,这意味着它无法使用 Content.Load() 重新加载。

    我认为您正在寻找的方法不是处理纹理,而是在关卡重置时覆盖它。当关卡重置时,您只需再次对同一纹理对象调用 Content.Load 方法。这将在覆盖您修改的纹理时重新加载默认纹理。

    【讨论】:

    • 似乎是一个合理的想法。你真的试过了吗?如果内容管理器仍然持有对已处置对象的引用,我不确定会发生什么。
    • 好点,刚刚检查过。因为内容管理器保留了纹理对象的引用,所以无法重新加载它,因为它将保持已释放状态。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    • 2017-10-20
    • 1970-01-01
    • 2016-09-04
    相关资源
    最近更新 更多