Hello, I’ve ran into this annoying issue as well and devised a semi-crappy solution.
Instead of modifying the material properties directly, I modify them through extension methods where I stash the initial value of the property in dictionaries so when play mode stops and OnDestroy is called on my singleton monobehaviour that collects these dictionaries, the initial values of those properties can be reverted back to all the modified materials. Hope it helps someone, it solved my issue with properties of materials being modified in git but I still have the problem with a field called m_InvalidKeywords which changes from empty array [ ] to _LIGHTS_ON… I didn’t figure this out or how I can revert that back. If anyone knows, I’d be grateful.
Anyway, here is my code that I use to modify material properties:
public static class MaterialSetterAndResetterExtensions
{
public static void SetColorTemp(this Material material, string property, Color value)
{
MaterialSetterAndResetter.SetColorTemp(material, property, value);
}
public static void SetFloatTemp(this Material material, string property, float value)
{
MaterialSetterAndResetter.SetFloatTemp(material, property, value);
}
public static void SetTextureScaleTemp(this Material material, string property, Vector2 val)
{
material.SetTextureScale(property, val);
}
public static void SetTextureTemp(this Material material, string property, Texture val)
{
material.SetTexture(property, val);
}
public static void SetVectorTemp(this Material material, string property, Vector2 vec)
{
material.SetVector(property, vec);
}
}
/// <summary>
/// This class tries to solve the issue of modifying material assets at runtime and having those changes affect the git repository.
/// OnDestroy, this script reverts back any material that was modified through its extension methods SetTempColor, SetTempFloat, etc.
///
/// In any script you want to modify a material, instead of
/// using mat.SetFloat("_lights",1),
/// use
/// mat.SetTempFloat(mat, "_lights", 1)
///
/// This can be modified to reset materials at different convenient times for the client like scene change, etc.
/// </summary>
public class MaterialSetterAndResetter : SingletonMonoSelfGeneratingNonPersistentPrivateInstance<MaterialSetterAndResetter>
{
private Dictionary<Material, MaterialChanges> materialsAndTheirChanges = new();
internal static void SetColorTemp(Material material, string property, Color value)
{
Instance.SetColor(material, property, value);
}
internal static void SetFloatTemp(Material material, string property, float value)
{
Instance.SetFloat(material, property, value);
}
protected override void OnCreation()
{
}
private void SetColor(Material material, string property, Color value)
{
var materialChanges = GetExistentOrNewMaterialChangesFor(material);
materialChanges.AddColorInitialValue(material, property);
material.SetColor(property, value);
}
private void SetFloat(Material material, string property, float value)
{
var materialChanges = GetExistentOrNewMaterialChangesFor(material);
materialChanges.AddFloatInitialValue(material, property);
material.SetFloat(property, value);
}
private void OnDestroy()
{
foreach (var pair in materialsAndTheirChanges)
{
pair.Value.ResetMaterialValues();
}
}
private MaterialChanges GetExistentOrNewMaterialChangesFor(Material material)
{
if (!materialsAndTheirChanges.TryGetValue(material, out MaterialChanges materialChanges))
{
materialChanges = new MaterialChanges(material);
materialsAndTheirChanges.Add(material, materialChanges);
}
return materialChanges;
}
private class MaterialChanges
{
private Dictionary<string, float> floatsAndInitialValues = new();
private Dictionary<string, Color> colorsAndInitialValues = new();
private Material material;
public MaterialChanges(Material material) => this.material = material;
internal void AddFloatInitialValue(Material material, string property)
{
if (floatsAndInitialValues.ContainsKey(property)) return;
float intialValue = 0;
if (material.HasProperty(property)) intialValue = material.GetFloat(property);
floatsAndInitialValues.Add(property, intialValue);
}
internal void AddColorInitialValue(Material material, string property)
{
if (colorsAndInitialValues.ContainsKey(property)) return;
var initialColor = Color.black;
if (material.HasProperty(property)) initialColor = material.GetColor(property);
colorsAndInitialValues.Add(property, initialColor);
}
internal void ResetMaterialValues()
{
foreach (var pair in floatsAndInitialValues)
{
material.SetFloat(pair.Key, pair.Value);
}
foreach (var pair in colorsAndInitialValues)
{
material.SetColor(pair.Key, pair.Value);
}
}
}
}
public abstract class SingletonMonoSelfGeneratingNonPersistentPrivateInstance<T> : MonoBehaviour
where T : SingletonMonoSelfGeneratingNonPersistentPrivateInstance<T>
{
private static T instance = null;
protected static T Instance
{
get
{
if (instance == null)
{
//Debug.LogFormat("Creating singleton {0}", typeof(T));
instance = Object.FindObjectOfType<T>();
if (instance == null)
{
instance = new GameObject(typeof(T).ToString()).AddComponent<T>();
}
instance.OnCreation();
}
return instance;
}
}
protected abstract void OnCreation();
}