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;
}
}
This answer is YES. You could modify the asset if it is purchased from Unity Asset Store.
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.
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.
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.
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.
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; }
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With