【发布时间】:2013-04-25 22:19:45
【问题描述】:
我的游戏窗口允许手动调整大小,这意味着它可以像任何其他普通窗口一样通过拖动其边缘来调整大小。游戏还使用了RenderTarget2D rt2d,在主 Draw 方法中设置了主渲染目标:GraphicsDevice.SetRenderTarget(rt2d),但在主函数末尾重置回null(默认渲染目标) Draw 方法,这让它有点混乱:这真的是问题的根源吗,在 Render Target 设置为rt2d 之间调整游戏窗口的大小,而不是重置为默认值?现在看起来很像。
主 Draw 方法中的代码应该始终将主渲染目标重置回 null,因此通常不会发生这种情况。
不过,调整游戏窗口大小的结果有时会导致GraphicsDevice.isDisposed 返回true,然后游戏在第一个SpriteBatch.End() 处抛出System.ObjectDisposedException。我发现有关此错误的帖子可以追溯到 XNA 的第一天,但没有很好的解释(也没有提及更改渲染目标,因此它也可能是这些海报问题的根源)。
现在我可以通过多次调用这个方法来触发这个错误:
graphics.PreferredBackBufferWidth = graphics.PreferredBackBufferWidth;
graphics.PreferredBackBufferHeight = graphics.PreferredBackBufferHeight;
graphics.ApplyChanges();
…在主要的 Draw 方法中使用以下几行:
RenderTarget2D rt2d = new RenderTarget2D(GraphicsDevice,
graphics.PreferredBackBufferWidth,
graphics.PreferredBackBufferHeight);
GraphicsDevice.SetRenderTarget(rt2d);
sb.Begin();
// main draw method here, it's pretty big, so it might be taking long
// enough to process to actually resize before resetting render target
sb.End();
GraphicsDevice.SetRenderTarget(null);
sb.Begin();
// draw the whole rt2d to the screen
sb.End();
我的猜测是,如果在重置渲染目标之前调整大小发生,我应该中止帧绘制并重置渲染目标,但我仍然不确定这正是导致此问题的原因。
UPD:有 Window.ClientSizeChanged 和 graphics.PreparingDeviceSettings 事件,但即使它们触发,默认渲染目标似乎也无济于事。
我猜这不是“调整客户区大小和应用新图形设置之间的超时”之类的。这很可能是由非默认渲染目标引起的。
渲染目标大小可能与新屏幕大小不同,因为这在将图形设备尺寸更改为完全相同的值时也会引发异常。
UPD2:我只是尝试让全屏切换挂起的操作,将 F11 设置为 isFullscreenTogglePending 为 true 并在主要Update 方法的开头,它根本没有帮助。然后我发现之前的全屏模式也是从主更新方法切换的,只是不是在一开始,而是在输入更新方法的一半,所以它在主Update方法中的位置并不重要运行,它仍然会导致此错误。有趣的是,当抛出异常时,GraphicsDevice.isDisposed 是 false。
这是异常消息:
System.ObjectDisposedException occurred
Message=Cannot access a disposed object.
Object name: 'GraphicsDevice'.
Source=Microsoft.Xna.Framework
ObjectName=GraphicsDevice
StackTrace:
at Microsoft.Xna.Framework.Helpers.CheckDisposed(Object obj, IntPtr pComPtr)
at Microsoft.Xna.Framework.Graphics.BlendState.Apply(GraphicsDevice device)
at Microsoft.Xna.Framework.Graphics.GraphicsDevice.set_BlendState(BlendState value)
at Microsoft.Xna.Framework.Graphics.SpriteBatch.SetRenderState()
at Microsoft.Xna.Framework.Graphics.SpriteBatch.End()
at secret_project.Game1.Draw(GameTime gameTime) in P:\msvs projects\secret_project\Game1.cs:line 3310
InnerException:
它位于主 Draw 调用中的 spriteBatch.End()。
如何防止出现此错误?
可能相关的问题:
【问题讨论】:
-
你做的有多小?
-
800×480 和 1920×1080,来回。我知道存在这个问题,将首选高度设置为零会导致处置,我想在以某种方式应用新分辨率时可能会发生类似的事情。也许这是某种尺寸检查超时的延迟,应该将其设置为更大的间隔?
-
您能否发布一个始终如一地重现错误的示例?
-
@borrillis 我更新了完成它的确切方法。
-
使用默认 XNA 项目和上面的代码(按下键时),我无法重现此异常。还有什么我应该做的吗?重现此行为的最小样本会很好。
标签: c# xna objectdisposedexception