Author Topic: Sprites shifting in a UIDraggablePanel  (Read 6100 times)

Radazen

  • Guest
Sprites shifting in a UIDraggablePanel
« on: January 14, 2013, 06:44:59 PM »
I have a UIDraggablePanel with a vertical list of items in it. Everything seems to work fine at first, but eventually the sprites start to exhibit some bizarre shifting behavior that I can't figure out. When I say "eventually," I mean that I tend to see this happen if I keep the app running in the background on my iPhone and then come back to it a day later, or if I keep the Unity editor running for a day or so. I've reproduced it in both places.

It looks like the drawn position of sprites is different from the actual transform position of their respective GameObjects. If I do anything in the Unity editor to change the transform of one of these shifted sprites, the sprite will jump back into the correct position as if all it needed was something to cause it to refresh its position. Like, the issue is happening on the Y axis, but if I change an affected GameObject's X position by 1 unit in the Unity editor, the drawn sprite on the screen will jump back into the correct Y position too.

The shifting seems to occur shortly after I resume the app after it's been in the background for a while, but I can't say for certain whether that's related.

The attached screenshots sum up the shifting effect better than I can really explain with words. The first screenshot is how everything looks initially, the middle ones are the shifting effect, and the last screenshot is of the Unity editor where the sprite is clearly being drawn in one place while its visible widget bounds are in a different place.

It's worth noting that all of the screenshots except for the last one were taken during the same run of the application. When I scroll the panel up and down (in and out of my hard-clipped panel), the shifting effect keeps changing.

EToreo

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 88
    • View Profile
Re: Sprites shifting in a UIDraggablePanel
« Reply #1 on: January 14, 2013, 08:55:41 PM »
Try capturing the event of coming back from background mode and set your grid's "repositionNow" = true.  I assume your vertical list of items is a grid (or table).  No idea if it will work, just an idea.

Radazen

  • Guest
Re: Sprites shifting in a UIDraggablePanel
« Reply #2 on: January 14, 2013, 09:01:43 PM »
No UIGrid involved here. Just a group of prefabs that get instantiated, programmatically positioned, and never get changed/updated/moved after that.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Sprites shifting in a UIDraggablePanel
« Reply #3 on: January 15, 2013, 07:00:19 AM »
Try broadcasting a Refresh message to the UI when you return from sleep.

Radazen

  • Guest
Re: Sprites shifting in a UIDraggablePanel
« Reply #4 on: January 16, 2013, 11:20:34 AM »
I tried broadcasting the refresh message to the UI root and all of its children, but the issue is still happening. It doesn't actually occur right when I resume the app...typically, it's after I resume the app and then scroll the list up and down a few times.

Radazen

  • Guest
Re: Sprites shifting in a UIDraggablePanel
« Reply #5 on: January 16, 2013, 11:38:34 AM »
I'm also starting to think that it's related to time tracking, because try as I might, I cannot make the issue happen right away after restarting the app...but somewhere between a few hours and a day from now, I'll resume the app, scroll a few times, and everything will start to jumble.

I'm using a MomentumAndSpring drag right now. I'm going to try basic scrolling with no effects and see if that does anything.

Radazen

  • Guest
Re: Sprites shifting in a UIDraggablePanel
« Reply #6 on: January 17, 2013, 12:58:50 PM »
Okay, it still happens when I don't use any drag effects, so I guess that's not related.

So I thought "maybe realtimeSinceStartup is being weird." The timescale in my game is always 1.0, so I figured I'd try a global replace of "Time.realtimeSinceStartup" in NGUI with "Time.time" to see what happens. Not being super familiar with NGUI's internals, I was hoping that the replacement wouldn't really break anything.

Funny enough, what it actually does is makes the issue easily reproducible. By replacing Time.realtimeSinceStartup with Time.time, I get the sprite shifting effect within the first couple of scrolls up and down whenever I launch the app. So now I'm even more convinced that it's somehow related to time, though I'm not exactly sure how yet. Of course, it's also possible that the two shifting effects are unrelated, and maybe my global search/replace created a different issue that looks identical to the bug I'm trying to solve, but it seems unlikely.

Radazen

  • Guest
Re: Sprites shifting in a UIDraggablePanel
« Reply #7 on: January 17, 2013, 02:19:30 PM »
As far as I can tell, the culprit is UpdateTransformMatrix () in UIPanel.cs. It'll take me a day or two to see if the problem reoccurs after I tweak this, but as far as I can tell, my sprites only shift in the frames where the transform matrix skips updating (when Time.realtimeSinceStartup == mMatrixTime). When I switched to using Time.time instead of Time.realtimeSinceStartup, the odds of having (time == mMatrixTime) went up dramatically, which is why I started seeing the issue occur more frequently. When I use Time.realtimeSinceStartup, I pretty much never see (time == mMatrixTime), but I'm guessing that it does occur occasionally over hours or days of usage, and that eventually causes the issue I'm seeing.

Am I in for a major performance hit if I comment out the conditional and always update the matrix in UpdateTransformMatrix? It doesn't seem like it, since it never seems to skip the update when I'm using Time.realtimeSinceStartup anyway.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Sprites shifting in a UIDraggablePanel
« Reply #8 on: January 17, 2013, 08:58:32 PM »
Eh? That check basically checks -- have we already calculated the matrix this update? If yes, don't do anything. It's for IsVisible() checks, so that they don't calculate the matrix more than once when checking for widget visibility.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Sprites shifting in a UIDraggablePanel
« Reply #9 on: January 17, 2013, 09:01:55 PM »
You can try adding this function in UIPanel.cs

  1. /// <summary>
  2. /// Reset the calculated matrix for the panel, forcing it to be updated the next time it's used.
  3. /// </summary>
  4.  
  5. public void ResetMatrix () { mMatrixTime = 0f; }

...then using it just prior to updating the scroll bars in UIDraggablePanel.SetDragAmount:

  1. // Update the clipping offset
  2. cr.x = ox;
  3. cr.y = oy;
  4. mPanel.clipRange = cr;
  5. mPanel.ResetMatrix();

Radazen

  • Guest
Re: Sprites shifting in a UIDraggablePanel
« Reply #10 on: January 17, 2013, 10:05:36 PM »
Thanks! I'll try that out in a day or two. I'm going to keep the current changes running on my phone for a couple of days to make sure the issue is really gone.