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

SM2 - 2D made easy and efficient!

Discussion in 'iOS and tvOS' started by Brady, Nov 4, 2009.

  1. Komar Games

    Komar Games

    Joined:
    Oct 18, 2009
    Posts:
    63
    Hi Brady, I have bought SM2 yesterday, and want to ask - how can I check if sprite was touch by finger(Unity Iphone version)

    P.S. I am new to Unity
     
  2. Lokken

    Lokken

    Joined:
    Apr 23, 2009
    Posts:
    436
    If you need to assign it in code and already have a reference to the gameobject:

    Code (csharp):
    1.  
    2. public PackedSprite mySprite;
    3. mySprite = (PackedSprite)myGameObject.GetComponent("PackedSprite")
    4.  
    Thats how I do it anyways.
     
  3. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    First, you'll need to add a collider component to the sprite object (click Component->Physics->Box collider, or whatever shape collider works best for your situation). Then, in the script that will handle all your input detection, make sure you have references to all the GameObjects you'll be using for input. Then do the following (this is the easiest example that supports single touches at a time, but works on both iPhone and Unity desktop):

    Code (csharp):
    1.  
    2. function Update()
    3. {
    4.    // NOTE: "hit" is of type RaycastHit
    5.    // and should be declared earlier
    6.    if (Input.GetMouseButton(0))
    7.    {
    8.       if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), hit, Mathf.Infinity))
    9.       {
    10.          if(hit.gameObject == sprite1)
    11.             // Do something
    12.          else if(hit.gameObject == sprite2)
    13.             // Do something else...
    14.       }
    15.    }
    16. }
    17.  
    Just be sure you have previously established references for "sprite1", "sprite2", etc. The easiest way to do this is to declare these as public references GameObjects, then just drag the various objects onto their corresponding "slots" in the inspector to establish the references.
     
  4. Komar Games

    Komar Games

    Joined:
    Oct 18, 2009
    Posts:
    63
    Thanks! After small code editing it works great!
     
  5. aerende

    aerende

    Joined:
    Apr 27, 2009
    Posts:
    316
    Hi Brady,
    When I'm trying to make a Texture atlas using SM2's Sprite Timeline I get the following error:

    • IndexOutOfRangeException: Array index is out of range.
      BuildAtlases.OnWizardCreate () (at Assets/Editor/BuildAtlases.cs:117)


    I'm only using 2 frames each 135x230 pixels, so I don't think I'm going over the limit of 1024 x 1024.

    Any idea what is wrong? I can send you the frames I am using.
     
  6. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    That sounds like either an animation doesn't have any textures assigned or something along those lines. Is there any kind of a sample you could send me directly via e-mail? It would be best if I could see how the sprite animations are set up so I can try to reproduce the problem.
     
  7. Komar Games

    Komar Games

    Joined:
    Oct 18, 2009
    Posts:
    63
    Another strange problem, when I am trying to declare a Sprite object, the debug log say: " The name 'Sprite' does not denote a valid type" or " The name 'PackedSprite' does not denote a valid type".

    Example:
    Code (csharp):
    1. var gameSprite: Sprite;
    2. var gamePackedSprite: PackedSprite;
     
  8. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    This is because you are referring to C# code from JavaScript. Unity is a bit quirky about this, so when calling C# code from JS, you need to make sure the C# code gets compiled before any JS so that it is "visible" to JS. The way you can do this is to create a folder in the root of your project called "Plugins" and drag the "Sprite Scripts" folder into this. This forces anything in "Plugins" to get compiled first, making it visible to your JS scripts elsewhere which get compiled later.

    Future versions of SM2 will already have the "Sprite Scripts" folder under "Plugins" for this reason.
     
  9. Komar Games

    Komar Games

    Joined:
    Oct 18, 2009
    Posts:
    63
    Thanks Brady, it works!
     
  10. Disaster

    Disaster

    Joined:
    Oct 31, 2009
    Posts:
    43
    I was wondering if anyone had any tips for improving the quality of the sprite. I seem to be getting a lot of tearing and the animations seem to distort a fair bit (the colours seem to S***, which is odd?)

    I have set my shader to Transparent / Vertex Coloured and each png is setup like so:

    Ansio: 1
    Filtering: Point Mode
    Wrap: Repeat

    Texture format: ARGB 32BIT

    Generate Mip / Bump: off

    Thanks!
     
  11. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    The animations should not distort if you have auto resize turned on. And for sure the colors shouldn't shift, but I do have an idea what might be going on. If using the vertex colored shader, check the shader color. If it is set to full-white, you'll want to use 50% white on your sprites. If you want to use full-white on your sprites, set the shader color to 50% white. Otherwise, if both are full-white, it will look "over bright"/over-exposed. This can be useful when you want a "highlight" effect, but normally, you want one of them set to 50%.
     
  12. Komar Games

    Komar Games

    Joined:
    Oct 18, 2009
    Posts:
    63
    Hi Brady, It's me again :), a have another problem - I have made a Packed Sprite object with 3 different animations. In code I am switching them like this -
    Code (csharp):
    1. mySprite.PlayAnim(My animation index);
    . But it shows only first frame of each animation. Whats wrong?
     
  13. Disaster

    Disaster

    Joined:
    Oct 31, 2009
    Posts:
    43
    Don't mean to patronize, but did you remember to rebuild your atlas? That got me a couple of times...
     
  14. Komar Games

    Komar Games

    Joined:
    Oct 18, 2009
    Posts:
    63
    Yes, I rebuild my atlas, it didnt help
     
  15. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    It is likely one of two issues:
    1) Make sure you have a framerate set in the animation.
    2) Remember that every time you call PlayAnim(), it starts the animation from the beginning. So only call PlayAnim() when your object changes states, or you otherwise intentionally want the animation to start over from the beginning. If you do something like:

    if(playerIsHoldingTheRunButton)
    mySprite.PlayAnim("run");

    Then the run animation will never get past its first frame so long as the player is holding down the button. Instead, use logic/flags to only trigger an animation when the object's state changes.
     
  16. Komar Games

    Komar Games

    Joined:
    Oct 18, 2009
    Posts:
    63
    Yes, problem was like you describe in second paragraph. Is there any function to check if animation is still playing? If I use bakedSprite?
     
  17. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    You could always use bakedSprite.IsAnimating(). But that will only tell you if it is currently animating. What you probably want to do is save a reference to your animations ahead of time like so:

    Code (csharp):
    1.  
    2. myAnim = bakedSprite.GetAnim("anim I want");
    3.  
    Then when you want to see if you need to change animation states, check against this like so:

    Code (csharp):
    1.  
    2. // Only play "myAnim" if it isn't already the current
    3. // animation:
    4. if( myAnim != bakedSprite.GetCurAnim() )
    5.    bakedSprite.PlayAnim(myAnim);
    6.  
     
  18. aerende

    aerende

    Joined:
    Apr 27, 2009
    Posts:
    316
    I'm trying to rotate a disc (Sprite) with a finger touch on the iPhone. I've instantiated the disc from a Prefab as shown below.

    Code (csharp):
    1. Disc_GO         = (Instantiate(Disc_PF, InitialPos, InitialRot));
    The problem I am having is comparing the finger touch position to the position of the disc. I have used the collider approach to know if a button is touched, but here I want to know where the touch is relative to the center of the button.

    1) So the problem is that the touch position is in Screen coordinates and the instantiated disc is at world coordinates for InitialPos, is that correct?

    I've tried translating the touch to world coordinates using

    Code (csharp):
    1. var worldTouch : Vector3 = Camera.main.ScreenToViewportPoint (touch.position);
    but worldTouch didn't change with touch position.

    2) I've also tried translating InitialPos to screen coordinates, but I end up getting negative numbers. Do you know what I am doing wrong in this case?

    3) Any suggestions on how to compare the touch.position to the center of a Sprite?
     
  19. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    If you're doing a ray cast, the RaycastHit class includes a "point" member which is the world space point of the hit. You should be able to easily compare this to the transform.position of the sprite's GameObject.
     
  20. sparkyman

    sparkyman

    Joined:
    May 3, 2009
    Posts:
    21
    Hey Brady

    You will have answered this before but I just can't seem to find the answer.

    I have created my atlas in my scene and all is working well , I am now creating a new scene but want to use some of the assets in the original atlas. I have added the Sprite script to an empty game object got the and got the sprite to appear. My question is I have lots of sprites from the atlas I want to use and wondered what the quickest way to get the X,Y and size of the sprite actually is? Is there some wonderful utility that can help here?

    Thanks
     
  21. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Are you using the Sprite or PackedSprite class? If you're using the Sprite class, I take it your question is one of two things:

    1) How to get the size and location of a sprite on a sprite atlas.
    A: I use a paint program. Most paint programs either give you the coordinates under your cursor, or have a selection tool that will give you the coordinates and dimensions of a selected box.

    2) How to reproduce a sprite that has been set up in a different scene without having to re-enter the position and size info.
    A: Save your sprite to a prefab and then you can just drag that prefab onto any other scene to reproduce it quickly, easily, and as many times as you need.

    If you're using a PackedSprite, I take it your question is one of the following:

    1) How to use a specific sprite frame from an atlas generated by a sprite in a different scene.
    A: Just drag the same frame(s) onto the new sprite you want to use. If the other PackedSprite is present in the scene and share the same material, they'll "share" the frames they have in common, and these frames will only be placed on the atlas once. In the next release (coming very soon) it will scan the project folder for prefabs as well, so there will be no need to have a "representative" of all your sprite types present in the current scene when you build your atlases.

    2) How to easily reproduce a sprite from a different scene.
    A: See #2 above.

    I hope that helps. If I've missed your question entirely, let me know and I'll give it another shot. :)
     
  22. aerende

    aerende

    Joined:
    Apr 27, 2009
    Posts:
    316
    How can I make a Sprite slowly fade away? I know I can make it disappear by disabling it's GameObject, but can someone tell me how to make the Sprite slowly fade away over a few seconds?
     
  23. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    You just modify its color (make sure you're using a vertex colored shader, like the one included with SM2). This can be done using the SetColor() method. Just alter the alpha component that you pass SetColor() over time. In fact, you'll see a sample of transparent fading in the demo script that comes with SM2. Look at the code in Update().
     
  24. aerende

    aerende

    Joined:
    Apr 27, 2009
    Posts:
    316
    I'd like to instantiate a lot of Sprites in Start() and switch which portions of the texture are shown later in time. Is it possible to do this programmatically with Sprite.lowerLeftPixel and Sprite.pixelDimensions? I tried the following which didn't work where Vector2(11.0, 210.0); and Vector2(8.0,13.0) are the new values:

    Code (csharp):
    1.  
    2. var A_GO          : GameObject;
    3. var A_S            : Sprite;
    4. var S_PF           : GameObject;
    5. var InitialRot    : Quaternion = Quaternion.identity;
    6. var InitialPos    : Vector3 = Vector3(2, 4, 6);
    7.  
    8. function Start(){
    9.  
    10.     A_GO = (Instantiate(S_PF, InitialPos, InitialRot));
    11.     A_S  = A_GO.GetComponent("Sprite");
    12.     A_S.lowerLeftPixel  = Vector2(11.0, 210.0);
    13.     A_S.pixelDimensions = Vector2(8.0,13.0);
    14.  
    15. }
     
  25. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Yes, you can do that. But you'll probably need to call CalcUVs() and then UpdateUVs() so that the UVs are converted from pixel to UV values, and then updated to the mesh, respectively.

    But it would probably be easier to just store these as animations/frames and then just set them at runtime. For example, have a single-frame animation set up (set to "Do Nothing" on end), then just call PlayAnim() with that animation as the argument. This basically accomplishes the same thing without having to hard-code the pixel offsets, etc, in your code, and also saves you the additional function calls.
     
  26. hxx2010

    hxx2010

    Joined:
    Aug 31, 2009
    Posts:
    155
    When save scene,Always prompt the following

    Cleaning up leaked objects in scene since no game object, component or manager is referencing them
    Mesh has been leaked 36 times.
     
  27. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    This is mentioned in the docs I believe. You can safely ignore this message as it only occurs in edit mode (not when the game runs, and not in an actual build). I'm also assured by the Unity folks that even in edit-time, this message should be disregarded based on what is generating it.
     
  28. Lokken

    Lokken

    Joined:
    Apr 23, 2009
    Posts:
    436
    Well I cant seem to find the new release thread that was on these forums so I am bumping this one.

    I have upgraded to the new version of SM2 and have everything set up just as before in my project but now the console is completely full of

    Code (csharp):
    1. !local.IsValid()
    2. UnityEngine.Mesh:RecalculateBounds()
    solution?
     
  29. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    I suspect that it could be related to the trimming feature if you have a frame in one of your sprites that is 100% transparent. I've got an internal version that will address this that will be coming out shortly. In the meantime, if this is the case, you could set one pixel of the texture to 1% transparency to solve it.

    Let me know if that's not the case, however.
     
  30. Lokken

    Lokken

    Joined:
    Apr 23, 2009
    Posts:
    436
    Bingo, that did it.

    What is the ETA on the fix?

    P.S. out of any software package Ive bought, with the possible exception of Unity, SM2 has had the best customer support I have ever experienced.
     
  31. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Thanks, Lokken!

    Actually, I just now uploaded a beta version of 1.0.1 to the group if you want to try it out. It should address your issue. Also features MUCH faster atlas building and a couple of other minor things.
     
  32. Lokken

    Lokken

    Joined:
    Apr 23, 2009
    Posts:
    436
    Actually I have another question.

    I have a game object with a simple animation.

    I instantiate it a bunch of times, but unlike the source of the instantiation, i want its default animation to loop. I manually go into each pre-fab and set its on_anim_end to play_default_anim.

    All of the clones just sit at the static texture and do not animate. Is there something special you have to do to clone objects?

    In the inspector during runtime they all show play_default_anim as its action to take when an animation ends. I have also set it to play on start too.

    Thanks!

    L

    Just saw your post. I will try that out tomorrow. Its late here and I have to go to bed unfortunately :(

    Thanks again Brady
     
  33. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Try making sure the default animation's loop cycles is set to -1 (loop infinitely), or else the number of times you want it to repeat.

    But from your description, it sounds like even the default animations aren't playing even though they are set to play on start. I'm not sure what could cause that. Maybe also check that the frame rates are set to non-zero? That's the only other thing I can think of that would cause them not to animate.
     
  34. Lokken

    Lokken

    Joined:
    Apr 23, 2009
    Posts:
    436
    If I set it to Play On Start it will play the animation once. It is like its ignoring the textureAnim information, but not the PackedSprite settings.

    I even tried setting the original to just loop over and over. The clones don't do it but the original does.

    I will export a package later after work that explains where in the code the issue is happening and forward it on unless someone figures out something else to try from my description.

    Thanks!
     
  35. aerende

    aerende

    Joined:
    Apr 27, 2009
    Posts:
    316
    I'm trying to implement a health bar with SM2, and I'm using Pixel Perfect to implement the health bar as a Sprite. Since I'm using Pixel Perfect, I don't seem to be able to scale the healthbar using SpriteBase.SetSize(), but I am able to scale the healthbar using localScale:

    Code (csharp):
    1. HB_GO.transform.localScale    = new Vector3(0.7,1.0,1.0);
    I have two questions:

    1) How can I make the healthbarHolder show up behind the healthbar? I've tried setting the healthbarHolder farther away from the camera, but that doesn't always work as the healthbar is scaled, if the spacing between the healthbarHolder and the healthbar is small. Is it possible to put each healthbar sprite on different layers where one layer is shown by the camera before the other layer?

    2) After scaling the healthbar, how can I realign it to the left hand side? I've tried using the healthbar's GameObject.transform.position but that seems to be a function of where the Sprite is located in space with respect to the camera. I.E. if I know the width in pixels of the healthbar and try to use the healthBarWidth to scale the X position of the healthbar, healthBarWidth will be too large as the healthbar is moved away from the camera.
     
  36. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Lokken:
    Thanks, if you could send a test project that'd be great.

    aerende:
    1) There probably isn't quite enough distance between the two given the amount of Z-precision available give your near/far clipping planes. You may try reducing your far clipping plane on your camera, and if you're using a dedicated UI camera, you can get away with an insanely close far plane. Also, as you suggested, you could put them on different layers and use a different camera to render them in order. But I think the easiest fix to try first would just be to reduce your far clipping plane. Most games I've seen leave that at the default and actually don't need the depth it provides, which means there's a lot more Z-precision available by reducing it.

    2) If your game's resolution doesn't change, you could disable pixel perfect once its been sized properly for the game viewport, and then you could use SetSize() without any problem. If you don't want to go that route, then if you use the transform scale, you should be able to use the x position * 0.5. I'm not clear on your description of how the width will be too large as it moves away from the camera though. Are you using an orthographic projection?

    One issue is if your health bar is, say, a gradient, and as it shrinks/grows, you want it to reveal less/more of that gradient, currently you'll have to manually adjust the UVs. But I've got a feature in the works that will make not only this problem go away, but also the sizing problem you're having. It'll basically truncate the sprite and won't be interfered with by pixel perfect. I'll let everyone know when this release is ready.

    Let me know if you need any more help with this. Thanks!
     
  37. blastone

    blastone

    Joined:
    Apr 7, 2009
    Posts:
    168
    I currently use SpriteManager1 for a number of moving sprites across a reasonably sized landscape, along with a custom spriteManager based particle effects.

    My questions are:

    - Is there a performance benefit to using SpriteManager 2 (and what!)
    - Does spriteManager 2 hide sprites that are invisible to the camera or is this an unnecessary optimisation

    Cheers
    Mark
     
  38. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    1) Yes, there is on iPhone. The automatic batching is much faster than how SM1 combines sprites into a single mesh and transforms them. It's hard to quantify exactly how much faster as there are lots of variables that can affect it, but in one test, we had a UI that was using SM1, and on an iPhone 3G it was getting about 43fps with SM1, and 59fps (which is right at the 60fps iPhone limit) with SM2.

    While that's a pretty significant performance increase, SM2's real charm is how incredibly easy the workflow is compared to SM1, and especially compared to having to roll your own sprite solution.

    2) Since SM2 uses Unity iPhone's batching instead of combining into a single mesh, Unity automatically frustum culls things that are outside the camera's frustum.
     
  39. r618

    r618

    Joined:
    Jan 19, 2009
    Posts:
    1,303
    Brady,
    would it be possible to write up a rough annotation somewhere about what is current beta about ? :) ( maybe on the dl page.. ? sorry if there's info about this somewhere .. )

    btw thanks for sm2; I recently gave it a try and i really like it very much. :)
     
  40. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    The group doesn't really have a way that I can see to annotate individual download files, so I'll put something in the announcements.
     
  41. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Actually, I've created a "Latest Beta Info" page under "Pages". That way nobody will get their e-mail spammed with constant announcement e-mails.
     
  42. r618

    r618

    Joined:
    Jan 19, 2009
    Posts:
    1,303
    perfect, thank you very much
     
  43. Lokken

    Lokken

    Joined:
    Apr 23, 2009
    Posts:
    436
    I have forwarded the email.

    As an update, the beta version you posted has corrected the deluge of runtime errors.

    Thanks again for the quick feedback and solutions!

    L
     
  44. aerende

    aerende

    Joined:
    Apr 27, 2009
    Posts:
    316
    I've created a bunch of buttons and UI display Sprites on the screen. When I move my character, the camera follows the character, but the buttons and Sprites stay where they are. I.E. the buttons and UI display Sprites move off screen as the character moves. How can I make the buttons and UI display Sprites stay in their position on the screen relative to the camera?
     
  45. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Lokken: I haven't received the e-mail yet, just so you know. You may want to try again.

    I would suggest making the UI sprites children of the camera. Or alternatively, you can put them in a different layer and use a separate camera to render them alone.
     
  46. Lokken

    Lokken

    Joined:
    Apr 23, 2009
    Posts:
    436
    Strange. I sent it to the email address that had responded to my last help request.

    Though now that I look at it the original address I sent it to was different so I sent it there this time. You should see it now.

    Thanks!

    L
     
  47. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Got it, and just replied. Thanks!
     
  48. aerende

    aerende

    Joined:
    Apr 27, 2009
    Posts:
    316
    Is there a way to make the UI Sprites children of the camera without attaching them to the camera? I have the UI Sprites as PreFabs that are attached to characters that move since the UI Sprite controls operate these characters.

    It sounds like putting the PreFabs on a separate layer that is pointed at by a separate camera might be the easier approach.
     
  49. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    Yes, it might be for your case. I can't quite picture what you're describing, but if your UI elements need to move in a way that is entirely independent from the camera, then yes, that'd probably be easier. But if you just want them to follow the characters, you might think of a way to attach them to the character GameObjects.

    Otherwise, if you always want a UI element to remain in the same exact place on-screen no matter how the camera moves, the easiest thing is to make it a child of the camera.
     
  50. Disaster

    Disaster

    Joined:
    Oct 31, 2009
    Posts:
    43
    Brady,

    I noticed Unity 3.0 now has 2D sprite support... is this Sprite Manager or something they have cooked up? I hope it's Sprite Manager, because it's awesome.