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. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    I believe someone else already did something like this in another thread. I think they made a class available for doing it, but I'm not certain. It was a separate solution from SpriteManager. IIRC, it was posted about the same time as SpriteManager too.
     
  2. mudloop

    mudloop

    Joined:
    May 3, 2009
    Posts:
    1,107
    Thanks, even though it's a bit vague :)

    Another question, do you think SpriteManager will be redundant when 1.1 is released? The recalculating of the veretices etc seems like an overhead to me due to the batching...
     
  3. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Yeah, sorry, I just remember that someone posted something along those lines, but I can't remember who, and I don't think it was given a specific name that I recall, so it's not much to go on. Sorry.

    As for 1.1, it's certainly possible. I've been hoping that this could be accomplished in-engine, since vertex transformation in native engine code would be faster than doing in-script, as SpriteManager must do. However, some of the sprite animation facilities of SpriteManager will likely not be present in 1.1, so I will likely wind up adapting certain SM features to 1.1's feature set, so we can have the best of both worlds.
     
  4. Martin-Schultz

    Martin-Schultz

    Joined:
    Jan 10, 2006
    Posts:
    1,377
    I'm getting always these ugly "Shader wants normals, but the mesh SpriteManager doesn't have them" reports in the Unity log. So far I learned that it depends on the shader if that error is thrown or not. I'm usually using "vertex lit" shader or "transparent vertex lit" to avoid unnecessary draw calls. Is there anything I can do to not get that spam in the logs? I've tried a few other shaders but always do get these warnings. Any help greatly appreciated.
     
  5. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    I'm using the "Particles/Alpha Blended" shader which does not require normals. Of course, you could always allocate a dummy normal buffer and assign it to the SpriteManager mesh object too... but that doesn't really seem necessary.
     
  6. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Okay, I've uploaded another update to the SpriteManager suite of classes. You'll find the latest version both on the wiki, as well as in a zip in the first post to this thread. You can see more detail on what's new in the change logs on the wiki, but besides a couple of stability and performance tweaks, the main change here is that the Sprite class is now no longer derived from Monobehavior. What does this mean?

    Well, for one, it means there is no longer a need for "dummy" GameObjects to host Sprite objects. So all those extra cloned GOs some of you complained about in the previous version are now gone. Also, this should lead to much better performance since being a Monobehavior means you have an Update(), which must get called each frame. Now that overhead is gone and a Sprite's animation routines only get called if its animating.

    Why was Sprite derived from Monobehavior before? Because the animation facilities made use of Invoke() and InvokeRepeating(). But this is now accomplished by keeping a list of active animations in the SpriteManager object, and then each frame an animated Sprite's StepAnim() routine is called to advance its animation. If it is not time to advance yet, a counter is incremented and nothing is done. This way, there's only a function call overhead for objects that are actually currently animating.

    All of that having been said, to the end-user/developer, all the animation functionality should appear unchanged. There should be no new conventions or methods to deal with. So any code you currently have that uses animation features should continue to work without any changes.

    Now it is somewhat conceivable that in a game with LOTS of sprites, where pretty much ALL of them are animating ALL THE TIME, this may potentially be slower than the previous approach. If so, feel free to continue to use version 0.631. But for most of you, I think you'll get a lot better performance from 0.632.

    Enjoy! Oh, and as this is becoming increasingly more complex, please let me know of any bugs you discover. I'm not so concerned with most of SM as it's been thoroughly tested by everyone, but I'm more concerned about the animation stuff. So let me know if you find anything unexpected with animation.

    And don't forget the new Draw Layers feature! I've personally found this very useful of late in my most recent game. For 2D orthographic games, this is very useful. I recommend planning out and assigning a numeric "layer" to each type of object in your game (probably in increments of 10, so you can insert other things between later on without having to recode) to keep things drawing in the correct order.

    For example, in my game, I have UFOs, bombs, explosion effects, score graphics, etc. I always want UFOs drawn on top of bombs, explosions on top of UFOs, and scores ontop of everything else. So my layer assignments look something like:

    Bombs 10
    UFOs 20
    Explosions 30
    Scores 40

    This is done by assigning one of these values to your sprite, and then calling SortDrawingOrder() sometime afterward like so:
    Code (csharp):
    1.  
    2. bombSprite.drawLayer = 10;
    3. ...
    4. sManager.SortDrawingOrder();
    5.  
    I separate them by 10 incase later I come up with another object type I want drawn between two of these. The end result of all of this will be properly drawn sprites, with the correct apparent depth.
     
  7. mjankela

    mjankela

    Joined:
    May 2, 2009
    Posts:
    19
    Hello to all,

    First of all thank you for the great sprite manager class.

    I am not sure if someone has the same problem with the new sprite manager class 0.62+;

    The old sprite manager class worked for me excellently and fine, but simply the new sprite manager does not paint any objects for me at all.

    The screen stays dark.

    I am not sure if I am using it correctly in the new form.

    Does anyone have a simple example demo regarding the new sprite manager/LinkedSpriteManager, showing an instanciation in javascript and a simple animation.

    Thank you,

    Martin
     
  8. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Interesting. As far as the basic SM functions (not animation), there shouldn't be anything different from the older version that would keep it from displaying. Just make sure you have it set to draw in the correct plane (XY, XZ, or YZ), and make sure you're using a shader that works. Try Particles/Alpha Blended just to see if its a shader problem. Also, use a scene frame (in-editor) and rotate around your scene to make sure your camera isn't just looking from the wrong direction, in which case you'll need to reverse the winding order.

    Sorry, I haven't updated the demo project yet with the new version to show the new features.
     
  9. devknob

    devknob

    Joined:
    Apr 2, 2009
    Posts:
    66
    I use multiple spritemanagers, how do you keep one spritemanager's sprites in front of the other spritemanager sprites??
     
  10. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Now that's a good question. From some limited experimentation I've done, it seems that Unity will draw back-to-front based on the bounding volume of the mesh. So if SM1's bounding volume is nearer to the camera than SM2's, even if SM1 has polys farther away than SM2, SM1 will be drawn after SM2 and therefore appear in front of it. But also bear in mind that unless you have a bounding volume recalculation scheduled, you'll have to manually call UpdateBounds() to recalculate the bounding volume. So see if it works to have the SM you want in front to have polys nearer the camera, then recalculate its bounding volume. Then proceed to add your additional sprites.
     
  11. FedericoStein

    FedericoStein

    Joined:
    Jul 26, 2009
    Posts:
    5
    Hi everyone!

    I'm new to Unity, and I'm just starting a port of a game in Flash for the iPhone, and the SpriteManager is a blessing for me, so I wanted to say thank you Brady! :D

    So far I had no real issues using it, and got sprites moving happily on my screen (I haven't tried animation yet, but I'll do it soon enough).

    I've noticed that in the Mesh Renderer component that gets created on the GO that has the SM, the flags for Cast Shadows and Receive Shadows are on, and I'm wondering if disabling them (in case that are not needed for your projects, of course) will help with performance.

    I don't have yet an actual iPhone (I'm even working on the Windows demo until I get a Mac) so I can't run any tests.

    In case that anyone wants and can try if this actually has any effect, I added this code in the Awake() method of SpriteManager.cs

    meshRenderer.renderer.castShadows = false;
    meshRenderer.renderer.receiveShadows = false;

    right after the line
    meshRenderer.renderer.material = material;


    Well, again, thanks for the good job! I have only 1 month to do a demo, so you can imagine how happy I am to have found this :D
     
  12. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Thanks for the kind words. As far as I'm aware, shadows are not currently supported on Unity iPhone, and those flags are therefore ignored.
     
  13. FedericoStein

    FedericoStein

    Joined:
    Jul 26, 2009
    Posts:
    5
    That solved it, then ;)
     
  14. Litewraith

    Litewraith

    Joined:
    Jul 7, 2009
    Posts:
    2
    Hello all,

    I'm wondering if someone can help me out with a odd bug I've run into with the spritemanager. I put in the images and when I'm using the AddSprite() it seems that when I'm using the AddSprite(), I need to divide by 2 to get the images to load the current image.
    I have to use:

    mySprite = SpriteMgr.AddSprite(this.gameObject, 1, 1, 0, 896/2, 512/2, 512/2, false);

    instead of

    mySprite = SpriteMgr.AddSprite(this.gameObject, 1, 1, 0, 896, 512, 512, false);

    to have the correct image load. The image is 512 by 512, and part of a larger atlas.

    Do the images need to follow a certain format to load correctly?
     
  15. mudloop

    mudloop

    Joined:
    May 3, 2009
    Posts:
    1,107
    Just a guess, but it could be your import settings for the image...
     
  16. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    If it isn't your import settings that are resizing the texture, also make sure that if you are supplying pixel values, that you use PixelCoordToUVCoord() and PixelSpaceToUVSpace() as described in the docs.
     
  17. MikeB

    MikeB

    Joined:
    Mar 19, 2009
    Posts:
    7
    Has this happened to anybody?

    All of my sprites show up just fine in the Editor, but on the iPhone . . . nothing. They just aren't there. :eek:

    I'm using the LinkedSpriteManager with one material. The Shader is Transparent/Vertex Lit. I've tried Particle shaders and they don't seem to work either.

    Sorry if this has been asked before. I couldn't find anything about this particular issue in the thread. Thanks.
     
  18. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Thanks strange... Is it possible whatever is supposed to be behind them is getting drawn last and therefore ontop of the sprites? If so, check a few posts up to see my recommendations on how to keep the Sprite mesh drawing ontop of other meshes.
     
  19. drahn

    drahn

    Joined:
    Jun 19, 2009
    Posts:
    16
    Yes thanks that is what the problem seems to be.
     
  20. LeFishy

    LeFishy

    Joined:
    Feb 11, 2009
    Posts:
    87
    UpdateBounds() fixed that for me.
     
  21. MikeHergaarden

    MikeHergaarden

    Joined:
    Mar 9, 2008
    Posts:
    1,027
    I found a bug where using X animations, it will mess up the animations after you instanciated more than the allocsize sprites (even when you never exceed the alloc size).

    This is caused by reusing an old sprite: It ill never clear/reset the animations.
    A easy fix is for example:

    Add this to the Sprite.cs
    Code (csharp):
    1. public void ClearSprite(){
    2. PauseAnim();
    3. animations = new ArrayList();
    4. }
    5.  
    And this to SpriteManager.cs (in RemoveSprite, before "availableBlocks.Add(sprite);" )
    Code (csharp):
    1.  
    2. sprite.ClearSprite();
    3.  
    Edit: I am using this in unity 2.5.1 (after which this will be ported to iphone as well). I guess that's why no one else experienced this as of yet?
     
  22. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Good find! I'll get this fixed in the next revision. Thanks!
     
  23. MikeHergaarden

    MikeHergaarden

    Joined:
    Mar 9, 2008
    Posts:
    1,027
    I didn't totally fix it yet..for example theres still an issue where switching animations will speed up the speed of the animation afterevery switch.

    I also had to add this hack to sprite.cs due to lack of time:

    Code (csharp):
    1. public bool StepAnim(float time)
    2.     {
    3.         if(curAnim==null){
    4.             PauseAnim();
    5.                         return false;
    6.         }
    This hack was required to prevent a nulref. But I guess with a proper fix to the animation bug(s) StepAnim shouldn't need to be touched.

    For my game everything runs well now. Key to these bugs is that re-usage of sprites in the sprite alloc array does not properly reset the animation data.

    Anyway; Thanks! My game is down to 5 draw calls (including 3 GUILayout.Labels).
     
  24. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    If you're using the previous version, you'll need to call CancelInvoke(). If you're using the latest version, the sprite's entry in the active animation array in the main SpriteManager object will need to be removed. I'll try to get a proper fix out for this in the next couple of days.
     
  25. Litewraith

    Litewraith

    Joined:
    Jul 7, 2009
    Posts:
    2
    Hey everyone.

    New to Unity and I love Spritemanager, definitely has made things easier. However I'm wondering is there anyway to use multiple SpriteManagers. I've been trying to figure it, but it seems that one of the manager's sprite is hidden behind anothers. Is there a way to get them to layer correctly?
     
  26. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Please see some of the recent posts on this subject. You should find my suggestions for this issue just a few posts back.
     
  27. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Leepo, try out this updated version. It's my internal version so it has some stuff in there that gets cleaned out before final release, but before releasing another iteration, I want to give you a chance to test it under your circumstances to see if it resolves the problems you're having in particular. Let me know as soon as possible so I can integrate this into a release.

    Thanks again for helping to spot this!
     

    Attached Files:

  28. MikeHergaarden

    MikeHergaarden

    Joined:
    Mar 9, 2008
    Posts:
    1,027
    Thanks, the bug I had to add that hack for is now gone.

    Another bug that (for my game) can be considered a feature is still there:
    When switching animations on one specific sprite; the more you switch, the faster it'll play the animations (In my game you switch on/off a parachute on a character; every time you switch this parachute on and off the character will start flapping his arms faster).
    I guess this is something along the lines of having the same sprite+animation appear twice in the "playingAnimations", so that (Linked)SpriteManager calls OneStep multiple times.

    The first thing I could come up with to fix this was:
    Code (csharp):
    1.     // Starts playing the specified animation:
    2.     public void PlayAnim(string name)
    3.     {
    4.         if(curAnim!=null){
    5.             m_manager.StopAnimation(this);
    6.             curAnim=null;
    7.         }
    8.         for (int i = 0; i < animations.Count; ++i)
    9.         {
    10.             if (((UVAnimation)animations[i]).name == name)
    11.                 PlayAnim((UVAnimation)animations[i]);
    12.         }
    13.     }
    This works, not sure if that curAnim=null; was required, but the StopAnimation was the key to fixing this as playing a new animation, will not stop the manager from double/triple/... managing the animation.

    I'm glad you also updated "(changed + to -).". That one confused me for a bit, but after I changed everything to -X I assumed sprites were supposed to work like that ;), back to +X now.

    Our first (free)iphone game has been submitted yesterday, keep an eye out for "Paradude";). It makes great use of SpriteManager.
    Thanks!
     
  29. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Ahh yes, in the switch to the new animation system, I neglected to anticipate the eventuality that users would play animations before explicitly stopping the previous ones. I should have thought of that since that is a very natural way to use it. Thanks for catching that! I'll make the change right away and do a release ASAP.
     
  30. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Okay, I've uploaded version 0.633 which should now solve the issue Leepo reported, as well as fixes a problem that existed in how animations were automatically built from a sprite sheet.

    Enjoy! And be sure to report any bugs you discover!
     
  31. playemgames

    playemgames

    Joined:
    Apr 30, 2009
    Posts:
    438
    I have been having trouble figuring out the UVAnimation code and how it changes the frames, I want to edit it so I can set up frames arbitrarily on the spritesheet. I have cooked up some edits, but now it doesn't play the animation, it only does it when I have the frames in order. I also edited the way it does timing so it takes a delay value instead of frames per second, this way I have more control over the timing of the animation and how it is played.

    There is another thing I want to try to do, but I am not sure if my solution is better or not. I have another type of sprite animation that uses a texture swap from an array, I tried to see if I can edit the UVAnimation code to do this, but it did not turn out right, probably because of the same problem. I must be misunderstanding how it calls the function to animate exactly because when I try to change the texture in the animation code, it doesn't seem to like it.

    Here is my edited UVAnimation class:

    Code (csharp):
    1. //-----------------------------------------------------------------
    2. // Describes a UV animation
    3. //-----------------------------------------------------------------
    4. //  NOTE: Currently, you should assign at least two frames to an
    5. //  animation, or else you can expect problems!
    6. //-----------------------------------------------------------------
    7. public class UVAnimation
    8. {
    9.     protected SpriteManager m_manager;      // Reference to the sprite manager in which this sprite resides
    10.     protected Sprite m_sprite;      // Reference to the sprite manager in which this sprite resides
    11.     protected Vector2[] frames;                     // Array of UV coordinates (for quads) defining the frames of an animation
    12.    
    13.     // Animation state vars:
    14.     public int curFrame;                        // The current frame
    15.     protected int stepDir = 1;                      // The direction we're currently playing the animation (1=forwards (default), -1=backwards)
    16.     public int numLoops = 0;                        // Number of times we've looped since last animation
    17.  
    18.     public string name;                             // The name of the animation
    19.     public bool loop = true;                        // Does the animation loop or not.
    20.     public int loopCycles = 0;                      // How many times to loop the animation (-1 loop infinitely)
    21.     public bool loopReverse = false;                // Reverse the play direction when the end of the animation is reached? (if true, a loop iteration isn't counted until we return to the beginning)
    22.     public float framerate;                         // The time delayed before the next frame is played
    23.     public float[] frameDelay;                      // Pointer to the array of float times as delay time for frames in the UVAnimation
    24.     public int startAtFrame = 0;                    // The starting frame of this animation.
    25.     public int endAtFrame = -1;                     // The ending frame of this animation.
    26.  
    27.     public UVAnimation()
    28.     {
    29.         sprite = null;
    30.         curFrame = startAtFrame;
    31.     }
    32.  
    33.     public Sprite sprite
    34.     {
    35.         get { return m_sprite; }
    36.         set { m_sprite = value; }
    37.     }
    38.    
    39.     public SpriteManager manager
    40.     {
    41.         get { return m_sprite.manager; }
    42.         set { m_manager = value; }
    43.     }
    44.  
    45.     // Resets all the animation state vars to ready the object
    46.     // for playing anew:
    47.     public void Reset()
    48.     {
    49.         curFrame = startAtFrame;
    50.         stepDir = 1;
    51.         numLoops = 0;
    52.         if (endAtFrame == -1)
    53.         {
    54.             endAtFrame = frames.Length - 1;
    55.         }
    56.     }
    57.  
    58.     // Sets the stepDir to -1 and sets the current frame to the end
    59.     // so that the animation plays in reverse
    60.     public void PlayInReverse()
    61.     {
    62.         stepDir = -1;
    63.         curFrame = endAtFrame;
    64.     }
    65.  
    66.     // Stores the UV of the next frame in 'uv', returns false if
    67.     // we've reached the end of the animation (this will never
    68.     // happen if it is set to loop infinitely)
    69.     public bool GetNextFrame(ref Vector2 uv)
    70.     {
    71.         // See if we can advance to the next frame:
    72.         if((curFrame + stepDir) >= endAtFrame + 1 || (curFrame + stepDir) < startAtFrame)
    73.         {
    74.             // See if we need to loop (if we're reversing, we don't loop until we get back to the beginning):
    75.             if( stepDir>0  loopReverse )
    76.             {
    77.                 stepDir = -1;   // Reverse playback direction
    78.                 curFrame += stepDir;
    79.                 framerate = frameDelay[curFrame];
    80.                 uv = frames[curFrame];
    81.             }else
    82.             {
    83.                 // See if we can loop:
    84.                 if (numLoops + 1 > loopCycles  loopCycles != -1)
    85.                     return false;
    86.                 else
    87.                 {   // Loop the animation:
    88.                     ++numLoops;
    89.  
    90.                     if (loopReverse)
    91.                     {
    92.                         stepDir *= -1;
    93.                         curFrame += stepDir;
    94.                     }
    95.                     else
    96.                         curFrame = startAtFrame;
    97.                     framerate = frameDelay[curFrame];
    98.                     uv = frames[curFrame];
    99.                 }
    100.             }
    101.         }else
    102.         {
    103.             curFrame += stepDir;
    104.             framerate = frameDelay[curFrame];
    105.             uv = frames[curFrame];
    106.         }
    107.  
    108.         return true;
    109.     }
    110.  
    111.     // Constructs an array of UV coordinates based upon the info
    112.     // supplied.
    113.     //
    114.     // start    -   The UV of the lower-left corner of the first
    115.     //              cell
    116.     // cellSize -   width and height, in UV space, of each cell
    117.     // cols     -   Number of columns in the grid
    118.     // rows     -   Number of rows in the grid
    119.     // totalCells-  Total number of cells in the grid (left-to-right,
    120.     //              top-to-bottom ordering is assumed, just like reading
    121.     //              English).
    122.     // fps      -   Framerate (frames per second)
    123.         public Vector2[] BuildUVAnim(Vector2 start, Vector2 cellSize, int cols, int rows, int totalCells, float fps)
    124.     {
    125.         int cellCount = 0;
    126.  
    127.         frames = new Vector2[totalCells];
    128.         frameDelay = new float[totalCells];
    129.         framerate = fps;
    130.  
    131.         frames[0] = start;
    132.         frameDelay[0] = fps;
    133.  
    134.         for(int row=0; row < rows; ++row)
    135.         {
    136.             for(int col=0; col<cols  cellCount < totalCells; ++col)
    137.             {
    138.                 frames[cellCount].x = start.x + cellSize.x * ((float)col);
    139.                 frames[cellCount].y = start.y - cellSize.y * ((float)row);
    140.                 frameDelay[cellCount] = fps;
    141.                 ++cellCount;
    142.             }
    143.         }
    144.  
    145.         return frames;
    146.     }
    147.  
    148.     public Vector2[] BuildUVAnim(int lowerLeftStartX, int lowerLeftEndY, int pixelWidth, int pixelHeight, int cols, int rows, int totalCells, float fps)
    149.     {
    150.         Vector2 start = m_manager.PixelCoordToUVCoord(lowerLeftStartX, lowerLeftEndY);
    151.         Vector2 size = m_manager.PixelSpaceToUVSpace(pixelWidth, pixelHeight);
    152.         Vector2[] frames = BuildUVAnim(start, size, cols, rows, totalCells, fps);
    153.         return frames;
    154.     }
    155.  
    156.     public Vector2[] AddFrame(Vector2 start, Vector2 cellSize, float delay)
    157.     {
    158.         int numFrames;
    159.         Vector2[] tempFrames;
    160.         float[] tempDelay;
    161.         if (frames != null)
    162.         {
    163.             numFrames = frames.Length + 1; // Number of frames the array has with this frame added
    164.             tempFrames = frames;
    165.             frames = new Vector2[numFrames];
    166.             tempFrames.CopyTo(frames, 0);
    167.             Debug.Log(numFrames);
    168.             Debug.Log(frames.Length);
    169.             frames[numFrames-1] = start;
    170.             frames[numFrames-1].x = start.x + cellSize.x;
    171.             frames[numFrames-1].y = start.y - cellSize.y;
    172.         }
    173.         else
    174.         {
    175.             numFrames = 1;
    176.             frames = new Vector2[numFrames];
    177.             Debug.Log(numFrames);
    178.             Debug.Log(frames.Length);
    179.             frames[numFrames-1] = start;
    180.             frames[numFrames-1].x = start.x + cellSize.x;
    181.             frames[numFrames-1].y = start.y - cellSize.y;
    182.         }
    183.  
    184.         if(frameDelay != null)
    185.         {
    186.             tempDelay = frameDelay;
    187.             frameDelay = new float[numFrames];
    188.             Debug.Log(frameDelay.Length);
    189.             tempDelay.CopyTo(frameDelay, 0);
    190.             frameDelay[numFrames-1] = delay;
    191.         }
    192.         else
    193.         {
    194.             frameDelay = new float[numFrames];
    195.             Debug.Log(frameDelay.Length);
    196.             frameDelay[numFrames-1] = delay;
    197.         }
    198.         return frames;
    199.     }
    200.  
    201.     public Vector2[] AddFrame(int lowerLeftStartX, int lowerLeftEndY, int pixelWidth, int pixelHeight, float delay)
    202.     {
    203.         Vector2 start = m_manager.PixelCoordToUVCoord(lowerLeftStartX, lowerLeftEndY);
    204.         Vector2 size = m_manager.PixelSpaceToUVSpace(pixelWidth, pixelHeight);
    205.         Vector2[] frames = AddFrame(start, size, delay);
    206.         return frames;
    207.     }
    208.  
    209.     // Assigns the specified array of UV coordinates to the
    210.     // animation, replacing its current contents
    211.     public void SetAnim(Vector2[] anim)
    212.     {
    213.         frames = anim;
    214.     }
    215.  
    216.     // Assigns the specified array of UV coordinates to the
    217.     // animation, replacing its current contents, adds frame delays per frame
    218.     public void SetAnim(Vector2[] anim, float[] delay)
    219.     {
    220.         frames = anim;
    221.         frameDelay = delay;
    222.     }
    223.  
    224.     // Appends the specified array of UV coordinates to the
    225.     // existing animation
    226.     public void AppendAnim(Vector2[] anim)
    227.     {
    228.         Vector2[] tempFrames = frames;
    229.  
    230.         frames = new Vector2[frames.Length + anim.Length];
    231.         tempFrames.CopyTo(frames, 0);
    232.         anim.CopyTo(frames, tempFrames.Length);
    233.     }
    234.  
    235.     // Appends the specified array of UV coordinates to the
    236.     // existing animation, also adds frame delays
    237.     public void AppendAnim(Vector2[] anim, float[] delay)
    238.     {
    239.         Vector2[] tempFrames = frames;
    240.         int numFrames = frames.Length + anim.Length;
    241.         frames = new Vector2[numFrames];
    242.         tempFrames.CopyTo(frames, 0);
    243.         anim.CopyTo(frames, tempFrames.Length);
    244.        
    245.         float[] tempDelay = frameDelay;
    246.         frameDelay = new float[numFrames];
    247.         tempDelay.CopyTo(frameDelay, 0);
    248.         delay.CopyTo(frameDelay, tempDelay.Length);
    249.     }
    250. }
    251.  
    Any help is appreciated, thanks for the great SpriteManager Brady, it is invaluable.
     
  32. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    I'm not sure about the texture swap thing... I haven't had a chance to look at your code yet, but right off the top of my head, changing textures means changing the texture for the entire SpriteManager, which would seem problematic.

    As for specifying arbitrary UV coordinates, that should be pretty straight-forward. All you need to do is create an array of Vector2, each element of which is a pair of UV coordinates for the lower-left corner of the location of the frame of animation. Then just pass this array to SetAnim(). Or you can also specify them frame-by-frame, and use AppendAnim() each time to build the animation. Be sure to fill in the other necessary vars, such as name, framerate, etc. Then assign the animation to your sprite with AddAnimation(). You should be good to go.
     
  33. playemgames

    playemgames

    Joined:
    Apr 30, 2009
    Posts:
    438
    Yeah I have the texture swap for its own SpriteManager, so maybe the solution I have is ok for now, it uses an Update() to keep it playing but I liked your solution of tying it to the SpriteManager itself but haven't figured out a way to do it nicely with my code. I have some huge sprites that cannot simply do spritesheets so it seems like this is the only way to do it.

    OK just to clarify, so in my BuildUVAnim function it creates an array of the frames, as a Vector2[]. So I then pass it to SetAnim(), or I can use my AddFrame() and pass it to AppendAnim(). Should I just include those inside the function I created for making animations? I suppose you have SetAnim() separate from the BuildUVAnim() so you can create multiple arrays and then put them all together with multiple uses of SetAnim().

    How does it pass the array of frames to be displayed exactly? I was trying to wrap my head on how things are being called but still don't get it. Which function does the actual changing of the UVs is it StepAnim() in the Sprite.cs or GetNextFrame() in the SpriteManager? I see that they are updated in the StepAnim, but not sure how they are passed to the SpriteManager.

    Let me know if I have this straight, if so then I can extend your class a bit and you can use my code if you like for future use. This version should allow for you to define a start frame and end frame in the animation that you can change at will in script. That way you can mix animations without having to make whole new animations if you only need a part of one to make another.

    Thanks for the quick response Brady.
     
  34. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Here's how the UVs get changed:

    StepAnim() calls GetNextFrame() which is passed a reference to the Sprite's m_lowerLeftUV, which is the current UV coordinate of the lower-left corner. Then later in StepAnim(), now that GetNextFrame() has altered the sprite's UV (in-sprite, mind you, not in the actual SpriteManager mesh), the associated SpriteManager's UpdateUV() method is called, which actually copies over the sprite's new UV into the SpriteManager's mesh data. Then, since the flag gets set that the UVs changed, the next LateUpdate() will see this flag and upload the SpriteManager's local copy of the mesh data to the actual in-engine mesh.

    I hope that helps.
     
  35. playemgames

    playemgames

    Joined:
    Apr 30, 2009
    Posts:
    438
    Hi Brady, I have done some modifications that allow me to change the delay times now, but it doesn't seem to play right. The timing is sporadic, is this because it is using a LateUpdate() in the SpriteManager?
     
  36. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Try using LinkedSpriteManager. It could be that you aren't updating the SM frequently enough. Only LSM automatically updates each frame.
     
  37. playemgames

    playemgames

    Joined:
    Apr 30, 2009
    Posts:
    438
    I am using LinkedSpriteManager. So I am not sure if that is the problem.
     
  38. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    That is strange. You can try putting the code in Update(), but I don't that would be the problem. Let me know if that affects it. Does it work right unmodified?
     
  39. playemgames

    playemgames

    Joined:
    Apr 30, 2009
    Posts:
    438
    If it is unmodified it works because there is not a variable delay. I tried it with just one frame with a delay at one sec and it plays sporadically.

    OK I tried it with an Update() as well but it still does the same thing. Maybe it is something with my code:

    Code (csharp):
    1.  
    2.     // Steps to the next frame of sprite animation
    3.     public bool StepAnim(float time)
    4.     {
    5.         if (curAnim == null)
    6.             return false;
    7.  
    8.         timeSinceLastFrame += time;
    9.         timeBetweenAnimFrames = curAnim.frameDelay[curAnim.curFrame];
    10.         framesToAdvance = (int) (timeSinceLastFrame / timeBetweenAnimFrames);
    11.        
    12.         // If there's nothing to do, return:
    13.         if (framesToAdvance < 1)
    14.             return true;
    15.  
    16.         while(framesToAdvance > 0)
    17.         {
    18.             if (curAnim.GetNextFrame(ref m_lowerLeftUV))
    19.             {
    20.                 --framesToAdvance;
    21.                 timeBetweenAnimFrames = curAnim.frameDelay[curAnim.curFrame];
    22.                 Debug.Log(curAnim.curFrame);
    23.             }
    24.             else
    25.             {
    26.                 // We reached the end of our animation
    27.                 if (animCompleteDelegate != null)
    28.                     animCompleteDelegate();
    29.  
    30.                 m_manager.UpdateUV(this);
    31.  
    32.                 return false;
    33.             }
    34.         }
    35.  
    36.         m_manager.UpdateUV(this);
    37.         timeSinceLastFrame = 0;
    38.         timeBetweenAnimFrames = curAnim.frameDelay[curAnim.curFrame];
    39.  
    40.         return true;
    41.     }
    42.  
     
  40. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    When you say variable delay, can you explain what you mean?
     
  41. playemgames

    playemgames

    Joined:
    Apr 30, 2009
    Posts:
    438
    Instead of doing frames per second. I just set the time I want the next frame to be shown at after the previous one.

    You have your current code do 1f/framerate which is equivalent to just setting the time. I can set each frame for a particular time, so I can adjust the animation better rather than making a bigger spritesheet.

    It is easier to think of it as time than frames per second. So that is why I have made it a variable delay. I am more of an animator than a coder so if my work here is sloppy, that is probably why.
     
  42. playemgames

    playemgames

    Joined:
    Apr 30, 2009
    Posts:
    438
    If worse comes to worse I will see if I can use my code that I am using for my sprite animations that use texture flipping, and must be put in an Update(). I just have to adjust it to take an array of UVs that the SpriteManager updates like in your functions. Although I may try to call it in the SpriteManager's LateUpdate() or Update() to see if that works. I am really not sure what else could be causing the problem, I have put up all the code relating to the functions in the past few posts and edited the one to the updated one.
     
  43. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Hmmm, I'm not seeing anything in the code that's jumping out at me, it seems to be correct. Though I suppose there's got to be a problem somewhere...
     
  44. playemgames

    playemgames

    Joined:
    Apr 30, 2009
    Posts:
    438
    OK, I tried it with my sprite animation code updating the uvs that way and it works for the timing now, but not the resizing of the UVs. It seems to assume that the first frame is the size of the entire UVAnimation, is there a way around this? I want to see if I can make variable size frames for the animation. If I can solve this last problem, I'll share my sprite animation code with you and you can see if what I put up previously works better or my own homegrown stuff. Thanks again for the help Brady.
     
  45. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Yes, there should be a way to make that work. You'll have to add a size parameter for each frame, obviously, and then in addition to modifying the m_lowerLeftUV, will also need to modify the size using SetSizeXY/XZ/YZ(), which means you'll also need to store the plane in which the sprite exists inside the Sprite so StepAnim() will know the right one to call.
     
  46. playemgames

    playemgames

    Joined:
    Apr 30, 2009
    Posts:
    438
    Yes, I kind of figured that, I will make another array called frameSize as a Vector2 and store the width and height there. I did not get the StepAnim timing to work properly so I am unsure of where I am going wrong with it, but I will try my own method and show you what I have when I am done.
     
  47. playemgames

    playemgames

    Joined:
    Apr 30, 2009
    Posts:
    438
    Hi Brady thanks for the help, I got it working now but using my animation code. You can use it if you like or modify it just give me cred if you will use the animation portion. I still couldn't get your animation code to work properly with it, but this will work. Let me know if I am missing anything or if there are parts to optimize for use with the SpriteManager. I know it's a little sloppy, but then again I am not a great coder either.

    Here is the code:

    Code (csharp):
    1.  
    2. //-----------------------------------------------------------------
    3. // Describes a UV animation
    4. //-----------------------------------------------------------------
    5. //  NOTE: Currently, you should assign at least two frames to an
    6. //  animation, or else you can expect problems!
    7. //-----------------------------------------------------------------
    8. public class UVAnimation
    9. {
    10.     protected SpriteManager m_manager;              // Reference to the sprite manager in which this sprite resides
    11.     protected Sprite m_sprite;                      // Reference to the sprite manager in which this sprite resides
    12.  
    13.     public float pixelsToWorldUnit;                 // The number of pixels for the sprite for each game world unit
    14.  
    15.     // Animation state vars:
    16.     public Vector2[] frames;                        // Array of UV coordinates (for quads) defining the frames of an animation 
    17.     public int curFrame;                            // The current frame
    18.     public float curFrameDelay;                     // Current frame's delay.
    19.     protected int stepDir = 1;                      // The direction we're currently playing the animation (1=forwards (default), -1=backwards)
    20.     public int numLoops = 0;                        // Number of times we've looped since last animation
    21.     public string name;                             // The name of the animation
    22.     public int loopCycles = 0;                      // How many times to loop the animation (-1 loop infinitely)
    23.     public bool loopReverse = false;                // Reverse the play direction when the end of the animation is reached? (if true, a loop iteration isn't counted until we return to the beginning)
    24.     public float previousTime;                      // The previous time in seconds.
    25.     public float framerate;                         // The time delayed before the next frame is played
    26.     public float[] frameDelay;                      // Pointer to the array of float times as delay time for frames in the UVAnimation
    27.     public Vector2[] frameSize;                     // The width and height of the sprite for each frame.
    28.     public int startAtFrame = 0;                    // The starting frame of this animation.
    29.     public int endAtFrame = -1;                     // The ending frame of this animation.
    30.     public bool loop = true;                        // Does the animation loop or not.
    31.     public bool reverse;                            // Does the animation loop in reverse or not.
    32.     public bool pause = false;
    33.  
    34.     public UVAnimation()
    35.     {
    36.         sprite = null;
    37.         curFrame = startAtFrame;
    38.     }
    39.  
    40.     public Sprite sprite
    41.     {
    42.         get { return m_sprite; }
    43.         set { m_sprite = value; }
    44.     }
    45.    
    46.     public SpriteManager manager
    47.     {
    48.         get { return m_sprite.manager; }
    49.         set { m_manager = value; }
    50.     }
    51.  
    52.     // Resets all the animation state vars to ready the object
    53.     // for playing anew:
    54.     public void Reset()
    55.     {
    56.         curFrame = startAtFrame;
    57.         stepDir = 1;
    58.         numLoops = 0;
    59.         if (endAtFrame == -1)
    60.         {
    61.             endAtFrame = frames.Length - 1;
    62.         }
    63.     }
    64.  
    65.     // Sets the stepDir to -1 and sets the current frame to the end
    66.     // so that the animation plays in reverse
    67.     public void PlayInReverse()
    68.     {
    69.         stepDir = -1;
    70.         curFrame = endAtFrame;
    71.     }
    72.  
    73.     // Stores the UV of the next frame in 'uv', returns false if
    74.     // we've reached the end of the animation (this will never
    75.     // happen if it is set to loop infinitely)
    76.     public bool GetNextFrame(ref Vector2 uv)
    77.     {
    78.         // See if we can advance to the next frame:
    79.         if((curFrame + stepDir) >= endAtFrame + 1 || (curFrame + stepDir) < startAtFrame)
    80.         {
    81.             // See if we need to loop (if we're reversing, we don't loop until we get back to the beginning):
    82.             if( stepDir>0  loopReverse )
    83.             {
    84.                 stepDir = -1;   // Reverse playback direction
    85.                 curFrame += stepDir;
    86.                 framerate = frameDelay[curFrame];
    87.                 uv = frames[curFrame];
    88.             }else
    89.             {
    90.                 // See if we can loop:
    91.                 if (numLoops + 1 > loopCycles  loopCycles != -1)
    92.                     return false;
    93.                 else
    94.                 {   // Loop the animation:
    95.                     ++numLoops;
    96.  
    97.                     if (loopReverse)
    98.                     {
    99.                         stepDir *= -1;
    100.                         curFrame += stepDir;
    101.                     }
    102.                     else
    103.                     {
    104.                         curFrame = startAtFrame;
    105.                     }
    106.                     framerate = frameDelay[curFrame];
    107.                     uv = frames[curFrame];
    108.                 }
    109.             }
    110.         }else
    111.         {
    112.             curFrame += stepDir;
    113.             framerate = frameDelay[curFrame];
    114.             uv = frames[curFrame];
    115.         }
    116.  
    117.         return true;
    118.     }
    119.  
    120.     // Constructs an array of UV coordinates based upon the info
    121.     // supplied.
    122.     //
    123.     // start    -   The UV of the lower-left corner of the first
    124.     //              cell
    125.     // cellSize -   width and height, in UV space, of each cell
    126.     // cols     -   Number of columns in the grid
    127.     // rows     -   Number of rows in the grid
    128.     // totalCells-  Total number of cells in the grid (left-to-right,
    129.     //              top-to-bottom ordering is assumed, just like reading
    130.     //              English).
    131.     // fps      -   Framerate (frames per second)
    132.         public Vector2[] BuildUVAnim(Vector2 start, Vector2 cellSize, int cols, int rows, int totalCells, float fps)
    133.     {
    134.         int cellCount = 0;
    135.         Vector2 size = m_manager.PixelSpaceToUVSpace((int)cellSize.x, (int)cellSize.y);
    136.         frames = new Vector2[totalCells];
    137.         frameDelay = new float[totalCells];
    138.         frameSize = new Vector2[totalCells];
    139.         framerate = fps;
    140.  
    141.         frames[0] = start;
    142.         frameDelay[0] = fps;
    143.         frameSize[0] = cellSize;
    144.  
    145.         for(int row=0; row < rows; ++row)
    146.         {
    147.             for(int col=0; col<cols  cellCount < totalCells; ++col)
    148.             {
    149.                 frames[cellCount].x = start.x + size.x * ((float)col);
    150.                 frames[cellCount].y = start.y - size.y * ((float)row);
    151.                 frameDelay[cellCount] = fps;
    152.                 frameSize[cellCount] = cellSize;
    153.                 ++cellCount;
    154.             }
    155.         }
    156.  
    157.         return frames;
    158.     }
    159.  
    160.     public Vector2[] BuildUVAnim(int lowerLeftStartX, int lowerLeftEndY, int pixelWidth, int pixelHeight, int cols, int rows, int totalCells, float fps)
    161.     {
    162.         Vector2 start = m_manager.PixelCoordToUVCoord(lowerLeftStartX, lowerLeftEndY);
    163.         Vector2 size = new Vector2(pixelWidth, pixelHeight);
    164.         Vector2[] frames = BuildUVAnim(start, size, cols, rows, totalCells, fps);
    165.         return frames;
    166.     }
    167.  
    168. // Add a Frame to the UVAnimation
    169.     public Vector2[] AddFrame(Vector2 start, Vector2 cellSize, float delay)
    170.     {
    171.         int numFrames; // Number of frames the array has with this frame added
    172.         Vector2[] tempFrames;
    173.         float[] tempDelay;
    174.         Vector2[] tempSize;
    175.         Vector2 size = m_manager.PixelSpaceToUVSpace((int)cellSize.x, (int)cellSize.y);
    176.        
    177.         if (frames != null)
    178.         {
    179.             numFrames = frames.Length + 1;
    180.             tempFrames = frames;
    181.             frames = new Vector2[numFrames];
    182.             tempFrames.CopyTo(frames, 0);
    183.             Debug.Log(numFrames);
    184.             Debug.Log(frames.Length);
    185.             frames[numFrames-1] = start;
    186.             frames[numFrames-1].x = start.x + size.x;
    187.             frames[numFrames-1].y = start.y - size.y;
    188.         }
    189.         else
    190.         {
    191.             numFrames = 1;
    192.             frames = new Vector2[numFrames];
    193.             Debug.Log(numFrames);
    194.             Debug.Log(frames.Length);
    195.             frames[numFrames-1] = start;
    196.             frames[numFrames-1].x = start.x + size.x;
    197.             frames[numFrames-1].y = start.y - size.y;
    198.         }
    199.  
    200.         if(frameDelay != null)
    201.         {
    202.             tempDelay = frameDelay;
    203.             frameDelay = new float[numFrames];
    204.             Debug.Log(frameDelay.Length);
    205.             tempDelay.CopyTo(frameDelay, 0);
    206.             frameDelay[numFrames-1] = delay;
    207.         }
    208.         else
    209.         {
    210.             frameDelay = new float[numFrames];
    211.             Debug.Log(frameDelay.Length);
    212.             frameDelay[numFrames-1] = delay;
    213.         }
    214.         if(frameSize != null)
    215.         {
    216.             tempSize = frameSize;
    217.             frameSize = new Vector2[numFrames];
    218.             Debug.Log(frameSize.Length);
    219.             tempSize.CopyTo(frameSize, 0);
    220.             frameSize[numFrames-1] = cellSize;
    221.         }
    222.         else
    223.         {
    224.             frameSize = new Vector2[numFrames];
    225.             Debug.Log(frameSize.Length);
    226.             frameSize[numFrames-1] = cellSize;
    227.         }
    228.         for (int i=0; i<frames.Length; i++)
    229.         {
    230.             Debug.Log("Frame " + i + ": " + frames[i].x + ", " + frames[i].y);
    231.             Debug.Log("Delay " + i + ": " + frameDelay[i]);
    232.             Debug.Log("Frame Size " + i + ": " + frameSize[i].x + ", " + frameSize[i].y);
    233.         }
    234.         return frames;
    235.     }
    236.  
    237.     public Vector2[] AddFrame(int lowerLeftStartX, int lowerLeftEndY, int pixelWidth, int pixelHeight, float delay)
    238.     {
    239.         Vector2 start = m_manager.PixelCoordToUVCoord(lowerLeftStartX, lowerLeftEndY);
    240.         Vector2 size = new Vector2(pixelWidth, pixelHeight);
    241.         Vector2[] frames = AddFrame(start, size, delay);
    242.         return frames;
    243.     }
    244.  
    245.     // Assigns the specified array of UV coordinates to the
    246.     // animation, replacing its current contents
    247.     public void SetAnim(Vector2[] anim)
    248.     {
    249.         frames = anim;
    250.     }
    251.  
    252.     // Assigns the specified array of UV coordinates to the
    253.     // animation, replacing its current contents, adds frame delays per frame
    254.     public void SetAnim(Vector2[] anim, float[] delay, Vector2[] size)
    255.     {
    256.         frames = anim;
    257.         frameDelay = delay;
    258.         frameSize = size;
    259.     }
    260.  
    261.     // Appends the specified array of UV coordinates to the
    262.     // existing animation
    263.     public void AppendAnim(Vector2[] anim)
    264.     {
    265.         Vector2[] tempFrames = frames;
    266.  
    267.         frames = new Vector2[frames.Length + anim.Length];
    268.         tempFrames.CopyTo(frames, 0);
    269.         anim.CopyTo(frames, tempFrames.Length);
    270.     }
    271.  
    272.     // Appends the specified array of UV coordinates to the
    273.     // existing animation, also adds frame delays
    274.     public void AppendAnim(Vector2[] anim, float[] delay, Vector2[] size)
    275.     {
    276.         Vector2[] tempFrames = frames;
    277.         int numFrames = frames.Length + anim.Length;
    278.         frames = new Vector2[numFrames];
    279.         tempFrames.CopyTo(frames, 0);
    280.         anim.CopyTo(frames, tempFrames.Length);
    281.        
    282.         float[] tempDelay = frameDelay;
    283.         frameDelay = new float[numFrames];
    284.         tempDelay.CopyTo(frameDelay, 0);
    285.         delay.CopyTo(frameDelay, tempDelay.Length);
    286.        
    287.         Vector2[] tempSize = frameSize;
    288.         frameSize = new Vector2[numFrames];
    289.         tempSize.CopyTo(frameSize, 0);
    290.         size.CopyTo(frameSize, tempSize.Length);
    291.     }
    292.  
    293. // Play an animation in an Update(), will only work if placed in an Update(), you can set the frame you want the animation to start at, end at, and if the animation loops or does a reverse loop meaning it plays backwards at the end of the animation.
    294.     public void Play(int startFrame, int endFrame, bool looping, bool reverseLoop)
    295.     {
    296.         startAtFrame = startFrame;
    297.         endAtFrame = endFrame;
    298.         loop = looping;
    299.         loopReverse = reverseLoop;
    300.         //Debug.Log(startAtFrame);
    301.         //Debug.Log(endAtFrame);
    302.         //Debug.Log(curFrameDelay);
    303.         Play();
    304.     }
    305.  
    306.  
    307.     public void Play(bool looping, bool reverseLoop)
    308.     {
    309.         int endFrame = frames.Length;
    310.         startAtFrame = 0;
    311.         endAtFrame = endFrame - 1;
    312.         loop = looping;
    313.         loopReverse = reverseLoop;
    314.         //Debug.Log(endAtFrame);
    315.         //Debug.Log(curFrameDelay);
    316.         //Debug.Log(m_sprite);
    317.         Play();
    318.     }
    319.  
    320.     public void Play()
    321.     {
    322.         if(endAtFrame == -1)
    323.         {
    324.             endAtFrame = frames.Length - 1;
    325.         }
    326.         if (pause == true)
    327.         {
    328.             return;
    329.         }
    330.         if (loopReverse == false)
    331.         {
    332.             reverse = false;
    333.         }
    334.         if(Time.time - previousTime >= curFrameDelay)
    335.         {
    336.             m_sprite.lowerLeftUV = frames[curFrame];
    337.             Vector2 newUVs = m_manager.PixelSpaceToUVSpace((int)frameSize[curFrame].x, (int)frameSize[curFrame].y);
    338.             m_sprite.uvDimensions = newUVs;
    339.             float width = frameSize[curFrame].x/pixelsToWorldUnit;
    340.             // Debug.Log(width);
    341.             float height = frameSize[curFrame].y/pixelsToWorldUnit;
    342.             // Debug.Log(height);
    343.             m_manager.UpdateUV(m_sprite);
    344.             m_sprite.SetSizeXY(width, height);
    345.            
    346.             if(loop == false  reverse == false  curFrame < endAtFrame)
    347.             {
    348.                 curFrame++;
    349.                 curFrameDelay = (float)frameDelay[curFrame];
    350.             }
    351.             else if(loop == false  loopReverse == false  curFrame >= endAtFrame  Time.time - previousTime >= (float)frameDelay[endAtFrame])
    352.             {
    353.                 curFrame = endAtFrame;
    354.                 curFrameDelay = (float)frameDelay[curFrame];
    355.             }
    356.             else if(loop == false  loopReverse == true  curFrame >= endAtFrame  Time.time - previousTime >= (float)frameDelay[endAtFrame])
    357.             {
    358.                 reverse = true;
    359.                 curFrame--;
    360.                 curFrameDelay = (float)frameDelay[curFrame];
    361.             }
    362.             else if (loop == false  reverse == true  curFrame <= startAtFrame  Time.time - previousTime >= (float)frameDelay[startAtFrame])
    363.             {
    364.                 curFrame = startAtFrame;
    365.                 curFrameDelay = (float)frameDelay[curFrame];
    366.             }
    367.             else if(loop == false  reverse == true  curFrame > startAtFrame)
    368.             {
    369.                 curFrame--;
    370.                 curFrameDelay = (float)frameDelay[curFrame];
    371.             }
    372.             else
    373.             {
    374.                 if(curFrame >= endAtFrame  loopReverse == false  Time.time - previousTime >= (float)frameDelay[endAtFrame]  numLoops < loopCycles || curFrame >= endAtFrame  loopReverse == false  Time.time - previousTime >= (float)frameDelay[endAtFrame]  loopCycles == -1)
    375.                 {
    376.                     curFrame = startAtFrame;
    377.                     curFrameDelay = (float)frameDelay[curFrame];
    378.                     numLoops++;
    379.                 }
    380.                 else if(curFrame >= endAtFrame  loopReverse == false  Time.time - previousTime >= (float)frameDelay[endAtFrame]  numLoops >= loopCycles)
    381.                 {
    382.                     loop = false;
    383.                     curFrame = endAtFrame;
    384.                     curFrameDelay = (float)frameDelay[curFrame];
    385.                     // Debug.Log("End of Loops");
    386.                 }
    387.                 else if (curFrame < endAtFrame  loopReverse == false)
    388.                 {
    389.                     curFrame++;
    390.                     curFrameDelay = (float)frameDelay[curFrame];
    391.                 }
    392.                 else if(curFrame >= endAtFrame  loopReverse == true  Time.time - previousTime >= (float)frameDelay[endAtFrame])
    393.                 {
    394.                     reverse = true;
    395.                     curFrame--;
    396.                     curFrameDelay = (float)frameDelay[curFrame];
    397.                 }
    398.                 else if(curFrame <= startAtFrame  reverse == true  Time.time - previousTime >= (float)frameDelay[startAtFrame]  numLoops < loopCycles || curFrame <= startAtFrame  reverse == true  Time.time - previousTime >= (float)frameDelay[startAtFrame]  loopCycles == -1)
    399.                 {
    400.                     reverse = false;
    401.                     curFrame++;
    402.                     curFrameDelay = (float)frameDelay[curFrame];
    403.                     numLoops++;
    404.                 }
    405.                 else if(curFrame <= startAtFrame  reverse == true  Time.time - previousTime >= (float)frameDelay[startAtFrame]  numLoops >= loopCycles)
    406.                 {
    407.                     reverse = false;
    408.                     loop = false;
    409.                     curFrame = startAtFrame;
    410.                     curFrameDelay = (float)frameDelay[curFrame];
    411.                     // Debug.Log("End of Reverse Loops");
    412.                 }
    413.                 else if (curFrame < endAtFrame  loopReverse == true  reverse == false)
    414.                 {
    415.                     curFrame++;
    416.                     curFrameDelay = (float)frameDelay[curFrame];
    417.                 }
    418.                 else if (curFrame < endAtFrame  reverse == true)
    419.                 {
    420.                     curFrame--;
    421.                     curFrameDelay = (float)frameDelay[curFrame];
    422.                     // Debug.Log(curFrame);
    423.                 }
    424.                 else
    425.                 {
    426.                     curFrame++;
    427.                     curFrameDelay = (float)frameDelay[curFrame];
    428.                     // Debug.Log(curFrame);
    429.                 }
    430.             }
    431.             previousTime = Time.time;
    432.         }
    433.     }
    434. }
    435.  
     

    Attached Files:

  48. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    So, is there a video of this working? Dunno if anyone posted one before, but I just want to see this in motion to decide what route a new project should go in.
     
  49. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    If you are referring to SpriteManager in general, there is a demo project attached to the first post.
     
  50. Razieln64

    Razieln64

    Joined:
    May 3, 2008
    Posts:
    129
    Hi,

    I'm trying to modify the spriteManager to use multiple materials in order to solve a layer problem. I've tried with multiple managers, but this doesn't work because the same manager needs to have a sprite in front and in the back of another SM (like a sandwich). I'm trying to use the materials[] attribute in the Renderer class. My problem with modifying the code is to find the right function/method in the SM where to put the line :

    meshRenderer.material = meshRenderer.materials[indexOfMaterialUsedForThisSprite];

    It must appear right before the specific sprite is rendered.
    Technically if I could modify the implicit drawing function of the renderer and identify the sprite being renderer, I could change the renderer's texture before the sprite is rendered.

    I'm trying to save some space by not putting the same sprite in different textures. Is this modification worth trying or should I just duplicate some sprites and use multiple SMs? Thanks