Search Unity

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

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

  1. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Just to make sure, are you using version 0.63? There were a couple of bugs I discovered in 0.622 that could cause something like this.

    Although this probably would show up before the Transform() call, be sure that when you remove your sprite, set any local references to that sprite to null, then in your code, before you ever dereference that sprite, check to see if it is null first. Otherwise what can happen is you may not realize that some of your code is being called that performs work on the sprite (like changing its color, resizing it, animating it, etc) even though it's been removed from the SpriteManager. Some such operations, such as resizing, will invoke Transform(), which tries to access the sprite's client GO. If the sprite has been removed from SpriteManager, its client GO will be null, and you'll get an exception.

    I had this problem in a project of mine and had to make sure that I set my sprite reference in my script to null at the very start, then always check to see if it is null from that point on. When the sprite is removed, I set the local reference to null, ensuring I don't "do anything" to that sprite reference again after it's been removed.
     
  2. Sarah

    Sarah

    Joined:
    Jun 11, 2009
    Posts:
    8
    Hi Brady,

    Can you elaborate on this a bit? Why would the Sprite object need to persist after you were done using it? I'm finding it hard to use the Hierarchy at runtime because there are so many dummy objects hanging around (not to mention having objects with duplicate names).

    You also mentioned in a recent post that there are issues around removing a Sprite's client before destroying the Sprite. Isn't this the opposite of what you state above?

    Thanks!
     
  3. anthropophagy

    anthropophagy

    Joined:
    Apr 28, 2009
    Posts:
    10
    you know that feeling, when you finally figure it out... that's easily my favorite feeling. Almost makes the enormous headaches worth it (almost). It's like brain freeze hurts so bad, but it feel so good as it's going away.

    so I figured it out. Thanks Brady, something you said led my mind in the right direction. -- so I had built this box around the stage so that if an object flew off in any direction, there were no holes for it to slip through and fall into the great abyss, but what was happening was if it happened to land in a corner and touch two walls at once it would try to deallocate the same block twice. -- since I guess the Destroy function actually waits until the end of the update loop before it actually destroys anything. So yeah, that explained the randomness, and why it actually got worse when I took the Destroy call out (cause the GO was still floating around running amuck)

    so I just made an airy box so that there were no corners, but the top and bottom were wider to catch any lucky escapist boxes. Thanks again Brady and to the community for your fantastic work.
     
  4. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    anthropophagy, glad you figured it out! I knew it had to be something like that.

    Sarah, yes, I suppose those two statements do seem contradictory at first. But actually they aren't. The sprite objects persist because they return to a pool of sprites awaiting use. It would be far less performant if the sprites were constantly destroyed and then re-allocated, constantly having to resize the buffers, etc. SpriteManager instead maintains two lists (well, actually three, but for simplicity's sake, we'll just consider two of them): an active list and an inactive list. When a sprite is "removed", it is not destroyed, but rather it is removed from the active list and is no longer transformed by a game object's transform (its client is set to null). However, it is then placed into the inactive list so that if you add another object to the system, instead of having to create a completely new sprite object and reallocate the entire vertex, color, etc, buffers, it merely brings the already-allocated sprite object back into activity by adding it back to the active list.

    So in the first case, it wouldn't do to tie the sprite to the client GO since that GO could be destroyed (as in anthropophagy's case), but the sprite object is not. Rather, the sprite object is returned to the the inactive list. But since Sprite is now of type Monobehavior, it must exist as a script object added to a GameObject. So what SpriteManager does is creates a dummy GO that has the sprite object added to it. This works since the dummyGO will exist as long as the sprite exists, so it fits the model.

    In the second case, you want to remove a sprite before you destroy its client game object because failure to do so will keep the sprite object in the active list and will therefore attempt to transform its vertices by its client object's transform. But since that client object has been destroyed, that will lead to an exception being thrown.

    Anyway, that's a lot of information, but I hope it clears things up.
     
  5. Sarah

    Sarah

    Joined:
    Jun 11, 2009
    Posts:
    8
    Got it! I guess it was more of a terminology problem - you do free the sprite in a manner, it just doesn't really get destroyed. Thanks for the clarification :)
     
  6. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    605
  7. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    605
    In a separate issue, one of my spriteManagers seems to be 'lagging' behind the rest of the game by 1-2 frames. It happens irrespective of whether Auto Update Bounds is active. Does anyone know what can cause this to happen?
     
  8. 1r0nM0nkey

    1r0nM0nkey

    Joined:
    Apr 8, 2009
    Posts:
    131
    Code (csharp):
    1.  
    2.  
    3. // from Sprite...
    4.  
    5.     public bool hidden
    6.     {
    7.         get { return m_hidden___DoNotAccessExternally; }
    8.         set
    9.         {
    10.             ...
    11.  
    12.             m_hidden___DoNotAccessExternally = value;
    13.  
    14.             if (value)
    15.                 m_manager.HideSprite(this);
    16.             else
    17.                 m_manager.ShowSprite(this);
    18.         }
    19.     }
    20.  
    21. // from SpriteManager...
    22.  
    23.     public void ShowSprite(Sprite sprite)
    24.     {
    25.         ...
    26.  
    27.         if (!sprite.m_hidden___DoNotAccessExternally)
    28.             return;
    29.  
    30.         sprite.m_hidden___DoNotAccessExternally = false;
    31.  
    32.         ...
    33.     }
    34.  
    Is this code correct? Or am I missing something on usage?

    * if the sprite is hidden and I unhide it with sprite.hidden = false
    * then won't it jump out of ShowSprite(...) prematurely?

    m_hidden___DoNotAccessExternally is set to false in the property, then checked in ShowSprite(...), which returns, thinking that the call was made on an already visible sprite.
     
  9. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    dock,
    offset: Yes, I have not yet "fixed" (added a feature) which conveniently applies the offset. However, there is a very simple work-around that should work. After setting the offset value (which currently only sets the values for the offset member, but performs no vertex modification), simply call SetSize*(). So, for example, assume you had a sprites in the XY plane, you'd call:

    Code (csharp):
    1.  
    2. sprite.offset = Vector3.right;
    3. sprite.SetSizeXY(sprite.width, sprite.height);
    4.  
    That should work. I know it's not as convenient as I'd like it, but it's a simple way to make it work. Alternatively, you could make "offset" into a property (instead of just a member) and automatically perform this operation in the "set" property. I would do this already except I currently don't track the sprite's plane (XY, XZ, or YZ). If it was merely added to the current vertex values, then subsequent offset "calls" would incrementally offset the vertices rather than setting them to the desired offset. I'll try to get this smoothed out better in the next release.

    As for your lag problem, I have no idea why that would be happening. I tend to think that wouldn't have anything to do with SpriteManager. I could be wrong, but I can't think of anything that could cause that. It seems more likely it's something peculiar to your particular situation and code.

    1r0nM0nkey,
    You're right. I think I've fixed this in my internal version now, and here's what I did: I just removed the line in the "hidden" property of the Sprite class which assigns the value to the m_hidden__... member since this gets set in HideSprite()/ShowSprite() anyway. That should solve it. I haven't tested it yet, but I think that'll do it. See if it works for you.

    Thanks everyone for helping me continue to identify issues that need to be resolved! This is precisely one of the reasons I made this public, so that many eyes upon it could help identify problems and improve it. Thanks again!
     
  10. 1r0nM0nkey

    1r0nM0nkey

    Joined:
    Apr 8, 2009
    Posts:
    131
    Ok, I'll make that change. One quick question though:

    Is it important to have similar checks in HideSprite(...) as well? Something like:

    Code (csharp):
    1.  
    2.         if(sprite.client == null)
    3.             return;
    4.  
    5.         if (sprite.m_hidden___DoNotAccessExternally)
    6.             return;
    7.  
    8.         sprite.m_hidden___DoNotAccessExternally = true;
    9.  
    10.  
    I really appreciate the work you've done to provide SpriteManager! I wish Unity were as active as you are on sprite sheets! Thanks!
     
  11. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    No, it shouldn't be necessary for hiding because the worst that can happen is the sprite is attempted to be removed from a list it is not in, and it does nothing. The reason the checks are done in ShowSprite() is so that the sprite doesn't get added to the lists twice. Since the client object isn't accessed, there's no need to check to see if it is null either.
     
  12. HMachuca

    HMachuca

    Joined:
    May 4, 2009
    Posts:
    36
    Is there a reason why SetColor doesn't work? I've seen some fixes for the RemoveSprite() function but that's not exactly what I'm looking for. In my case, the SetColors function doesn't work at all.
     
  13. 1r0nM0nkey

    1r0nM0nkey

    Joined:
    Apr 8, 2009
    Posts:
    131
    HMachuca

    make sure your shader respects vertex colors
     
  14. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Hey Brady,

    just getting around to swapping out the old SM for the new one.

    I have several GOs with the LinkedSM dropped onto them.

    I just took the code from the wiki and swapped out the code in LinkedSM (and nothing more), I swapped out the code for SM (and nothing more) and created a new Sprite class and dropped in the code from the wiki and dragged that onto a GO.

    I have some sprites not showing (same Linked as other sprites that are showing) anything I am missing ? (I have a zillion and one temp GOs when running)

    thanks (as always)

    Also: Is it worth updating given that the old SM does everything I need (thinking of performance enhancements)
     
  15. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Just to be safe, I'd download the .zip package in the first post which has all the latest files. I'm not sure why some sprites wouldn't be showing.

    If the last revision was working fine for you, then there's not much reason to update unless you need animation or were encountering some of the bugs that were in the previous release. Bugs such as the color not being reset upon sprite removal, etc. But none of the bugs should threaten stability, only functionality. And if you haven't encountered functionality problems, then you're not using it in such a way as to invoke those bugs.

    So are you having problems only since the update?
     
  16. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Hey Brady,

    missing sprites turned out to be an atlas issue.

    If there are no performance reasons then I will go back to original SM (only removal which we spoke about a while back was a prob but not any more).

    Not sure for a whole heap of temp GOs and was concerned about performance with them (I had a huge amount).


    (should have used the zip but the cut and paste seems fine)

    thanks
     
  17. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Yeah, there will be a temp GO for each sprite in the pool (not just active sprites). Also, since the newer version's Sprite class derives from MonoBehavior, each has its own Update(). I'm not sure if that has any impact since Update() is not defined. But if it does, then the older version may be slightly faster for that reason as well.

    However, I came across a horribly unoptimized bit in LinkedSpriteManager that somehow evaded my notice. There are lots of temporary vars that get allocated in LateUpdate(). I've made changes so that only the absolutely necessary ones are left, and they get allocated once for the entire object. I'll be releasing the updated LSM file soon, and you should be able to use it with the old SM since LSM doesn't really touch any of the changed portions of the Sprite or SpriteManager classes.
     
  18. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Thanks Brady

    will keep with the old SM and look out for the new Linked. Given the number of sprites the game is managing then I would be concerned about the temps.

    Game is only a few weeks away now so I hope to pm you as we get closer with details/links

    thank you
     
  19. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Cool! I'd certainly appreciate that. Looking forward to it.
     
  20. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Hey (again) Brady,

    I have 2 separate LinkedSMs.

    In one I create 5 Sprites at 0.4f on the Y axis. In the other I create 2: 1 at 0.2f and the other is a child created at 0.1f (which overlays its parent).

    In the gameplay when 4 of the 5 sprites pass over the first sprite (the parent) then the overlay shows on the parent and the 5th sprite passes over it.

    This works fine if the single parent sprite is created before the 5 sprites. However if the 5 sprites are created first then when the overlay is created after the 4th sprite passover the 5th sprite goes under the overlay.

    I understand the z order issue when sprites are created in the same SM but here there are 2 SMs and the 5 sprites are at 0.4f whilst the overlay is at 0.3f ?

    Clearly it is linked to creation order but as I say they are separate SMs ?

    Is there a way around this ?

    thanks
     
  21. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Hmmm... this sounds like less of an SM issue and more of a Unity quirk issue. Some of the sorting issues have been discussed in this thread, and it can sometimes be a bear. But I don't know that any issues have yet arisen involving multiple SMs. Perhaps it has something to do with draw order, and the one SM is being drawn before the other?

    Personally, it seems to me that, using the right shader, any polygon rendered in front of another, regardless of its draw order or mesh membership, should appear to occlude polygons behind it. After all, a character mesh's polys self-occlude depending on orientation.

    Does anyone have any ideas here?
     
  22. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    In case anyone has any ideas here is the shader I am using (no idea about shaders but this has been ok so far)

    Code (csharp):
    1. Shader "SpriteMan"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Color Tint", Color) = (1,1,1,1)
    6.         _MainTex ("Color (RGB) Alpha (A)", 2D) = "white"
    7.     }
    8.  
    9.     Category
    10.     {
    11.         ZWrite Off
    12.         Cull Back
    13.         Fog { Mode Off }
    14.         Blend SrcAlpha OneMinusSrcAlpha
    15.         Tags { "Queue" = "Transparent"}
    16.  
    17.         SubShader
    18.         {
    19.             Pass
    20.             {
    21.                 SetTexture [_MainTex]
    22.                 {
    23.                     ConstantColor [_Color]
    24.                     Combine Texture * Constant
    25.                 }
    26.             }
    27.         }
    28.     }
    29. }
    thanks
     
  23. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    I think you'll need Z writes for the z buffer to work. The z buffer is what tells which pixels are in front of others, thereby allowing nearer polygons to occlude ones farther away.
     
  24. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Thanks Brady,

    I know squat about shaders but changing the ZWrite Off to ZWrite On seems to have fixed it.

    I would be interested to know if anyone has a better/more efficient shader.

    thank you again

    Edit: seems to have introduced too many other issues (sprites not showing correctly). Will need to look some more into the shader
     
  25. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    In what way are the sprites not appearing correctly now?
     
  26. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Hi Brady,

    looking back through this thread I think it was mentioned somewhere about making sure that ZWrite was off and it seems like there is good reason for that. In our case imagine a square sprite with an explosion in the middle and of course transparency around it. With ZWrite On you see explosion (and then we swap out the sprites to give the appearance of the explosion getting larger) but you see the explosion contained within the square (hard to explain sorry). Also when sprites are on top of each other you get a sliding effect as one passes over the other. It's all pretty messy and of course goes away with ZWrite Off.

    Not found another shader yet but we have a workaround which should suit us fine for this one particular situation. Would be better to have a shader which can handle this but no complaints given that SM is great :)

    thanks for the help
     
  27. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Ahh yes. There's a couple of ways around it, such as using Z testing. But that won't work for semi-transparent objects.

    I've actually been working on a partial solution lately which allows you, the developer, to move a sprite to the front or back of the drawing order.

    I should be posting this update soon, so it may help you out.
     
  28. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Thanks Brady,

    I guess that solution would be for sprites in the same sm ?
     
  29. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Yes, it wouldn't really help in the case of multiple SMs not rendering in the order you want. In that case, we'll have to figure out how Unity determines drawing order among meshes. I'm not sure about that. The only thing that comes to mind at the moment is to apply a layer mask to one of the SMs and use a separate camera set to only render that layer. That would fix it since you can set rendering order for cameras.
     
  30. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Okay, I've uploaded a new .ZIP to the first post, and also updated the Wiki with version 0.631. This version includes a couple of the aforementioned fixes as well as the ability to specify where you want sprites to be drawn in the drawing order. In addition to being able to specify that you want a particular sprite drawn before or after (appearing behind or in front of, respectively) another sprite, or to move a sprite to the beginning or end of the drawing order, you can also specify a sprite's "drawLayer". This allows you to set a numeric value for various "layers" of sprites.

    Think of it like this: let's say you have a classic carnival shooting gallery type of game. You want ducks to always be in the back, targets in the middle, and cans in the front. You can assign ducks a drawLayer of 0, targets 1, and cans 2. This will mean the ducks are drawn first, then the targets, then the cans, so that whenever they overlap, the cans will appear to occlude the targets, and the targets will appear to occlude the ducks.

    Please see the wiki docs on drawLayer, SetDrawLayer(), and SortDrawingOrder() to understand how to use these. This should solve a lot of people's problems! Have fun!
     
  31. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Thanks Brady.

    I am still using the 'old' version for now (the temps worry me). Will wait for the LinkedSM update (you mentioned that it was not optimized).

    Without SM the pseudo 2D type game is not available on the iPhone with Unity. Hopefully there is some recognition from Unity for the work you are putting in on this.

    thanks
     
  32. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    The updated Linked SM is part of the new release, so you should be able to download the zip in the first post and just use the LinkedSpriteManager.cs file that is inside with the old version.
     
  33. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    I did skim over linked sm on the wiki and did not see any changes. Will take another look.

    Thank you
     
  34. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    It's nothing real major, just some cleanup of TransformSprites(). You may not notice any improvement, but you might as well have the cleaner code with fewer allocations per frame.
     
  35. damien

    damien

    Joined:
    Jun 17, 2009
    Posts:
    32
    In using any of the new draw order methods (MoveToFront, MoveToBack, etc.), I am getting all IndexOutOfRange exceptions. None of the sprite indexes are being found in the following line which appears at the top of all the new draw order methods, so all offsets are being set to -6:
    Code (csharp):
    1. int offset = spriteDrawOrder.IndexOf(s) * 6;
    I am scripting in C#.
     
  36. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Yes, I caught that recently and added code to anticipate that possibility. Basically, it's just this:

    Code (csharp):
    1.  
    2. if (offset < 0)
    3.     return;
    4.  
    It should be finding the sprites in the list, though there are rare occasions where I've seen the sprites not be found and I'm trying to figure out under what circumstances that would occur. Are ALL sprites not being found for you? Or is it just certain ones, or a periodic times?
     
  37. ugur

    ugur

    Joined:
    Jun 3, 2008
    Posts:
    692
    i recently released my first game making heavy use of the SpriteManager, its called Puzzled Pet Planet (PPP) and you can see that here:
    http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=315478103&mt=8
    so i wanted to say thanks for all your efforts Brady =)

    Its not just about pimping and props giving though, i also wanted to discuss something =)
    So for PPP i worked on my own Sprite animation handling and that worked fine for my needs there (and is funnily quite similar to what you have going there in the latest SpriteManager update now) but for my next game i need more sophisticated animation handling so i wanted to bring it up here to discuss to see if you guys think it would be something to do in SpriteManager in an update or i should cook up my custom solution again =)

    So the thing is the PPP animation system, like the current one in SpriteManager is mostly about tilebased cell animation. So its expected that each cell has the same dimensions and then one cell after the other is shown. So then its also more about passing in which cells make up an animation.

    Well, for what i want to do in my next game i thought it would make more sense to create a KeyFrame Class which holds the data for what to show in one frame of an animation.
    That class could have properties like this:

    -uvX (or pixelX) : offset position x in texture
    -uvY (or pixelY) : offset position y in texture
    -uvWidth (or pixelWidth)
    -uvHeight (or pixelHeight)
    -displayX: where to display it relative to the sprite position
    -displayY: ""
    -rotation: at which rotation to display the image/ sprite during this keyframe
    -alpha: at which alpha to display the sprite during this keyframe
    -display duration: how long to display this frame


    So then to define an animation one could create an array of Keyframe objects, one could get away with smaller spritesheet textures (as not all cells have to have the same big dimensions) and the additional properties would allow to create more varied animations.

    What do you think about something like this?
     
  38. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Good job on the game! Thanks for posting this here.

    As for the animation, that definitely sounds like something you could roll into the current UVAnimation class to extend its functionality. Though I'm not sure why you would need rotation information in the animation since that can be handled by the GO to which the sprite is attached. But I suppose if that's more convenient for your case, that would work just fine.
     
  39. drahn

    drahn

    Joined:
    Jun 19, 2009
    Posts:
    16
    I am having a problem downloading and using this demo package. When I open it I have like 12 folders named things like ABSDJBSJHBDSJHFGDKFJSDKF - any ideas?

    UPDATE:
    Ok newb error. Seems loading the package on the Mac failed, but opening it on the PC I was able to import the package into unity. Now I am sending over to my mac.
     
  40. drahn

    drahn

    Joined:
    Jun 19, 2009
    Posts:
    16
    Does anyone have a unity project they could share with me that demonstrates the BuildUVAnim functionality in use? Here is what I am doing but I am not getting any results:

    Code (csharp):
    1. public class spriteman : MonoBehaviour
    2. {
    3.     public LinkedSpriteManager SpriteMgr;
    4.     public Sprite mysprite;                     //The sprite of the gameobject
    5.     public UVAnimation anim = new UVAnimation();
    6.     public int x;
    7.    
    8.     void Awake()
    9.     {
    10.         SpriteMgr = (LinkedSpriteManager) GameObject.Find("GO_SpriteManager").GetComponent(typeof(LinkedSpriteManager));
    11.     }
    12.  
    13.     void Start ()
    14.     {          
    15.       mysprite = SpriteMgr.AddSprite(this.gameObject,
    16.                     1.0f,      // The width of the sprite
    17.                     1.0f,      // The height of the sprite
    18.                      0,         // Left pixel
    19.                      50,        // Bottom pixel
    20.                      50,        // Width in pixels
    21.                      50,        // Height in pixels
    22.                      false);   // Billboarded?
    23.                      
    24.       anim.BuildUVAnim(new Vector2(1.0f, 1.0f), new Vector2(1.0f, 1.0f), 10, 1, 10, 30f);
    25.  
    26.       anim.name = "walk";  // name of animation
    27.  
    28.       anim.loopCycles = 10; // number of times to loop before stopping
    29.  
    30.       anim.loopReverse = true; // Reverse play back to beginning once the end is reached
    31.       mysprite.AddAnimation(anim);
    32.       mysprite.PlayAnim("walk");
    33.  
    34. }
    35.            
    36.    
    37.     void Update()
    38.     {
    39.        
    40.         if (x==0) // lets just play the animation once for testing
    41.         {
    42.             x++;
    43.             mysprite.PlayAnim("walk");
    44.         }
    45. }
     
  41. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    It looks like you're not defining the start and cell size properly. The start argument is where, in UV coordinates, the lower-left corner of the first sprite in a series of sprites begins in the texture atlas. Usually, the easiest thing to do for this is to specify it in pixel coordinates using the following function:

    SpriteMgr.PixelCoordtoUVCoord(0,50)

    That will return the UV coordinates of pixel 0,50 of the texture atlas, for example. Look to see where the lower-left pixel is of the first sprite in the series, and use that. Currently, you're using 1,1, which points to the upper-right corner of the texture, which is certainly not where the lower-left corner of your first sprite is located.

    The cellSize argument defines, in UV space, the size of each sprite "cell" (frame of your animation). To use BuildUVAnim(), each "cell" should occupy the same width and height in pixels. Again, it is easiest to use the following method:

    SpriteMgr.PixelSpaceToUVSpace(50,50)

    Note this unlike PixelCoordToUVCoord(), this is used for pixel-to-UV space conversion - as opposed to UV coordinate conversion. There is a difference. Anyway, the above example would return the UV-space equivalent to 50 pixels wide by 50 pixels tall (not screen pixels, mind you, but texture pixels). So if each "cell" of your sprite animation is 50x50 pixels in size in your texture, then that's what you would use for the cellSize argument. Currently, you are passing 1,1, which in UV space means the full width and height of the entire texture, which again is surely not what you want for an animation.

    So given what you listed as your arguments when creating the sprite, I'm going to guess that the proper args for BuildUVAnim() in your case would be:

    Code (csharp):
    1.  
    2. anim.BuildUVAnim(SpriteMgr.PixelCoordToUVCoord(0,50),
    3.              SpriteMgr.PixelSpaceToUVSpace(50,50),
    4.              10, 1, 10, 30f);
    5.  
    I also noted that you have loopCycles set to 10 while your animation contains 10 frames. Just to be sure you know, if you only want your animation to play through once (that is, play through all 10 frames one time), you would set loopCycles to 1. Setting it to 10 will cause it to loop through the entire animation 10 times before stopping. That may be what you intended, but I just wanted to make sure that was clear.

    Also, loopReverse will cause the animation to reverse direction when it reaches the end. So in other words, your walk animation would play forwards until it reaches the 10th frame, then it would play in reverse, making your character appear to walk backwards.

    Anyway, I hope that helps.
     
  42. drahn

    drahn

    Joined:
    Jun 19, 2009
    Posts:
    16
    ABSOLUTELY! Thank you for the reply! I have it working but I have a GIANT SPRITE... LOL! Somewhere I must be plugging in the wrong figures. I'll bang at it for a bit and see where I get. Thanks again.
     
  43. LeFishy

    LeFishy

    Joined:
    Feb 11, 2009
    Posts:
    87
    I may be being entirely stupid with this but who knows. My sprites appear to be drawing but not correctly in the slightest. They are only visible if I zoom quite far out in the editor. Any idea why this might be. They are completely invisible in game.
     
  44. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    I'm not sure. That's odd behavior. Could it be winding order? Check out the demo project and make sure things are set up right.
     
  45. bobber205

    bobber205

    Joined:
    May 12, 2009
    Posts:
    139
    Pardon me if I've missed it, but is there example code for the SM that doesn't require the iPhone version to use?
     
  46. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    SpriteManager should work on regular Unity. I've not tested it, but I can't think of anything in it that would be iPhone-specific.
     
  47. mudloop

    mudloop

    Joined:
    May 3, 2009
    Posts:
    1,107
    I tested it (before I had a macbook I started my game with regular Unity), and it worked perfectly. It wasn't the most recent version though.
     
  48. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Hey Brady,

    using SetSizeXZ(). The original sprite size was 77 x 77 and the new size is 112 x 112 so I use Sprite.SetSizeXZ(112,112);

    The result is that the sprite is huge but this may be to do with the fact that the sprite is not in the correct position (so the Y is much higher giving the appearance of a larger size). Do I need to call another method in order to put it back in the correct position?

    It doesn't seem so looking at the code but I must be missing something.

    thank you as always for the help
     
  49. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Nothing about SetSizeXZ() should be repositioning the sprite. Check your offset, and also check to make sure your SpriteManager object is at the origin. Also check the associated GameObject's scale and such.
     
  50. mudloop

    mudloop

    Joined:
    May 3, 2009
    Posts:
    1,107
    Hey,

    I'd like to build and animate a (flat) skeleton, and then have different sprites "attached" to this skeleton.

    Two options I can think of :
    - dynamically weighing the vertices of the sprites
    - parenting the gameobjects that are linked to the sprites to the joins, but I think this might have the rotations in the wrong place (since rotating a sprite rotates it at the center, which won't always be right

    Off course I'll epxeriment myself, but I'm at work right now, and was wondering if there already was a solution for this...

    Thanks!