Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

make changes to material assets in unity3d

Tags:

c#

unity3d

I am overriding some Material Assets using an Editor Script, and materials override nicely. I can see new material properties get applied and when I click on individual materials I can see new textures applied etc. However when I hit play, my materials reset to pre-edit state, Same thing happens when I hit CTR+S. My materials all reset back to what they were.

How can I make the changes get saved to database and persist when I hit play?

using UnityEngine;
using UnityEditor;
using Newtonsoft.Json;
using Unify.Utilities;
using System.Collections.Generic;
using System;
using System.IO;

public class ProcessMaterials : MonoBehaviour
{
    [MenuItem("Unify/ProcessMaterials")]
    static void UnifyProcessMaterials()
    {
    ImportTextures();
    ApplyMaterials();
    }

private static void ImportTextures()
{
    // check if folder exists and create one if not
    if (!AssetDatabase.IsValidFolder("Assets/Resources"))
    {
        AssetDatabase.CreateFolder("Assets", "Resources");
    }

    // load settings file
    TextAsset ta = Resources.Load("UnifySettings") as TextAsset;
    string json = ta.text;
    List<List<UnifyObject>> unifyObj = JsonConvert.DeserializeObject<List<List<UnifyObject>>>(json);
    List<UnifyObject> allMats = unifyObj[3];

    // copy textures over to unity folders
    HashSet<string> uniqueTextures = new HashSet<string>();
    foreach (UnifyObject obj in allMats)
    {
        if (obj.DiffuseTexture != null && uniqueTextures.Add(obj.DiffuseTexture))
        {
            CopyImageAsset(obj.DiffuseTexture);
        }
        if (obj.BumpTexture != null && uniqueTextures.Add(obj.BumpTexture))
        {
            CopyImageAsset(obj.BumpTexture);
        }
        if (obj.TransparencyTexture != null && uniqueTextures.Add(obj.TransparencyTexture))
        {
            CopyImageAsset(obj.TransparencyTexture);
        }
        if (obj.EnvironmentTexture != null && uniqueTextures.Add(obj.EnvironmentTexture))
        {
            CopyImageAsset(obj.EnvironmentTexture);
        }
    }
}

private static void CopyImageAsset(string sourceFilePath)
{
    string fileName = "Resources\\" + Path.GetFileName(sourceFilePath);
    string destFile = Path.Combine(Application.dataPath, fileName);

    try
    {
        File.Copy(sourceFilePath, destFile, true);
    }
    catch (Exception) { }
}

private static void ApplyMaterials()
{
    TextAsset ta = Resources.Load("UnifySettings") as TextAsset;
    string json = ta.text;
    List<List<UnifyObject>> unifyObj = JsonConvert.DeserializeObject<List<List<UnifyObject>>>(json);

    GameObject cube;
    cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
    Renderer cubeRenderer = cube.GetComponent<Renderer>();

    List<UnifyObject> allMaterials = unifyObj[3];
    foreach (UnifyObject obj in allMaterials)
    {
        // skip layers with no materials assigned/default
        if (obj.Guid != Guid.Empty.ToString())
        {
            // obj replaces all dashes in names with underscores hence material assets will have different names than in Rhino
            // if layers had dashes in their names
            string objUniqueName = obj.UniqueName.Replace("-", "_");
            Material m = (Material)AssetDatabase.LoadAssetAtPath("Assets/Resources/Model/Materials/" + objUniqueName + "Mat.mat", typeof(UnityEngine.Object));
            if (m != null)
            {
                OverrideMaterial(m, obj, cubeRenderer);
                AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(m));
            }
        }
    }
    DestroyImmediate(cube);
}

