Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: AtomicBob on June 12, 2013, 03:06:41 PM

Title: Changing UITextures at runtime
Post by: AtomicBob on June 12, 2013, 03:06:41 PM
I've run into a bit of a problem using UITextures and hoping someone can point me in the right direction. I'm instantiating 6 copies of a prefab with a UITexture on it. Then I'm choosing which texture should be used on each item, of which there are 2 placeholder textures and the rest are downloaded from the internet. What I'm seeing is things working precisely as I expect for a while, but then after running the game enough times in the editor, changing the texture on one instance causes all of the other instances to change too. I'm trying to prevent this from happening.

I'm guessing it has something to do with the materials being used for the UITextures. Possibly that they all have the same material. However, I thought UITextures generated their materials automatically.

Some extra info: the prefab has the Unlit/Transparent Colored shader assigned. The prefab does not have any texture assigned (though I noticed the prefab actually get's updated based on which textures are set at runtime, odd). I'm using mUITexture.mainTexture = downloadedTexture to change the textures.
Title: Re: Changing UITextures at runtime
Post by: ArenMook on June 13, 2013, 03:55:54 AM
If you duplicate a UITexture within the editor, it will use the same material until you hit Play. If you assign a material instead of assigning a texture, it will always keep using that material (which will then be shared between different UITextures). Otherwise UITextures should have different materials, generated dynamically.

If you run into any issues, just create your own material (mat = new Material()) and assign it to the UITexture instead of setting its mainTexture.
Title: Re: Changing UITextures at runtime
Post by: AtomicBob on June 13, 2013, 10:34:19 AM
Thanks for the response. I'm a bit unclear on a couple of your points.


I've worked around the problem by assigning a new material to each UITexture as they are instantiated, but I still want to understand how this is supposed to work. I can see arguments for instances of prefabs sharing the original material and for having their own, however, changing the texture on one should be consistent. The question is, should changing the texture create a new material so it can't affect other instances, or should changing one instance be able to change all of them? We can obviously assign a new material explicitly when we want to ensure we don't affect other instances, however this could be done automatically with, say, a boolean createMaterialOnChange.

PS While testing this, I noticed other odd behaviors.
Title: Re: Changing UITextures at runtime
Post by: AtomicBob on June 18, 2013, 02:49:37 PM
Still curious about this if anyone has any insight.
Title: Re: Changing UITextures at runtime
Post by: ArenMook on June 18, 2013, 11:58:44 PM
First thing first -- what version of NGUI are you using?

2. Assigning a material to a UITexture means it will use that material. Other UITextures will only use that material if you duplicate the UITexture, or assign the same material to others manually.

3. Theoretically it should be consistent, but it might depend on what info Unity stores on the prefab. To be safe, clear the texture reference from your UITexture on the prefab since you are assigning them manually anyway.
Title: Re: Changing UITextures at runtime
Post by: AtomicBob on June 19, 2013, 09:58:56 AM
2.6.1e. I haven't gotten around to upgrading to 2.6.3 yet.

Regarding clearing the texture from the prefab, I threw together a test scene and it looks like that may be the solution. I tested this before but it didn't work because the other issues were interfering. Here's what happens:

Case 1: Adding a new UITexture component to the prefab will have no material, texture, or shader. If copies are instantiated at this point, everything behaves correctly.

Case 2: Assigning a texture to the UITexture prefab will auto generate a material and choose a shader. If copies are instantiated at this point, changing the texture on any instance changes every instance, like one would expect.

The unintuitive part:
Case 3: Removing the texture (and/or shader) from the UITexture prefab does not remove the autogenerated material. If copies are instantiated at this point, one would expect things to act like Case 1 above, but instead changing the texture on any instance changes every instance.

The only way to distinguish when Case 3 will occur is when the Material is hidden on the UITexture prefab. There is no way to get back to Case 1 without removing the UITexture component and readding it.

I can't test this in the original scenario at the moment, so I don't know why it would work for a while and then suddenly stop, but I suspect it has something to do with the prefab being updated with changes to instances.