- Home /
Edit SkinnedMeshRenderer
Hello guys!
i got the problem with my script for edit mesh. I'm trying to achieve edit mesh with vertices. When i'm using my script in prefab mode everything works fine.
But when i'm reopening my project my modifed prefab mesh back to the original form(vertices positions saving).
Someone culd help me to figure out how to save my modified mesh even i'm reopen the project? I wan't to edit my mesh with vertices without assign script everytime when i reopen the project. Code:
using System;
using UnityEditor;
using UnityEngine;
[ExecuteInEditMode]
[DisallowMultipleComponent]
public class BoneEditor : MonoBehaviour
{
public SkinnedMeshRenderer skinned;
public MeshCollider meshCollider;
public Mesh meshCreated;
Transform[] bones;
Matrix4x4[] bindPoses;
BoneWeight[] boneWeights;
public int count = 0;
Vector3[] vertices;
BoneWeight[] weights;
private void Awake()
{
skinned = GetComponent<SkinnedMeshRenderer>();
meshCreated = GetComponent<SkinnedMeshRenderer>().sharedMesh;
meshCollider = GetComponent<MeshCollider>();
}
void Start()
{
CreateLoadBone();
}
private void CreateLoadBone()
{
count += 1;
if (count > 1) { count = 2; }
if (this.gameObject.GetComponent<BoneEditor>().count == 1)
{
SkinnedMeshRenderer skinned = this.GetComponent<SkinnedMeshRenderer>();
if (skinned.sharedMesh == null || skinned.sharedMesh.vertexCount == 0)
return;
//Mesh mesh = (Mesh)UnityEngine.Object.Instantiate(skinned.sharedMesh);
meshCreated.RecalculateBounds();
meshCreated.RecalculateNormals();
meshCreated.RecalculateTangents();
bones = new Transform[meshCreated.vertexCount];
bindPoses = new Matrix4x4[meshCreated.vertexCount];
boneWeights = new BoneWeight[meshCreated.vertexCount];
// AssetDatabase.CreateAsset(meshCreated, "Assets/body.mesh");
// AssetDatabase.SaveAssets();
for (int index = 0; index < meshCreated.vertexCount; index++)
{
bones[index] = new GameObject(string.Format("Bone [{0}]", index)).AddComponent<VerticalesMidifierGizmo>().transform;
bones[index].SetParent(this.transform);
bones[index].position = this.transform.TransformPoint(meshCreated.vertices[index]);
bindPoses[index] = bones[index].worldToLocalMatrix * this.transform.localToWorldMatrix;
boneWeights[index].boneIndex0 = index;
boneWeights[index].weight0 = 1;
}
meshCreated.bindposes = bindPoses;
meshCreated.boneWeights = boneWeights;
skinned.sharedMesh = meshCreated;
skinned.bones = bones;
}
else
{
for (int index = 0; index < meshCreated.vertexCount; index++)
{
bones[index] = GetComponent<VerticalesMidifierGizmo>().transform;
bones[index].SetParent(this.transform);
bones[index].position = this.transform.TransformPoint(meshCreated.vertices[index]);
bindPoses[index] = bones[index].worldToLocalMatrix * this.transform.localToWorldMatrix;
boneWeights[index].boneIndex0 = index;
boneWeights[index].weight0 = 1;
}
}
}
private void Update()
{
vertices = meshCreated.vertices;
meshCreated.RecalculateBounds();
meshCreated.RecalculateNormals();
meshCreated.RecalculateTangents();
skinned.sharedMesh = meshCreated;
meshCollider.sharedMesh = skinned.sharedMesh;
}
}
public class BoneBuilder : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (GUILayout.Button("Create Bone from Verts"))
{
MakeBoneFromVerts();
}
}
[MenuItem("Bone Editor/Create Bone")]
public static void MakeBoneFromVerts()
{
if (Selection.gameObjects.Length == 0)
return;
GameObject go = new GameObject("Bone:SetPartName");
go.transform.parent = Selection.activeTransform.parent;
go.transform.position = new Vector3(0f, 0f, 0f);
foreach (GameObject g in Selection.gameObjects)
{
g.transform.parent = go.transform;
}
}
[MenuItem("Bone Editor/Add Vertecs")]
public static void MakeVertecsFromGO()
{
if (Selection.gameObjects.Length == 0)
return;
Selection.activeGameObject.AddComponent<BoneEditor>();
}
}
Thanks for the help :)
Answer by Bunny83 · Jun 23, 2019 at 05:03 PM
Where is the mesh you're editing actually stored? If you edit the built-in cube mesh you will directly modify the mesh in memory. However the built-in asset is read-only. So the actual asset is not changed (which wouldn't make any sense since you could completely destroy the default mesh, forever). So when restarting Unity it will load the mesh again from the internal asset.
If you want to edit / change a mesh in the editor and want those changes to persist in the editor, you have to save that mesh as an asset in your project. From your code it's hard to tell where the mesh is actually comming from. We can see this commented line:
//Mesh mesh = (Mesh)UnityEngine.Object.Instantiate(skinned.sharedMesh);
which assumes that in the past you probably instantiated the mesh before modifying it. This is the correct way if you try to manipulate a built-in mesh. However if you create a clone and modify it, you have to save it as asset. If you don't save the cloned mesh, the mesh instance will simply not exist after a restart and the reference to the mesh would be null.
Finally, be careful with "ExecuteInEditMode". You seem to abuse this attribute to add editor functionality to your game. However that's not what this attribute is meant for. It's meant to provide a certain runtime feature during edit time (an example would be a particle system which is playing during edit time). Any actual editor functionality should be implemented in an actual editor script.
Your answer
Follow this Question
Related Questions
How to manipulate(flatten) the Mesh of an object 0 Answers
Accessing mesh vertices is extremely inefficient; any workarounds? 0 Answers
Adding vertices to procedural mesh generator 2 Answers
Multiple Meshes 0 Answers
Handles does not modify mesh... 1 Answer