There is a problem when animating a UIPanel's clipping region which means that widgets on the panel which should be drawn end up not getting drawn at all.
I first encountered this in a fairly complex UI scene I was working on, although I've reproduced the problem in a very simple scene. I don't know if there's a way to send you the scene file (I can do so if you want me to), but it's probably simple enough for me to describe. It looks like this:
UIRoot
- Camera2D
-- UIPanel (with an Animation)
--- UISprite
The UIPanel is at (0,0,0) and has an Alpha Clip which is initially set up with centre (0,0) and size (100,200). The Animation is set to play automatically, has the culling type set to Always Animate, and the animation itself simply animates the Clip Range W from 1 to 200 over a second.
The UISprite is just a simple sprite which I've made 100*100, with the pivot point at the Top. This could be any widget though, I've seen the problem happen with UILabels as well. Now, when the sprite's transform starts out at (0,0,0) and you hit play, everything works as expected: The clip panel starts 1 pixel high, then expands and you see the sprite appear from the top down (like a fill sprite with an inverted vertical fill). However, if you set the sprite's transform to (0, -1, 0) or some other negative y value, then the panel expands but you never see the sprite. The Inspector view for the panel says that it contains 1 Widget but 0 Draw Calls. The only way to make the sprite appear is by editing its transform in some way, which forces a refresh and makes the sprite appear.
I've had some trouble following the ins and outs of the panel/widget visibility code, so I might be wrong here, but I think what happens is as follows:
- Scene gets created. Animation is started automatically, setting the initial clip region to (100,1)
- UIPanel.LateUpdate adds the widget(s) to the panel, but notices that the sprite is just outside the clip region (its top edge being -1), so sets it as not visible
- In subsequent frames during and after the animation, nothing changes in the sprite's material, depth or alpha, meaning it's never added to the panel's mChanged list, so is never passed to the Fill method to have its visiblity reconsidered. Only some external effect that changes the transform or material causes this to happen and the sprite to reappear.
How can I get around that? It seems to me that if a clip region is animating, the panel should consider all of its widgets to have changed, and so reprocess them every frame. Or if that's too inefficient, perhaps the panel needs to work out at which point it will be biggest, and base its calculations from that. Or should I write some custom thing than, on the first update, sets the panel to some sufficiently big size, marks all of the widgets dirty and then sets the size back to whatever the animation had set it to?