Swaping materails for different platforms (Desktop vs.iOS)

I’ve not figured this one out yet…

If you have a game designed for multiple platforms, is there some way to create a different set of materials for each? In particular, I have a game that will emit a desktop, web, iOS (maybe others) version. Unity does this great, but I need the materials (more specifically the shaders) to be different on say the iPhone than on the desktop for obvious reasons.

How is this generally done?

David

In the manual:

http://unity3d.com/support/documentation/Manual/Platform%20Dependent%20Compilation.html

That’s for differences in code. I’m talking about the materials (shaders).

Instead of switching materials, you could try setting shader LOD (using Shader.maximumLOD) from scripts depending on current platform: Unity - Manual: ShaderLab: assigning a LOD value to a SubShader

So I take it this is just a missing feature? You’ll notice that textures have overrides for different platforms. Shaders (or maybe more specifically materials) need this as well.

Make the two materials, then via script, set your model to use the proper material using platform dependent compilation.

define variables like:

public Material iPhoneMaterial;
public Material desktopMaterial;

somewhere in Start():

#if UNITY_IPHONE
renderer.material = iPhoneMaterial;
#elif
renderer.material = desktopMaterial;
#endif

That would wok. Though very tedious.

I notice that Unity has alternate settings for materials per platform. Hoping for a similar feature on materials in the future.

David

So, using #ifdef UNITY_ANDROID within a .shader files has no effect? Would be useful.

vote for this feature here
http://feedback.unity3d.com/unity/all-categories/1/hot/active/change-material-on-different-pla

We have scripts that open every scene, and replace textures, so you fire it once, it’ll run through 20 or 30 scenes, done :slight_smile: Editor scripts… Amazing stuff.

writing editor script to make some change befor build help alot, but i don’t like it ,
because i will find my self having a list of things i have to do before any build , and if you use asset server or svn , you have to be carefull not to commet these changes , because it is changes for build for specific platform.

It’s not uncommon to have a build checklist, in fact I recently shared mine here for one of our titles.

Another option is a pre-build script (part of the pre-process scripts I guess) that does the same thing to swap materials in the scene (so you aren’t building two lots of dependencies).

This is actually an ongoing concern with Unity, it would be good to have platform dependant mesh, shader and maps as part of its core functionality. You can of course script all of these things, but since cross-platform functionality is a big key to Unity’s success, it does seem sensible to include the feature :slight_smile:

Old Post but maybe someone will be able to use this.
Useage:
Create a new scene
For each material create a ball with the original material assigned
Assign the script to each ball
Assign the new material to the script
Save the scene.
Duplicate the project or modify the script to have a reverse option
Ensure all scenes are in the build settings.
Run the script.
Warning: This will overwrite all of your scenes / materials with new ones.

using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using System.Collections.Generic;

public class MaterialSwaper : MonoBehaviour
{
    public Material newPS4Material;

    [UnityEditor.MenuItem("PlayStation VR/Change Materials")]
    private static void materialChanger()
    {
        Material[,] materialsToSwap = GetMaterialsToChange();
        string[] sceneNames = GetScenes();

        for(int i = 0; i < sceneNames.Length; i++)
        {
            LoadAndProcess(sceneNames[i], materialsToSwap);
            SaveScene();
        }
    }

    private static Material[,] GetMaterialsToChange()
    {
        GameObject[] allGameObjects = GameObject.FindObjectsOfType(typeof(GameObject)) as GameObject[];
        Material[,] materials2DArray = new Material[allGameObjects.Length, 2];

        Debug.Log("There are " + allGameObjects.Length + " gameObjects in your scene");

        for( int i = 0; i < allGameObjects.Length; i++)
        {
            materials2DArray[i,0] = allGameObjects[i].GetComponent<Renderer>().sharedMaterial;
            materials2DArray[i,1] = allGameObjects[i].GetComponent<MaterialSwaper>().newPS4Material;

            Debug.Log(i + " Names are " + materials2DArray[i, 0] + " -> " + materials2DArray[i, 1]);
        }

        return materials2DArray ;
    }

    private static string[] GetScenes()
    {
        List<string> temp = new List<string>();
        foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
        {
            if (scene.enabled)
            {
                string name = scene.path;//.Substring(scene.path.LastIndexOf('/') + 1);
                //name = name.Substring(0, name.Length - 6);
                temp.Add(name);
                Debug.Log("Scene Name: " + name);

            }
        }
        return temp.ToArray();
    }

    private static void LoadAndProcess(string sceneName, Material[,] materialsOldAndNew)
    {
        EditorSceneManager.OpenScene(sceneName);

        GameObject[] allGameObjects = GameObject.FindObjectsOfType(typeof(GameObject)) as GameObject[];

        if(allGameObjects.Length > 0)
        {
            foreach (GameObject GO in allGameObjects)
            {
                //Debug.Log("Processing GO = " + GO.name);

                Renderer gameObjectRenderer = GO.GetComponent<Renderer>();

                if (null != gameObjectRenderer)
                {
                    Material[] gameObjectMaterials = gameObjectRenderer.sharedMaterials;

                    //Debug.Log(gameObjectRenderer.name + " is Not Null @ " + gameObjectMaterials.Length);

                    for (int cm = 0; cm < gameObjectMaterials.Length; cm++)
                    {
                        //Debug.Log("Processing Material = " + gameObjectMaterials[cm].name);
                    
                        for (int nm = 0; nm < materialsOldAndNew.Length / 2; nm++)
                        {
                            //Debug.Log("--->Concidering = " + materialsOldAndNew[nm,0].name );// +", " + materialsOldAndNew[nm, 1].name);

                            if (gameObjectMaterials[cm] == materialsOldAndNew[nm, 0])
                            {
                                //Debug.Log("Replacing " + materialsOldAndNew[nm, 0].name + " with " + materialsOldAndNew[nm, 1].name);
                                gameObjectMaterials[cm] = materialsOldAndNew[nm, 1];
                            }
                        }
                    }

                    gameObjectRenderer.sharedMaterials = gameObjectMaterials;
                }
            }
        }
    }

    private static void SaveScene()
    {
        Scene thisScene = SceneManager.GetActiveScene();

        if (EditorSceneManager.SaveScene(thisScene)) Debug.Log("Scene Saved!" + ", " + thisScene.name);
    }
}