I am going to have lots of (same looking) zombies in my game.
Is it a good idea to make the texture static, so that SpriteBatch wont need to load a new texture?
I go through the whole zombie list and draw every zombie with the same call, just changing the position. Will SpriteBatch get it? That its exactly the same texture every time? Where could be the disadvantage?
I don't think that the use of static will give you some kind of benefit.
What's sure is that, if you load your Texture2D only once, you save memory and you can draw it how many times you need using the same variable.
Anyway, if you're using only one texture you don't have any problem, because:
Each instance of ContentManager will only load any given resource
once. The second time you ask for a resource, it will return the same
instance that it returned last time.
ContentManager maintains a list of all the content it has loaded
internally. This list prevents the garbage collector from cleaning up
those resources.
Reference here.
Related
I'm working on a 2D fighting game with XNA (C#). Everything was going well in my game until I added a story mode. There are more than 60 frames. I have a variable whose value changes each time the person presses the spacebar.
I wanted to experiment game state transitions and dispose() (or .Unload()) content when a screen was no longer needed. I have searched about Dispose() and Unload () to save memory that take my textures, but I can not give a value to my variable Texture2D after having called Dispose() for it. (texture.IsDisposed = true).
I have created a ContentManager xContent in a Manager Class.
Texture2D texture;
int image = 0;
____________________
if (Keyboard.GetState().IsKeyDown(Keys.Space))
{
if (image == 0)
{
texture = Manager.xContent.Load<Texture2D>("texture1");
}
else if (image == 1)
{
texture.Dispose();
texture = Manager.xContent.Load<Texture2D>("texture2");
}
}
Draw :
spriteBatch.Begin();
...
spriteBatch.End();
I received an error on spriteBatch.End() of the above paste because I have reloaded the texture. What should I do?
You should not be calling 'Dispose()' on any of the content which was loaded by the XNA content manager. The content manager will manage the lifespan of the content (that's it's job, after all). It ought to make reasonable decisions about when to load/unload specific textures based on usage.
When the content manager itself is disposed then it will dispose all of the content that it's currently managing, so you don't need to dispose individual pieces of content.
Try to to organize it inside your manager. Loading the appropriate texture to the collection as needed and use them and remove if they become do not really need. If the texture will not link it sooner or later pick up the garbage collector.
I'm making a game and need to store a fair bit of animation data. For each frame I have about 15 values to store. My initial idea was to have a list of "frame" objects that contain those values. Then I thought I could also just have separate lists for each of the values and skip the objects altogether. The data will be loaded once from an XML file when the game is started.
I'm just looking for advice here, is either approach at all better (speed, memory usage, ease of use, etc) than the other?
Sorry if this is a dumb question, still pretty new and couldn't find any info on stuff like this.
(PS: this is a 2D game with sprites, so 1 frame != 1 frame of screen time. I estimate somewhere around 500-1000 frames total)
If the animation data is not changing, you could use a struct instead of an class, which combines the "namespacing" of objects with the "value-typeness" of primitives. That will make all the values of a single frame reside in the same space, and save you some memory and page faults.
Just make sure that the size of your arrays doesn't get you into LOH if you intend to allocate and deallocate them often.
you are creating an animation So you should keep in mind a few basic things of.net:
Struct is created on stack. So, it is faster to instantiate (and destroy) a struct than a class.
On the other hand, every time you assign a structure or pass it to a function, it gets copied.
you can still pass struct by reference simply by specifying ref in the function parameter list
So it will be better to keep in mind this things
I have the following code as part of a game:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
terrainSprite.Draw(spriteBatch);
if (resourceMap.pixels.IsDisposed == false)
{
resources.Draw(spriteBatch, spriteFont);
}
spriteBatch.End();
base.Draw(gameTime);
//Disposes the texture here:
resources.pixels.Dispose();
}
//In the resources class
public void Update()
{
//gD = graphics device
pixels = new Texture2D(gD, 800, 353);
//big update method
//manipulate the pixels texture
}
When I open task manager and look at the resource monitor, the memory usage for 'myGame.exe' is constantly going up by about 8 KB (I realize this is small, but my game holds a LOT of data, so saving every bit I can is important, and it builds up fairly quickly). This is after all other code is commented out except for what is shown here. Then, when I comment out the code: "pixels = new Texture2D(gD, 800, 353);", the memory usage stays constant. I also tried GC.Collect(), but no dice.
Is there anything else I can do to try and stop it? (Sorry, getting rid of the code is not an option :p, renewing the texture is much faster than any other method I've come across to make the texture go blank)
Depending on your Game configuration and really, many other factors, such as how slow everything is running, etc., Update and Draw are not perfectly synchronous with each other and are not guaranteed to be run in the following fashion:
Update
Draw
Update
Draw
Update
Draw
Update
Draw
....
Therefore, since you're Disposeing in one and creating a brand new one in the other, something like this can definitely happen:
Update: create new
Update: create new //PREVIOUS ONE LEAKED!
Draw: disposes only current
Update: create new
Update: create new //AGAIN LEAK
Draw: disposes only current
...
Thus, do not Dispose separately in this fashion; Dispose one time for each new one created, no matter what.
I should also add on that textures, along with some other XNA classes (sound and music, and Effects, to name a few) are unmanaged resources, meaning the GC does not see them at all. You must call Dispose on these.
As Andrew points out in his comment, the best way to avoid these pitfalls is not to recreate textures so often - simply reuse the same one and modify it as you see fit.
It appears that Texture2D are not fully handled by the garbage collector.
So when you stop using it (when reusing a variable referencing it, like here, or during the OnDestroy callback), you have to manually destroy the texture. Here :
if(pixels != null) {
Destroy(pixels);
}
pixels = new Texture2D(gD, 800, 353);
I'm working on a personal project that, like many XNA projects, started with a terrain displacement map which is used to generate a collection of vertices which are rendered in a Device.DrawIndexedPrimitives() call.
I've updated to a custom VertexDeclaration, but I don't have access to that code right now, so I will post the slightly older, but paradigmatically identical (?) code.
I'm defining a VertexBuffer as:
VertexBuffer = new VertexBuffer(device, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
VertexBuffer.SetData(vertices);
where 'vertices' is defined as:
VertexPositionNormalTexture[] vertices
I've also got two index buffers that are swapped on each Update() iteration. In the Draw() call, I set the GraphicsDevice buffers:
Device.SetVertexBuffer(_buffers.VertexBuffer);
Device.Indices = _buffers.IndexBuffer;
Ignoring what I hope are irrelevant lines of code, I've got a method that checks within a bounding shape to determine whether a vertex is within a certain radius of the mouse cursor and raises or lowers those vertex positions depending upon which key is pressed. My problem is that the VertexBuffer.SetData() is only called once at initialization of the container class.
Modifying the VertexPositionNormalTexture[] array's vertex positions doesn't get reflected to the screen, though the values of the vertex positions are changed. I believe this to be tied to the VertexBuffer.SetData() call, but you can't simply call SetData() with the vertex array after modifying it.
After re-examining how the IndexBuffer is handled (2 buffers, swapped and passed into SetData() at Update() time), I'm thinking this should be the way to handle VertexBuffer manipulations, but does this work? Is there a more appropriate way? I saw another reference to a similar question on here, but the link to source was on MegaUpload, so...
I'll try my VertexBuffer.Swap() idea out, but I have also seen references to DynamicVertexBuffer and wonder what the gain there is? Performance supposedly suffers, but for a terrain editor, I don't see that as being too huge a trade-off if I can manipulate the vertex data dynamically.
I can post more code, but I think this is probably a lack of understanding of how the device buffers are set or data is streamed to them.
EDIT: The solution proposed below is correct. I will post my code shortly.
First: I am assuming you are not adding or subtracting vertices from the terrain. If you aren't, you won't need to alter the indexbuffer at all.
Second: you are correct in recognizing that simply editing your array of vertices will not change what is displayed on screen. A VertexBuffer is entirely separate from the vertices it is created from and does not keep a reference to the original array of them. It is a 'snapshot' of your vertices when you set the data.
I'm not sure about some of what seem to be assumptions you have made. You can, as far as I am aware, call VertexBuffer.SetData() at any time. If you are not changing the number of vertices in your terrain, only their positions, this is good. Simply re-set the data in the buffer every time you change the position of a vertex. [Note: if I am wrong and you can only set the data on a buffer once, then just replace the old instance of the buffer with a new one and set the data on that. I don't think you need to, though, unless you've changed the number of vertices]
Calling SetData is fairly expensive for a large buffer, though. You may consider 'chunking' your terrain into many smaller buffers to avoid the overhead required to set the data upon changing the terrain.
I do not know much about the DynamicVertexBuffer class, but I don't think it's optimal for this situation (even if it sounds like it is). I think it's more used for particle vertices. I could be wrong, though. Definitely research it.
Out of curiosity, why do you need two index buffers? If your vertices are the same, why would you use different indices per frame?
Edit: Your code for creating the VertexBuffer uses BufferUsage.WriteOnly. Good practice is to make the BufferUsage match that of the GraphicsDevice. If you haven't set the BufferUsage of the device, you probably just want to use BufferUsage.None. Try both and check performance differences if you like.
In XNA, when calling Content.Load() to load in a resource, if you load the same resource into multiple objects (i.e. the texture for a projectile of which there can be many) are you getting a copy for each object, or is the system just internally referencing the same memory for each one?
I was realizing that having a separate Texture2D object in each item may be a memory issue down the line.
The ContentManager will cache the object and return the reference to that object when you try to load it again.
Yes modifying the texture data will change all textures that reference that data.
If you need multiple ones then duplicate the original file and load different versions.
You would need to make a new Texture2D object and simply copy the changed data into the new texture with the SetData method:
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.texture2d.setdata.aspx