C# XNA 4.0 SpriteBatch.Draw内存不足异常引发
首先,我想我调用了很多次spritebatch.draw方法,但是我需要这样做,或者,这是我唯一能知道如何绘制游戏窗口的方法。我会把我的代码扔了 我的窗口类C# XNA 4.0 SpriteBatch.Draw内存不足异常引发,c#,xna,out-of-memory,xna-4.0,spritebatch,C#,Xna,Out Of Memory,Xna 4.0,Spritebatch,首先,我想我调用了很多次spritebatch.draw方法,但是我需要这样做,或者,这是我唯一能知道如何绘制游戏窗口的方法。我会把我的代码扔了 我的窗口类 using System; using System.Text; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.X
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace System.Window
{
class Window
{
#region Variables
public Texture2D importedTexture;
public Texture2D WindowSkin;
public RenderTarget2D currentWindow;
public RenderTarget2D windowTexture;
public Vector2 pos;
public int prevWindowWidth;
public int prevWindowHeight;
public int windowWidth;
public int windowHeight;
public bool visible;
public bool active;
public bool drawNew;
#region Rectangles
public Rectangle clickRect;
public Rectangle topLeftRect;
public Rectangle topRightRect;
public Rectangle buttonRect;
public Rectangle botLeftRect;
public Rectangle botRightRect;
#endregion
#endregion
public Window()
{
}
public void Initialize(GraphicsDevice g, Texture2D ws, Texture2D it, int w, int h, bool v, bool a)
{
WindowSkin = ws;
importedTexture = it;
windowWidth = w;
prevWindowWidth = w;
windowHeight = h;
prevWindowHeight = h;
windowTexture = new RenderTarget2D(g, windowWidth, windowHeight);
currentWindow = windowTexture;
visible = v;
active = a;
drawNew = true;
topLeftRect = new Rectangle(0, 0, 32, 32);
topRightRect = new Rectangle(32, 0, 32, 32);
buttonRect = new Rectangle(64, 0, 32, 32);
botLeftRect = new Rectangle(0, 64, 32, 32);
botRightRect = new Rectangle(64, 64, 32, 32);
}
public void Update(GraphicsDevice g, Vector2 p, int width, int height)
{
prevWindowWidth = windowWidth;
prevWindowHeight = windowHeight;
pos = p;
windowWidth = width;
windowHeight = height;
windowTexture = new RenderTarget2D(g, windowWidth+2, windowHeight+2);
}
public void Draw(SpriteBatch s, GraphicsDevice g)
{
s.Draw(currentWindow, pos, new Rectangle(0, 0, windowWidth, windowHeight), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
}
public void DrawNewWindow(SpriteBatch s, GraphicsDevice g)
{
g.SetRenderTarget(windowTexture);
g.Clear(Color.Transparent);
s.Begin();
#region Draw Background
for (int w = 3; w < (windowWidth); w += 32)
{
for (int h = 32; h < (windowHeight); h += 32)
{
s.Draw(WindowSkin, new Vector2(w, h), new Rectangle(32, 32, 32, 32), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
}
}
#endregion
s.Draw(importedTexture, new Vector2(3, 32), new Rectangle(0, 0, importedTexture.Width, importedTexture.Height), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
#region Draw resizables
for (int i = 32; i < (windowWidth - 64); i += 32)
{
s.Draw(WindowSkin, new Vector2(i, 0), new Rectangle(16, 0, 32, 32), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
}
for (int i = 32; i < (windowWidth - 32); i += 32)
{
s.Draw(WindowSkin, new Vector2(i, windowHeight - 32), new Rectangle(32, 64, 32, 32), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
}
for (int i = 64; i < (windowHeight - 32); i += 32)
{
s.Draw(WindowSkin, new Vector2(0, i), new Rectangle(0, 48, 32, 32), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
}
for (int i = 64; i < (windowHeight - 32); i += 32)
{
s.Draw(WindowSkin, new Vector2(windowWidth - 32, i), new Rectangle(64, 48, 32, 32), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
}
#endregion
#region Draw Corners
s.Draw(WindowSkin, new Vector2(0, 0), topLeftRect, Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
s.Draw(WindowSkin, new Vector2(0, 32), new Rectangle(0, 32, 32, 32), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
s.Draw(WindowSkin, new Vector2(windowWidth - 64, 0), topRightRect, Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
s.Draw(WindowSkin, new Vector2(windowWidth - 32, 32), new Rectangle(64, 32, 32, 32), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
s.Draw(WindowSkin, new Vector2(windowWidth - 32, 0), buttonRect, Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
s.Draw(WindowSkin, new Vector2(0, windowHeight - 32), botLeftRect, Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
s.Draw(WindowSkin, new Vector2(windowWidth - 32, windowHeight - 32), botRightRect, Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
#endregion
s.End();
currentWindow = windowTexture;
}
}
}
这一切都很好,并为我的小窗口皮肤纹理配置,等等。唯一的问题是,它会变得有点滞后,然后在运行它大约一分钟后完全崩溃在我身上。它抛出了一个内存不足的异常,但我不知道也找不到任何其他与spritebatch相关的主题或帖子。有没有人对我如何让它工作而不占用太多内存有什么建议?我认为这是一种简单、划算的画窗户的方法。我只是不知道该如何减少我的抽签电话,或者如何找回那些记忆
windowTexture=new RenderTarget2Dg,windowWidth+2,windowHeight+2
可能是罪犯的一部分。尽量不要每次更新都实例化新的内容。它大约每秒发生60次,可能会导致严重的开销。改为在Initialize方法中初始化渲染目标
windowTexture=new RenderTarget2Dg,windowWidth+2,windowHeight+2
可能是罪犯的一部分。尽量不要每次更新都实例化新的内容。它大约每秒发生60次,可能会导致严重的开销。改为在Initialize方法中初始化渲染目标 RenderTarget2D实现了IDisposable:在使用完它之后,您应该始终对其调用Dispose,因为它可能会占用非托管资源,如Direct3D曲面。这是您看到的内存泄漏的根本原因
当然,如前所述,在每个绘图上实例化一个新的RenderTarget2D并不是一个好主意,因为这是一个昂贵的调用。RenderTarget2D实现IDisposable:一旦完成,您应该始终调用Dispose,因为它可能会占用非托管资源,如Direct3D曲面。这是您看到的内存泄漏的根本原因
当然,如前所述,在每次绘制时实例化新的RenderTarget2D并不是一个好主意,因为这是一个昂贵的调用。但是我如何补偿更改的rendertarget大小?我用这种方式编码,所以它很容易调整大小。另外,它在两个轴上都是“+2”,因为当它移动得更快时,它会在两侧都剪掉一点,这样更新就可以跟上。再加一点就可以解决这个问题了。等等,这意味着我可以更新它的宽度/高度,而不是重新初始化。。。让我查一下。编辑:不,它是只读的。。。我想这就是我首先重新初始化的原因。。XdI还尝试只绘制自上次更新以来大小发生变化的新窗口大小,但尝试告诉它不要重画,这样它就不必循环所有这些绘制,由于某些原因,它无法工作,在第一次绘制后它就会消失。这就像绘制渲染目标后,渲染目标会自动删除。如果需要,请创建两个渲染目标。如果需要,以后只需要一个渲染目标,请将纹理移动到纹理上,以便可以绘制它。为了处理屏幕大小的变化,取决于图像是否可以缩放,然后在渲染器上绘制一个巨大纹理上的所有对象,并根据最终绘制的屏幕尺寸进行缩放。是的,我想我已经解决了这个问题。谢谢你的麻烦,+1.:]或者,如果它能让我…呃。。。我找不到办法接受它。你能告诉我它在哪里吗?编辑:Pfft,无需担心。对勾。完成,谢谢。但是我如何补偿更改的渲染目标大小?我用这种方式编码,所以它很容易调整大小。另外,它在两个轴上都是“+2”,因为当它移动得更快时,它会在两侧都剪掉一点,这样更新就可以跟上。再加一点就可以解决这个问题了。等等,这意味着我可以更新它的宽度/高度,而不是重新初始化。。。让我查一下。编辑:不,它是只读的。。。我想这就是我首先重新初始化的原因。。XdI还尝试只绘制自上次更新以来大小发生变化的新窗口大小,但尝试告诉它不要重画,这样它就不必循环所有这些绘制,由于某些原因,它无法工作,在第一次绘制后它就会消失。这就像绘制渲染目标后,渲染目标会自动删除。如果需要,请创建两个渲染目标。如果需要,以后只需要一个渲染目标,请将纹理移动到纹理上,以便可以绘制它。为了处理屏幕大小的变化,取决于图像是否可以缩放,然后在渲染器上绘制一个巨大纹理上的所有对象,并根据最终绘制的屏幕尺寸进行缩放。是的,我想我已经解决了这个问题。谢谢你的麻烦,+1.:]或者,如果它能让我…呃。。。我找不到办法接受它。你能告诉我它在哪里吗?编辑:Pfft,无需担心。对勾。完成,然后 脚踝。
protected override void Draw(GameTime gameTime)
{
window1.DrawNewWindow(spriteBatch, GraphicsDevice);
window1.drawNew = false;
GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.AlphaBlend,
SamplerState.PointClamp,
null,
null,
null);
window1.Draw(spriteBatch, GraphicsDevice);
spriteBatch.End();
base.Draw(gameTime);
}