private static Material OverrideMaterial(Material m, UnifyObject obj, Renderer renderer)
{
    renderer.material = m;
    // set main color
    // set transparency
    if (obj.Transparency != "0")
    {
        Color newColor = Utilities.ConvertToUnityColor(obj.Diffuse, obj.Transparency);
        renderer.sharedMaterial.SetFloat("_Mode", 3);
        renderer.sharedMaterial.SetColor("_Color", newColor);
    }
    else
    {
        Color newColor = Utilities.ConvertToUnityColor(obj.Diffuse);
        renderer.sharedMaterial.SetColor("_Color", newColor);
    }

    // set main texture
    if (obj.DiffuseTexture != null)
    {
        renderer.sharedMaterial.mainTexture = Utilities.Texture2dFromPath(obj.DiffuseTexture);
    }

    // set bump map
    if (obj.BumpTexture != null)
    {
        Texture2D bumpTexture = Utilities.Texture2dFromPath(obj.BumpTexture);
        float strength = Convert.ToSingle("1.0");
        Texture2D normalBump = Utilities.CreateNormalMap(bumpTexture, strength);
        renderer.sharedMaterial.SetTexture("_BumpMap", normalBump);
        // need to get that value from Rhino somehow
        renderer.sharedMaterial.SetFloat("_BumpScale", 0.3f);
    }

    // set metallic
    renderer.sharedMaterial.SetFloat("_Metallic", Utilities.ConvertRange(0, 255, 0, 1, Convert.ToSingle(obj.Metallic)));

    // set emission color
    Color emissionColor = Utilities.ConvertToUnityColor(obj.EmissionColor);
    renderer.sharedMaterial.SetColor("_EmissionColor", emissionColor);
    return renderer.sharedMaterial;
}
}
like image 341
konrad Avatar asked Apr 29 '16 18:04

konrad


People also ask

Can you edit assets in Unity?

This answer is YES. You could modify the asset if it is purchased from Unity Asset Store.

Does Unity have a material editor?

Use the Material Editor window to apply Materials to objects or faces. Use the Quick Material section to set up a Material to apply with a button or a hotkey. Use the Material Palette section to designate several Materials to use with buttons or hotkeys.

How do I load a material variant in Unity?

When Unity begins to load a new Material Variant, the Material Variant has a striped icon in the Project window. After Unity finishes loading the new Material Variant, the normal Material preview replaces the striped icon in the Project window. Select a Material Variant.

What is a mesh filter in Unity?

Meshes: meshFilter. mesh The main graphics primitive of Unity. Meshes make up a large part of your 3D worlds. Unity supports triangulated or Quadrangulated polygon meshes. Nurbs, Nurms, Subdiv surfaces must be converted to polygons. More info Physic Materials A physics asset for adjusting the friction and bouncing effects of colliding objects.

Is it possible to write scripts in Unity?

However, it is possible in Unity to write scripts A piece of code that allows you to create your own Components, trigger game events, modify Component properties over time and respond to user input in any way you like. More info See in Glossary that will permanently modify a source asset. Let’s use the above material example as a starting point.

How to temporarily change the material’s shader?

To temporarily change the material’s shader, we change the shader property of the material component. private var invincibleShader = Shader.Find ("Specular"); function StartInvincibility { renderer.material.shader = invincibleShader; }


1 Answers

After you overwrite the materials, call the following functions

UnityEditor.EditorUtility.SetDirty(AssetName);
UnityEditor.AssetDatabase.SaveAssets();
UnityEditor.AssetDatabase.Refresh();

If the method above did not work, another method that might work is to create a simple cube, assign the loaded material to the cube then modify the Renderer.sharedMaterial of the cube instead of Renderer.material. Usually, modifying sharedMaterial changes the original material permanently but I don't know if applies to loaded materials from AssetDatabase. This should be done inside your OverrideMaterial function. The GameObject.CreatePrimitive(PrimitiveType.Cube); function should only be called once.

GameObject cube;
cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

Renderer cubeRenderer = cube.GetComponent<Renderer>();

//Change the cube material to the material that is loaded from the disk
cubeRenderer.material = m;

//Now modify the shared array of the cube
cubeRenderer.sharedMaterial.SetFloat("_Mode", 3);
cubeRenderer.sharedMaterial.SetColor("_Color", newColor);
//cubeRenderer.sharedMaterial.
//cubeRenderer.sharedMaterial.
like image 154
Programmer Avatar answered Sep 28 '22 05:09

Programmer