- Home /
Changes to Mesh Vertex Colors Reset on Build
Hey folks,
I created a more complex version of Alex's Vertex Color Method for my artist a few days ago, allowing her to change multiple vertex colors in her meshes : the idea being that she could (e.g.) create a model of a house with a different vertex colour for the roof, door and walls, then give the house a vertex colour material and change the colours of these elements individually.
The vertex colour editing scrip looks like this :
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[ExecuteInEditMode]
public class UpdateVertexColors : MonoBehaviour
{
private int[] colorPosition;
private List<Color> colors = new List<Color>();
private MeshFilter meshFilter;
private Mesh mesh;
private MeshFilter MeshFilter
{
get
{
return this.GetComponent<MeshFilter>();
}
}
private Mesh Mesh
{
get
{
return this.MeshFilter.mesh;
}
set
{
this.MeshFilter.mesh = value;
}
}
public List<Color> Colors
{
get
{
if(this.colors.Count == 0)
{
this.GetColors();
}
return this.colors;
}
set
{
this.colors = value;
}
}
public void GetColors()
{
int i = 0;
colorPosition = new int[this.Mesh.vertices.Length];
while(i < this.Mesh.vertices.Length)
{
if(!colors.Contains(this.Mesh.colors[i]))
{
this.colors.Add(this.Mesh.colors[i]);
}
colorPosition[i] = this.colors.IndexOf(this.Mesh.colors[i]);
i++;
}
}
public void SetColors()
{
int i = 0;
Color[] newColors = new Color[this.Mesh.vertices.Length];
while(i < this.Mesh.vertices.Length)
{
newColors[i] = this.colors[this.colorPosition[i]];
i++;
}
this.Mesh.colors = newColors;
}
}
... and in order to simplify the artist's life, it's manipulated by a custom inspector that looks like this :
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(UpdateVertexColors))]
public class UpdateVertexColorInspector : Editor
{
UpdateVertexColors script;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
int i = 0;
while(i < this.Script.Colors.Count)
{
this.Script.Colors[i] = EditorGUILayout.ColorField("§", this.Script.Colors[i]);
i++;
}
if(GUI.changed)
{
this.Script.SetColors();
}
}
private UpdateVertexColors Script
{
get
{
if(script == null)
{
script = (UpdateVertexColors)target;
}
return script;
}
}
}
The script works absolutely fine, and the artist can adjust colours to her little heart's content BUT almost all the changes disappeared the moment we make a Build (originally to test the Shaders on Android devices, but I have since tested the problem with a Standalone build and the same thing happens).
I say "almost all the changes" because a number of trees, which she appears to have copied and pasted after changing their colour, appear to retain their new colour.
The colours are also wiped out in the Editor. I've tried various combinations of serializing the Mesh / Meshfilter etc. and it doesn't seem to have any kind of effect.
Thoughts? I'm out of ideas at this point.
R.
Answer by MakeCodeNow · Jun 20, 2014 at 03:19 PM
On changes, mark the Mesh with EditorUtility.SetDirty() so that Unity knows to save it.
Good thought @$$anonymous$$akeCodeNow, I made the $$anonymous$$esh
property public in my script and added EditorUtility.SetDirty(this.Script.$$anonymous$$esh);
after this.Script.SetColors();
in the custom inspector, but it doesn't seem to have made any difference. I tried the same thing setting the $$anonymous$$eshFilter
and/or the entire GameObject
dirty, but that didn't do it either.
Just to be clear, this only happens if I make a Build from the File menu, pressing Play doesn't appear to wipe the Vertex Colour changes from my meshes. It occurred to me that this might somehow be a serialization issue, but I'm not entirely sure how to address it if that's the case.
Are you modifying a $$anonymous$$esh that's imported from an FBX or the like? If so, that's the problem. You'd need to duplicate the original mesh to a new mesh asset, assign that to the object, and then mutate the vert colors on that copy.
@$$anonymous$$akeCodeNow, that sounds promising and it would certainly explain why some trees are retaining their changes.
Questions, though : The meshes of the trees that retain their colours are labeled "Instance" somehow, but I'm not sure how/where that happened. So the surviving trees have meshes named Fichte6_050 Instance
rather than the normal Fichte6_050
I assume that's essentially what you're describing?
Do you mean that I should duplicate the meshes in editor, or that I should do it in code as part of the colour-changing process? (I ask because I've just duplicated the meshes in editor as a test run and it doesn't appear to have changed anything, but I'm essentially just duplicating an imported .fbx so I might be going about it the wrong way).
Thanks for your help!
You should read up on the difference between the mesh and the sharedmesh attributes of $$anonymous$$eshFilter. That will explain where the instances are co$$anonymous$$g from. In general, though, if you want to take a mesh, change it's vertex colors, and have it be saved, you'll need to make a new mesh resource in code, copy the original mesh data into it, modify the vertex colors, and then save it using AssetDatabase.
Hi @$$anonymous$$akeCodeNow, I'm familiar with the difference between meshes and sharedmeshes, but I'm still not sure where the instances are co$$anonymous$$g from (or how our artist managed to create these instances in editor). What do you mean?
Alright, I was hoping I would be able to avoid creating and saving new mesh resources, but it does increasingly look like that's the only way. I'll amend my scripts and see what exciting new issues that might create.
Thanks for your thoughts. R.