Swapping textures at runtime and memory usage

Hi. I’m curious about swapping out textures when a scene loads. Basically I want to swap out all the textures for textures half the resolution in it’s on an iphone. If I do that would the old textures that were previously assigned to the material be completely removed from memory or will they still be lingering making it pointless to swap them in the first place.

Also, I know I can loop through all the gameObjects in the scene, but I should only have to do it for each material once right? Is there a way to just find all the materials being used in the scene?

Thanks

Is this so you can use lower resolution textures on 3G compared to 3GS?

The property you are after is this one:

renderer.sharedMaterialYou’ll probably still have trouble limiting which materials you need to swap out but you could create a list of materials with a loop to filter out any duplication

List<Material> changeMaterials = new List<Material>();

foreach (Material material in allMaterials)
{

   if (!changeMaterials.Contains(material))
   {

       changeMaterials.Add(material);

   }

}

foreach (Material material in changeMaterials)
{

     material.mainTexture = blah;

}

}

yeah, it’s basically cause everything is setup with higher res textures for ipad and iphone 4 right now so I figured I’d swap them out if on a lower system.

So that old texture would be completely removed from memory then? I don’t want to just add more to memory.

Textures are not removed from memory unless you explicitly Destroy them (and even then, the space used remains allocated until you load a new level or use Resources.UnloadUnusedAssets). Unity objects such as textures, meshes, etc. are not touched by the garbage collector, which only deals with Mono objects.

–Eric

SO then would it not make sense to swap out the textures, cause then I’ll be using more memory right?

If you have Unity Pro, you could use AssetBundles to load in your textures at run time and assign them; ugly… but works.

edit
You could use Resources\ as well if you don’t have pro; my understanding is that the Resources\ content doesnt touch memory until you Load it explicitly.

I don’t have pro. I just have iPhone basic. All the textures are already assigned to the material in the editor. I was just going to swap them out for half res versions. If I didn’t assign them in the editor I would be able to see anything I was doing.

I would recommend doing it the other way around. Set up your materials with the half-res textures and swap them to the high res ones for iPad/Retina, as the newer devices will probably have enough memory to hold both of the textures.

You can use multiple version of texture in Resources directory and use Resources.UnloadUnusedAssets() whenever you done the swapping! It’s work really nice! I handled 3 different version of texture for a game.

Another option that is really simple that you don’t see around here very often is to change the QualitySettings based on the current device:

This might be a dumb question, but I want to make sure I understand the Resources functionality: does Resources.UnloadUnusedAssets() only remove assets that were from the Resources folder? It will not scan other assets that are not within the Resources folder right?

@corey, it appears to unload all resources. From the docs:

I am playing around with loading assets from the Resources folder according to the documentation. But since I’m using Unity iPhone Pro 1.7 I can’t even use Resources.UnloadUnusedAssets. Back to the search bar.

If anyone can point me to some references where I can successfully remove an asset loaded by the Resources.Load method (besides loading a new level), I’d appreciate it. Thanks.

That seems like it should actually be the best way. Nice and easy. But I can’t seem to get it to work. I set the texture quality on the fast setting to half resolution. I tried testing it by setting the default quality to fast and playing it. All the textures still looked full resolution. Is there something else I need to do?

Thanks

*Edit, I figured it out. The textures had to have mipmaps turned on

I was just about to post that you need mips. There isn’t an easier way to pull off multiple texture sizes than this for sure. Kudos to Unity for adding it. If only more people were aware of it.

Does the mipmapping method still load in the whole texture at all sizes? As in the max size and all the smaller sizes into memory? Because if it preforms in this manner it would still be better for memory intensive games to load the textures individually rather than using the mip mapping.

On the unity site it says:
This lets you choose whether to display textures at maximum resolution or at a fraction of this (lower resolution has less processing overhead). The options are Full Res, Half Res, Quarter Res and Eighth Res.
but mentions nothing about a lower memory footprint.

Instead of using Resources.UnloadUnusedAssets() which will spin through and check the reference count on loaded resources it is much more efficient to call Resources.UnloadAsset(object) which was added in 3.5.2; it was added to the API specifically for this purpose.

I’m also wondering the same thing.

I think I read in another thread that Unity will load all mip maps up to the requested quality level. So loading the Full Res texture will also load the half, quarter, and eighth res versions. But loading the Quarter Res version would only load the quarter and eighth res textures. I haven’t tested this, though.

Using the QualitySettings sounds like a great solution if mobile is your only target. It doesn’t seem like it would work if you also plan on targeting the Retina Macbook Pros or other high resolution desktop monitors :frowning: