Author Topic: Update UI2DSprite.sprite2D in place  (Read 8808 times)

favoyang

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 14
    • View Profile
Update UI2DSprite.sprite2D in place
« on: July 08, 2014, 08:15:19 AM »
Hi, I want to change UI2DSprite.sprite after "unity internal animation update", so I can sync my UI2DSprite with Unity SpriteRenderer.sprite. According to "Execution Order of Event Functions" (http://docs.unity3d.com/Manual/ExecutionOrder.html) I need put the logic in LateUpdate callback. however if I change UI2DSprite.sprite2D directly, it will be removed from screen 1 frame whenever the sprite changed. If I change UI2DSprite.nextSprite, it will delay 1 frame. Any idea for this?

My intention to sync UI2DSprite with SpriteRenderer is that, I want to animate sprite with Unity Animation Panel (Dope Sheet) and manage display using NGUI. Some complex animation requires coordinate with other objects carefully, so I prefer this way.

Here's my code,

  1. using UnityEngine;
  2.  
  3. /// <summary>
  4. /// Small script that sync SpriteRenderer.sprite to UI2DSprite.nextSprite.
  5. /// </summary>
  6.  
  7. [RequireComponent(typeof(UI2DSprite))]
  8. [RequireComponent(typeof(SpriteRenderer))]
  9. [ExecuteInEditMode]
  10. public class UI2DSpriteAnimationHelper : MonoBehaviour
  11. {
  12.         UnityEngine.SpriteRenderer mUnitySpriteRdr;
  13.         UI2DSprite mNguiSprite;
  14.  
  15.         void Awake()
  16.         {
  17.                 mUnitySpriteRdr = GetComponent<UnityEngine.SpriteRenderer>();
  18.                 mNguiSprite = GetComponent<UI2DSprite>();
  19.                 mUnitySpriteRdr.enabled = false;
  20.         }
  21.  
  22. #if false
  23.         void Update()
  24.         {
  25.                 if (Application.isEditor && !Application.isPlaying)
  26.                         LateUpdate();
  27.         }
  28. #endif
  29.        
  30.         void LateUpdate()
  31.         {
  32.                 if (mNguiSprite.sprite2D.name != mUnitySpriteRdr.sprite.name) {
  33.                         mNguiSprite.sprite2D = mUnitySpriteRdr.sprite;
  34.                         // mNguiSprite.nextSprite = mUnitySpriteRdr.sprite;
  35.                 }
  36.         }
  37. }
  38.  

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Update UI2DSprite.sprite2D in place
« Reply #1 on: July 08, 2014, 12:29:16 PM »
You need to set your script's execution order to run before UIPanel, as that's when the draw calls get re-created. This way your script's LateUpdate will execute prior to UIPanel's.

favoyang

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 14
    • View Profile
Re: Update UI2DSprite.sprite2D in place
« Reply #2 on: July 08, 2014, 09:57:13 PM »
I have set my script execution order before UIPanel, problems remain.

- If I assigned UI2DSprite.sprite2D in script, no matter in LateUpdate or Update, the sprite will be removed from screen in current frame => make the sprite looks "flash".
- Change UI2DSprite.nextSprite works fine, (I guess for the current way NGUI works, UI2DSprite.sprite2D has to be updated in UI2DSprite.OnUpdate like the way nextSprite be handled). However that will intro 1 frame delay in animation.


favoyang

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 14
    • View Profile
Re: Update UI2DSprite.sprite2D in place
« Reply #3 on: July 08, 2014, 10:10:43 PM »
Attached an example project so you can debug. The left sprites are rendered by Unity Sprite, the right ones are rendered by UI2DSprite. All animated by Unity Animation Panel. Try play to see the sprites "flash" and toggle the nextSprite line in UI2DSpriteAnimationHelper.cs to see the 1 frame delay (hat should be animated to perfect follow the hero sprite animation)

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Update UI2DSprite.sprite2D in place
« Reply #4 on: July 09, 2014, 04:39:48 PM »
Thanks, it helped me figure out the issue. Replace UI2DSprite.sprite2D with this:
  1.         public UnityEngine.Sprite sprite2D
  2.         {
  3.                 get
  4.                 {
  5.                         return mSprite;
  6.                 }
  7.                 set
  8.                 {
  9.                         if (mSprite != value)
  10.                         {
  11.                                 RemoveFromPanel();
  12.                                 mSprite = value;
  13.                                 nextSprite = null;
  14.                                 CreatePanel();
  15.                         }
  16.                 }
  17.         }
Your script's LateUpdate function was this in my working version:
  1.         void LateUpdate ()
  2.         {
  3.                 if (Application.isPlaying)
  4.                 {
  5.                         mNguiSprite.sprite2D = mUnitySpriteRdr.sprite;
  6.                 }
  7.         }

favoyang

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 14
    • View Profile
Re: Update UI2DSprite.sprite2D in place
« Reply #5 on: July 09, 2014, 10:02:31 PM »
Thanks it works! Do you think it worth to update NGUI upstream for this patch?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Update UI2DSprite.sprite2D in place
« Reply #6 on: July 10, 2014, 08:15:54 PM »
I've made the changes in the Pro repository, so they will be a part of the next release.