Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

SpriteManager - draw lots of sprites in a single draw call!

Discussion in 'iOS and tvOS' started by Brady, Jan 15, 2009.

  1. zoul

    zoul

    Joined:
    May 5, 2007
    Posts:
    50
    I thought I answered those questions ... but,

    If your allocBlockSize is set to 1000, but you only ever use 100 of those ... then you've got 900 unused blocks allocated in memory (so your using memory you don't have too ... but iphone, thats not a bright idea).

    For the 20 sprites thing you said you have, if you add 20 sprites, then remove 6, and add 6 back in ... then, 20 is all you need to have.

    You can test this by setting allocBlockSize to 20 ... and then playing a bit, then ... check allocBlockSize after you've removed/added a few times ... if it's still at 20, then 20 is all you need. If it increases, then your adding sprites before removing them ... so either reverse your logic and remove them first, then add them ... or increase your allocBlockSize to 40 to accommodate.

    Setting it to the 'most likely used' value, is better than letting it increase a lot over time.
     
  2. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    I tested SM already and saw that the removed sprites were being reallocated (quite elegantly) but wanted to be absolutely sure I was not missing anything from my testing.

    On the over allocation I wondered if there were any issues regarding the manipulation of the vertices which would impact on processing.

    thanks for the reply zoul (nice workstation btw)
     
  3. zoul

    zoul

    Joined:
    May 5, 2007
    Posts:
    50
    over allocation is just that, 'over allocating' ... consuming more than is necessary.

    A nice update I'd like to see for Sprite Manager is an 'initial block size' and an 'alloc block size' ...

    This way, you can set your initial block count to say 100, but set your allocBlockSize to 10.

    This would cover situations where you know your going to consume up to 100 locations at start, but 'may' use more than that over time, but not much more than that.
     
  4. Derek

    Derek

    Joined:
    May 1, 2009
    Posts:
    4
    First off, thanks for this! They should roll this into the next version of Unity. I'd love to see better support for 2d games.

    Q:

    Is that the only way to manage a sprite's depth? I'd like to be able to change it during the game, i.e. tell certain sprites to appear in front of others on the fly.

    Also, I'm not so sure that Sprite Manager draws sprites in the order of creation. I've tried removing all the sprites on screen and then re-adding them from back to front and it doesn't always work.
     
  5. noocell

    noocell

    Joined:
    Mar 23, 2009
    Posts:
    104
    I am trying to extend the JavaScript example given in the middle of page 12 http://forum.unity3d.com/viewtopic.php?t=17864&postdays=0&postorder=asc&start=165

    It works ok, but when adding a rigidbody (with gravity) to the client the linked sprite doesn't follow the object as it falls downwards. Same applies when adding a physics force.

    Has anybody managed to properly implement the SM from within JavaScript? What do I miss? :roll:


    Here is my client script:

    Code (csharp):
    1. var sprHolder:GameObject;
    2. var sprManager:SpriteManager;
    3. var spr : Sprite;
    4.  
    5. function Awake () {
    6.     sprHolder =  GameObject.Find("SpritesHolder");
    7.     sprManager = sprHolder.GetComponent("SpriteManager");
    8. }
    9.  
    10. function Start() {
    11.     var spr = sprManager.AddSprite(gameObject, .5, .5, 3, 120, 128, 128, true);
    12. }
    13.  
    14. function Update () {
    15. rigidbody.AddRelativeForce(0.1, 0, 0);
    16. }
    And here is the whole package...
     

    Attached Files:

  6. Langaert

    Langaert

    Joined:
    Mar 2, 2009
    Posts:
    21
    Derek: I would love to see better 2d game support as well. SpriteManager is nice, I guess, but is no magic 2D bullet. Unity iPhone still has to be dragged kicking and screaming to that party. I don't really know at this point how to accomplish dynamic sprite depths. It may be possible by turning on the Billboarding option. But the word is that will slow your performance and so may not be worth it. Still, its worth a shot if you haven't tried it already.
     
  7. Derek

    Derek

    Joined:
    May 1, 2009
    Posts:
    4
    I'm pretty sure I have billboarding on by default, but I'll check. Didn't realize it was significantly slower, either. Thanks, Langaert!

    One idea is to have multiple Sprite Managers running, one for each "layer" of depth you need. I have no idea what that would do to performance, though.

    If I figure out a way to hack SM to allow dynamic sprite depth, I'll definitely share it here. But I'm new to Unity and 3d programming in general, so first I have to understand what it's actually doing. :)
     
  8. Dark-Table

    Dark-Table

    Joined:
    Nov 25, 2008
    Posts:
    315
    If you're doing a 2D game, couldn't you just use an orthographic camera and actually move the sprite's z values to have them sort correctly? Looking through the ortho camera you wouldn't be able to tell that they were further from the camera, and they would sort as desired (as long as your shader had zwrite on).
     
  9. Langaert

    Langaert

    Joined:
    Mar 2, 2009
    Posts:
    21
    silentchujo: That's the way it should work, and it does work that way if you make every sprite a single texture on a seperate plane/mesh/box- the "normal" way. I don't claim to understand all the specifics of why SpriteManager doesn't do it right, and you can find some indications of that previously in this forum. Bottom line is that the alpha blending gets all messed up where the alpha portions of one sprite will cause sprites positioned behind it to disappear if you shuffle their depth order after creating them.
     
  10. Dark-Table

    Dark-Table

    Joined:
    Nov 25, 2008
    Posts:
    315
    It's working for me. I think you're using a bad shader. Here's a real quick demo, no weird artifacts beyond my crappy art skills. I'm using a copy of one of the particle shaders that I changed to enable zwrite.
     

    Attached Files:

  11. Langaert

    Langaert

    Joined:
    Mar 2, 2009
    Posts:
    21
    Actually, I can see a perfect demonstration of the problem in that screenshot. You've helped compensate for the issue by incrasing the alphatest (which slows down performance). However, it is still visible in the black dots on the edges of your balls. Because you are using simple graphics using minimal AA, this is not a huge problem (though still quite undesirable imo). It becomes a much bigger problem if you have quality AA'd sprites.
     
  12. Dark-Table

    Dark-Table

    Joined:
    Nov 25, 2008
    Posts:
    315
    Still, all about the shader and nothing to do with SpriteManager. If you change the "AlphaTest Greater .1" to "AlphaTest Greater .5" the artifacts all but disappear (but the edges get more aliased). You need to find a shader that does proper Alpha, but doesn't require normals, and then SpriteManager will do what you want.
     
  13. Derek

    Derek

    Joined:
    May 1, 2009
    Posts:
    4
    Hey, silentchujo, thanks for that. Aside from the artifacts, it seems to work as intended.
     
  14. lesguerra

    lesguerra

    Joined:
    Apr 20, 2009
    Posts:
    24
    Hi, does anyone have an idea on how to use multiple materials for one SpriteManager. I'm trying on displaying text and non-text using a single SpriteManager, like this idea...

    Code (csharp):
    1. BeginDrawingText()
    2. //assign bitmap font material
    3. //add text sprites (1 draw call))
    4. EndDrawingText()
    5. BeginDrawingOthers()
    6. //assign different material
    7. //add sprites (1 draw call))
    8. EndDrawingOthers()
    9.  
    i used the spritemanager to display text using bitmap fonts. combining both text and non text to a single texture is not practical imo. or should i just create another empty object to handle the texts. thanks.
     
  15. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    SpriteManager is basically just a way to manage independently moving objects that are all rendered with a single mesh (so as to have a single draw call). If you change materials, you're adding a draw call. So you might as well just use a second SpriteManager object with its own material.
     
  16. CedarParkDad

    CedarParkDad

    Joined:
    May 28, 2008
    Posts:
    98
    Since I'm looking to add a TextManager to SpriteUI, I'm interested in how you're planning on getting the sizes to use for characters on the character sprites. Are you using TextMesh and getting the sizes from there, or are you combining TextMesh objects? Or is there a way to get UV data from a Font object that is undocumented?
     
  17. oksana

    oksana

    Joined:
    Mar 20, 2009
    Posts:
    4
    Hi, could somebody please help me!!!!
    I am trying to use SpriteAnimation within SpriteManager object and call them from JavaScript and it doesn't work!! I am creating three cloned objects, and I can see them on Hierarchy panel, but script seems to have problems attaching mesh and actually render the objects. I am attaching a small test project, and I put on a scene a prefab, with what my objects should look like. I read all 15 pages of this topic, but it didn't help me.
    Code to instantiate objects and play animation is very straight forward and I actually copied it from the project which was attached here in the thread, but still...
    Code (csharp):
    1.  
    2. var _mySpriteManager:SpriteManager;
    3. var  wormPrefab : GameObject;
    4. var ref1;
    5.  
    6. function Awake () {
    7.     _spriteManagerReference =  GameObject.Find("SpriteManagerGO");
    8.     _mySpriteManager = _spriteManagerReference.GetComponent("SpriteManager");
    9. }
    10.  
    11. function Start() {
    12.     CreateGameObjects();
    13.     CreateSprites();
    14. }
    15. function Update(){
    16.     ref1.stepAnimation(Time.deltaTime);
    17. }
    18. function CreateGameObjects(){
    19.     var worm1 = Instantiate(wormPrefab, Vector3 (-7.58921, 0.759709, -41.49905), Quaternion.identity);
    20.     var worm2 = Instantiate(wormPrefab, Vector3 (29.0128, 1.722624, -50), Quaternion.identity);
    21.     var worm3 = Instantiate(wormPrefab, Vector3 (12.17669, 1.177972, -45.186), Quaternion.identity);
    22. }
    23.  
    24. function CreateSprites(){
    25.      ref1 = _mySpriteManager.AddSprite(wormPrefab, 20, 20, 0, 64, 64, 64, false);
    26.      ref1.AddAnimation("warmWait",   // animation name
    27.                         0,           // lower left x coord of first frame
    28.                         -200,        // lower left y coord of first frame
    29.                         16,          // number of frames in the animation
    30.                         12,      // frame rate (30fps)
    31.                         true,      // should loop
    32.                         false);       // should autodestruct when animation finished
    33.        // Start the animation
    34.       ref1.StartAnimation("warmWait");
    35.      
    36.            
    37.     _mySpriteManager.AddSprite(wormPrefab, 20, 20, 0, 64, 64, 64, false);
    38.     _mySpriteManager.AddSprite(wormPrefab, 20, 20, 0, 64, 64, 64, false);
    39. }
    Edit:
    Can't attach anything to the post.
     
  18. Dark-Table

    Dark-Table

    Joined:
    Nov 25, 2008
    Posts:
    315
    It looks like you are trying to attach the sprites to the prefab, and not the gameobjects you instantiated.

    _mySpriteManager.AddSprite(wormPrefab should be _mySpriteManager.AddSprite(worm1

    The other problem is that worm1, worm2, and worm3, aren't getting stored anywhere, so those references will be gone when you call the CreateSprites() function. You should either combine the two functions, or store worm1 up at the top with ref1.
     
  19. noocell

    noocell

    Joined:
    Mar 23, 2009
    Posts:
    104
    I wonder how draw calls minimization is correlated with in-game fps.

    Without SM, I had 30 cubes with rigidbodies, colliders and raycasting (inside Update) giving 15-35 fps with 35 drawcalls.

    After implementing SM I have the same 30 objects, with rigidbodies, colliders and raycasting giving about 17-40 fps, despite minimizing drawcalls to just 4 (850 tris, 650 verts). :?
     
  20. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    So the key here is to use the INTERNAL PROFILER inside XCode to see where your bottleneck is.

    Reducing drawcalls (may) improve your performance if your rendering time is your main bottleneck and its not due to an overly high Tri/Vert count.

    In this case wether it was or not, 30 rigidbodys is at the very high end of what an iPhone can handle at a good FPS.

    Check your Physics and FixedUpdate times in the profiler to see if they are high.

    There are many aspects of what the Unity engine does per frame (and sub frame) and you need to know where your bottlenecks are before you start to optimise.
     
  21. noocell

    noocell

    Joined:
    Mar 23, 2009
    Posts:
    104
    Seon, thanks for helping!

    I suppose you are talking about Instruments (this is the first time I use it). I've tried to "start with performance tool", each time with a different performance template (activity monitor, cpu, openngl etc) but I cannot find statistics about Physics and FixedUpdate. Could you point me to the right direction?
     
  22. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    No, not instruments.

    When you have you project open in XCode, click on the Appcontroller.mm file and you will see a compiler directive called;

    Code (csharp):
    1. #define ENABLE_INTERNAL_PROFILER 0
    change this to..

    Code (csharp):
    1. #define ENABLE_INTERNAL_PROFILER 1
    and then build and play your game, and in the XCode debugger, you will see a constant stream of stats being displayed.

    They are all explained in the Unity iPhone docs.

    It looks something like this...


    Code (csharp):
    1. cpu-player>    min: 15.7   max: 49.2   avg: 32.3
    2.  
    3. cpu-ogles-drv> min:  4.9   max: 17.0   avg:  9.1
    4.  
    5. cpu-present>   min:  1.2   max:  9.1   avg:  1.6
    6.  
    7. frametime>     min: 32.6   max: 69.2   avg: 52.8
    8.  
    9. draw-call #>   min: 29   max: 35   avg: 32
    10.  
    11. tris #>        min: 3161   max: 3281   avg: 3214
    12.  
    13. verts #>       min: 4854   max: 5080   avg: 4951
    14.  
    15. player-detail> physx:  4.6 animation:  0.0 skinning:  0.0 render: 20.6 fixed-update-count: 0 .. 1
    16.  
    17. mono-scripts>  update:  0.9   fixedUpdate:  3.5 coroutines:  0.8
    18. mono-memory>   used heap: 1699840 allocated heap: 2060288
     
  23. oksana

    oksana

    Joined:
    Mar 20, 2009
    Posts:
    4
    silentchujo, thank you very much for you reply!
    It helped a lot, and now I can see at least that the object is rendered, not quite correctly yet, though.

    Maybe, who used animation for the Sprites knows why I am still having troubles. I am using the same texture like matrix, as I would use for AnimatedTextureUV.js from wiki to animate my sprites. It has 4x4 images. Then in the code, I am trying to turn on animation:
    Code (csharp):
    1.  
    2. sprite1 = _mySpriteManager.AddSprite(worm1,7, 5, 0, 0.5, 64, 16, false);
    3.  sprite1.AddAnimation("warmWait", // animation name
    4.                        0,// lower left x coord of first frame
    5.                        10.04551,    // lower left y coord of first frame
    6.                        16,          // number of frames in the animation
    7.                        12,      // frame rate (12)
    8.                        true,      // should loop
    9.                        false);       // should autodestruct when animation finished
    10.        // Start the animation
    11. sprite1.StartAnimation("warmWait");  
    and then in Update()
    I just execute the animation :

    Code (csharp):
    1. sprite1.stepAnimation(Time.deltaTime);
    what I can see in the game is a 7x5 square which is moving.
    I am wondering if I am passing wrong values to the AddAnimation() function, or I need to use different image/Texture for the animation of my sprite, in order to get the same effect from SpriteAnimation , as AnimatedTextureUV,js script creates.
     
  24. noocell

    noocell

    Joined:
    Mar 23, 2009
    Posts:
    104

    Seon, thanks for the directions. The results for my test project are not encouraging. I removed raycasting, colliders and even rigidbodies but I cannot achieve a persistent fps of 30+. The last thing I am going to try is having all my objects be moved from within a single script, instead having each object driving itself (30 updates). With current setup the major time consumption is within update or fixedupdate (total of 20-25 ms) and the overkill is not from rigidbodies or physics.


    I would very much like to hear from community's experience concerning the appropriatness of Unity+SM for a game like this...

    What I am trying to do is to make a game which will have about 30-40 objects on screen, each one moving itself after reading the positions of the nearby objects (just the first 2-3 objects in front of it). Objects will have some simplistic animation from time to time, and all objects could share the same texture. I know there are many ways to setup the movement of my objects. I am not sure that rigidbodies+raycasting is a realistic option. Maybe a grid and a single script that could move all 30 objects/sprites on the grid.

    Do you believe that having 30-40 independently (and constantly) moving objects and some minor artwork on screen could be achievable with Unity + SM, with a stable 30+ fps ? Are there any similar games released so far? I have in mind Zombieville but it is not using SM.

    Thanks for any answers!
     
  25. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    30-40 objects is easily do-able. The bottleneck won't be SM, it will be physics or AI/behavior logic. 30-40 separate draw calls, on the other hand (which is what you'd have without SM or something similar), will be a bottleneck itself.
     
  26. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    And 30 separate Update loops is suicide!

    You need to get all of your logic into 1x Update() and 1x FixedUpdate().

    That might seem like a major hurdle, but its not that bad and will dramatically reduce your overhead over having each element control themselves!
     
  27. oksana

    oksana

    Joined:
    Mar 20, 2009
    Posts:
    4
    Please, answer me ...
    What kind of texture/matrix to use with SpriteAnimation.cs? Should it look like the same as texture-matrix for AnimatedUV.js ?
    I am trying to setup 3 sprites which supposed to be animated. For some reason it doesn't work for me. I can generate sprites/objects during the run of the game, but I am having troubles with rendering. The sprites have just a part of the texture I am using.
    So my texture is 4x4 matrix.

    First I am instantiating the object
    Code (csharp):
    1. object = Instantiate(wormPrefab, Vector3 (-7.58921, 0.759709, -41.49905), Quaternion.identity);
    Then I am adding it to the manager
    Code (csharp):
    1. sprite1 = _mySpriteManager.AddSprite(worm1,5, 7, 0, 0, 256, 256, false);
    After thet I am adding an animation:
    Code (csharp):
    1. sprite1.AddAnimation("warmWait",   // animation name
    2.                         0,              // lower left x coord of first frame
    3.                         0,              // lower left y coord of first frame
    4.                         16,             // number of frames in the animation
    5.                         12,             // frame rate (30fps)
    6.                         true,           // should loop
    7.                         false);         // should autodestruct when animation finished
    8.  
    9.  
    Then start:
    sprite1.StartAnimation("warmWait");

    and then in Update() function I call this statement:
    sprite1.stepAnimation(Time.deltaTime);

    Am I doing anything wrong? I am really stucked.
     
  28. noocell

    noocell

    Joined:
    Mar 23, 2009
    Posts:
    104
    Brady, thanks for sharing SM with us! :)

    Seon, that was exactly what I hoped to hear. I am going to move all my logic to a single Update and I'll report the results here.
     
  29. anthropophagy

    anthropophagy

    Joined:
    Apr 28, 2009
    Posts:
    10
    Hey, first of all, thanks to everyone in the community, I've been silently following this thread religiously since I started my game, it's been a great help.

    I was just curious if anybody had tried stacking this against something built straight up in xcode with atlas sprites. -- I'd love to know what the performance breakdown is like if anyone has done any sort of head-to-head benchmarking like that...


    thanks again!
     
  30. 1r0nM0nkey

    1r0nM0nkey

    Joined:
    Apr 8, 2009
    Posts:
    131
    @langaert

    The problem you are seeing with "holes" in the scene is due to the fact that alpha triangles are being rendered out of order. If I want to render a partially transparent triangle or quad, say a window, I need to know what is behind it to be able to add my color to it. So, if I render the window before I render the landscape, there will be nothing behind the window. It is saying, "ok, add a little bit of my color to the background and then move on to the next triangle". If the background is your clear color at that moment, that is what you will see behind the window.

    I have taken a look at the SpriteManager code and the trouble you are having is because the index list (which tells the renderer how the mesh is connected) is not being sorted.

    You have already found the "quick fix", which is to add your sprites in the order that you wish them to be rendered (first added is first rendered; read: opaque first!) Although, if slots are being reused without sorting, then you can't rely on this after you have removed and added sprites.

    A more general solution (if your sprites are static in the z-direction) would be to extend the SpriteManager.AddSprite (...) method to include a sprite layer and do a quicksort to keep the indices sorted by layer when you add a new sprite.

    If your sprites are not going to stay parallel with the view plane, you will need to do this every frame; as in many particle systems where the entire mesh is actually re-generated every frame (SpriteManager makes a big mesh and just squishes the unused sprites down to a point; AddSprite (...) expands four vertices to form your quad)

    Also, if you want to use multiple SpriteManagers, you will probably want to replace the line of code in SpriteManager.Awake (...) that sets the manager at the origin with:

    Code (csharp):
    1.  
    2.         transform.position = Vector3.forward * transform.position.z;
    3.  
    so that you at least don't have sorting problems between managers.

    Maybe you should look into SpriteUI. I have not looked at it, but I saw somewhere that it supports gui layers, which must use some kind of index list sorting. If your sprites are not moving in the z, this will most-likely work for you.

    SpriteManager is a great class, and with a little polishing could be very useful, but I really think the community should apply some pressure here to get this very general functionality into the next Unity release (out of C# and into a compiled component!).

    Other than that, just make sure your shader is alpha-enabled, and if you want to use the vertex colors, that it also takes those into account.

    Hope that helps ...
     
  31. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    All of the above also depend on your camera not rotating around the subjects in your scene. If your camera moves around, then the z-order of the sprites would have to be determined based upon their distance to the camera each frame -- very expensive.

    But I agree, Unity really needs to implement something like SpriteManager natively into Unity since it would run much faster not running in script, and since the draw call overhead is so incredibly huge.
     
  32. 1r0nM0nkey

    1r0nM0nkey

    Joined:
    Apr 8, 2009
    Posts:
    131
    I would even be happy if they would only do this with GUITextures! :) Those things are unusable for anything other than text.
     
  33. Langaert

    Langaert

    Joined:
    Mar 2, 2009
    Posts:
    21
    Thanks for the in-depth explanation ironmonkey. I'm glad to know that I'm not crazy. Everyone keeps talking about shader problems, but the shader is not the issue. I will continue using my simple solution, as maintaining decent performance is already enough of a problem.

    I would consider having a native-level SpriteManager more than just a performance issue. It's also an asset chain issue. I commend everyone who has worked on SpriteManager, but part of the benefit of Unity is supposed to be an easy chain for inserting and updating assets. The asset chain for a 2D project in Unity iPhone using SpriteManager is a nightmare. Any time our artists make any significant changes or additions, there is a rather large amount of work to be done on my end.

    Add to that the fact that supposedly having a lot of Update functions running in an iPhone project leads to lag, and yet Unity is most advantagous when objects can all have a number of different components each doing their own thing. The advantages to Unity iPhone seem to start disappearing...
     
  34. 1r0nM0nkey

    1r0nM0nkey

    Joined:
    Apr 8, 2009
    Posts:
    131
    You are welcome :)

    Yes, 2D games can get unmanageable in terms of workflow and shear tonnage of image data; both source and runtime.

    Unity also starts to fall apart as the team grows; for small teams, Unity "unites" the disciplines of making games and does a nice job of it, for larger teams... yikes! I worked briefly with Unity on a Wii project where the unifying theory didn't work at all.

    And, I can sympathize with the workflow bottleneck of creating sprite sheets. You really need a stitching tool for a game with a significant number of sprites, which is any 2D game with animation. Unity should incorporate a texture stitcher to automate sprite sheet generation; it's really not that hard to do, and there is open source code floating around from NVIDIA and others.

    I'm really not sure about the overhead of Update calls; I also have spread my processing out among the components. I can say, for my part, Update overhead has not been an issue. But, you're right, if we say "screw Update! Im centralizing my processing!", then what is the point of the component model?

    Although, like I said, I haven't had trouble with performance yet; just with call order... when you split your game into many scenes and load them up, managing the dependencies and initialization orders is a major hastle.

    But, on the bright side, Unity is quite accessible, pretty stable, and respectably capable. I worked for a time with the Unreal3 engine, and I can say, it costs upwards of 800K and is a huge beast, but it also has issues where you just sit back and smack your forehead.

    We should make sure the Unity team is listening and responding to our needs as customers, but on the other hand making games just isn't easy! But its cooool! :D

    EDIT: btw, a respectable stitching tool also creates a data file so you don't need to synchronize texels/pixels; you simply refer to the sprite by name or ID.
     
  35. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    603
    Argh! I'm running into this annoying SpriteManager problem. When I create more sprites than the buffer allowance the sprites freak out and then the iPhone crashes. Has anyone had this problem before? I have to destroy and reInstantiate the SpriteManager to stop the errors.

    It only occurs on the iPhone for me, and it happens reliably when I have used more than 10 sprites, with my ten sprite Alloc Block Size.
     
  36. Poita_

    Poita_

    Joined:
    Dec 18, 2008
    Posts:
    146
    It's not a problem, that's how it works. The whole point of a buffer is that you do not go over the maximum size in any circumstances. If you need a bigger buffer then use a bigger buffer.
     
  37. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    603
    I only have seven sprites on screen. The rest have been destroyed. However, when I get to the tenth sprite drawn (including the ones I have destroyed) it gives errors, and then I think it crashes when I try to RemoveSprite on the corrupted sprites. This only happens on iPhone.
     
  38. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    603
    Code (csharp):
    1.  
    2. //  availableBlocks.Add(sprite);
    3.  
    Commenting out the availableBlocks.Add(sprite) seems to fix it! o_o Thanks to zero for this tip. It's found here:

    public void RemoveSprite(Sprite sprite)

    There is still some concern to me as to the knock-on effects of this, and whether it will just add sprites forever and never re-use the previous slots.
     
  39. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Strange, I'll have to look into this. When you reach the edge of the allocated buffer, it should automatically allocate more in increments of allocBlockSize.
     
  40. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    603
    There was some suggestion that this might be because of something automatic on the iPhone, such as garbage collection.
     
  41. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Were you able to narrow the point of the crash down to a particular line or area of code? Surely it wasn't availableBlocks.Add() that was the actual line where it crashed?
     
  42. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    603
    Unfortunately I wasn't able to narrow it down. I'm quite new to coding and I don't know any C# so it's not easy for me to debug something like this.

    This has been a persistent problem for me though and I've had to do several workarounds until now to make spriteManager work for me.
     
  43. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    What sort of work-arounds? I'm interested in being able to improve it.
     
  44. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    603
    My game Instantiates a whole new SpriteManager to for the next level, and then deletes the old one. It's pretty crude but it was the only way I could find until now that reliably wiped the buffer on iPhone.
     
  45. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Okay, I modified the Sprite Demo package to constantly call "DoStuff" every three seconds, which removes a few old sprites, replaces them with new ones, and then adds a few more on top of that so that the number is always increasing. The allocBlockSize is 10. It seems to work fine in both the editor and on iPhone.

    Please look it over (attached) and see if you can find what is different between this test and your project so we can narrow down the source of the problem you're having.

    (As a side note, as you can see after this demo runs for a while, I'm amazed at how capable the iPhone is handling this many rigid bodies. And without SpriteManager, just drawing that many objects and incurring so many draw calls would bring the iPhone to its knees long before the physics became the bottleneck.)
     

    Attached Files:

  46. atomic1der

    atomic1der

    Joined:
    May 10, 2009
    Posts:
    3
    Hoping someone can help me figure out how to get rid of these lines in my objects.

    I'm using the SpriteManager and instantiating a bunch of objects in the XY Plane.

    All are at Z-index 0. The TileMap that is being used has a bunch of 128x128 bitmaps and I am mapping them all to the objects with scale (1,1,0). So basically I have a bunch of 1x1 objects.

    I've specified Particles/Alpha Blended or Particles/Alpha Blended Z-Enabled for shader for the material that is assigned to the spritemanager. I've tried the CW and CCW for winding but that doesn't help.

    As I move my character along the screen I see the Vertices come in and out with or without lighting on. This happens whether the camera is in orthographic or not.

    Can someone help me figure out how to get rid of the lines?

    Thanks for your help!
     

    Attached Files:

  47. bobber205

    bobber205

    Joined:
    May 12, 2009
    Posts:
    139
    When I download that package, unzip it and open up the .unitypackage file, the first time nothing happens. Keeping unity open (it still has my default project on) I try to open it again and I get "cannot depress package".

    Any ideas?
     
  48. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    atomic1der:
    From the looks of the screenshot, it could be mip filtering. Try either turning off mipmapping, or pull your UVs in 1 pixel and see if either of those gets rid of the edge artifacts.

    bobber205:
    It wasn't zipped, so you shouldn't have to unzip it. It should just be a raw unityPackage file. Also, it was created with Unity iPhone 1.02, incase that's the problem.
     
  49. atomic1der

    atomic1der

    Joined:
    May 10, 2009
    Posts:
    3
    Thanks for the reply. I think it may be the UV offsets. I made sure MipMapping and filtering was off on the texture for the TileMap. And then played with the pixel widths and heights as well as adjusting the x and bottom.y variables.

    If I have a tile that's 128x128, and at (0,0) in my map, then I presume bottom pixel should be 127, and the width and height parameters should be 128. But if I set the width and height to 128-1, the vertex lines go away. I still have a couple tiles that want to display the vertex even though they are the same dimensions and offsets so will have to figure that out.

    Code (csharp):
    1.                
    2. Tile tile = (Tile) tileAtlas[prefabTemplate.materialName];
    3.  
    4. // Create the preFab and Put Sprite on it
    5. prefabTemplate.obj = Instantiate(prefab, prefabTemplate.position, Quaternion.identity);
    6. GameObject go = (GameObject)prefabTemplate.obj;
    7.  
    8. Sprite s = spriteMan.AddSprite(go, // The game object to associate the sprite to
    9.         prefabTemplate.scale.x, // The width of the sprite
    10.         prefabTemplate.scale.y,  // The height of the sprite
    11.         tile.x,                                  // Left pixel
    12.         tile.y + tile.height -1,      // Bottom pixel
    13.         tile.width,                           // Width in pixels
    14.         tile.height,                          // Height in pixels
    15.         false);                                  // Billboarded?
    16.  
    Each tile in the map lives in a hashtable where I code in the top, left, width and height. The code above just pulls in the appropriate offsets from the corresponding entry in the table.
    Code (csharp):
    1.  
    2. tileAtlas.Add("grass_l",    new Tile(     0, 0, 128, 128) );
    3. tileAtlas.Add("grass_r",   new Tile( 128, 0, 128, 128) );
    4. tileAtlas.Add("grass_t1", new Tile( 256, 0, 128, 128) );
    5. tileAtlas.Add("grass_t2", new Tile( 384, 0, 128, 128) );
    6.  
    By the way, this is an awesome tool. I've currently got 205 objects referencing 57 sprites in this spritemanager and it takes less than a second to instantiate the prefabs associate the sprites and draw them on an iPhone 3G, all in one draw call. Which is a huge improvement.

    As an aside, I have a workflow I adopted just for using this spritemanager. I build up each level graphically in a "prefab scene". I then use an Editor script I wrote to export all of the positions, rotations, scale and materials of the game objects in the "prefab scene" to a data file. The material names used in the objects correspond to entries in my hashtable. I then import the data file and use it within my "level building code" in the actual "runtime scene". This way I get the best of both worlds: WYSIWYG design and fast, efficient runtime code.
     
  50. atomic1der

    atomic1der

    Joined:
    May 10, 2009
    Posts:
    3
    There were two issues in the picture above:

    1) I had to set the width and height properties to tile width - 1 and height - 1.
    2) I had specified PRVTC compression on the texture to reduce memory consumption. Setting this to RGBA-16(original format), elminated the edge artifacts due to compression.