Last active
December 22, 2023 23:31
-
-
Save kiosion/9cac71f965fc560e1342724005a59d87 to your computer and use it in GitHub Desktop.
Unity script to reassign mesh weights to new armature
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEngine; | |
using UnityEditor; | |
public class ArmatureAssignment: EditorWindow | |
{ | |
private int MeshCount = 1; | |
private List<SkinnedMeshRenderer> Meshes = new List<SkinnedMeshRenderer>(); | |
private Transform NewArmature; | |
private bool IncludeInactiveBones = true; | |
private bool ContinueOnMissingBones = true; | |
private string RootBoneName = "Hips"; | |
private string Status = "Waiting for input"; | |
[MenuItem("Kio/ArmatureAssignment")] | |
static void Init() | |
{ | |
ArmatureAssignment window = EditorWindow.GetWindow(typeof(ArmatureAssignment)) as ArmatureAssignment; | |
window?.Show(); | |
} | |
void OnGUI() | |
{ | |
GUILayout.Label("Reassign mesh bones to the selected Armature (Create a backup first!)"); | |
GUILayout.Box("", new GUILayoutOption[] { GUILayout.ExpandWidth(true), GUILayout.Height(1) }); | |
this.MeshCount = EditorGUILayout.IntField("Mesh Count ", this.MeshCount); | |
while (this.MeshCount > this.Meshes.Count) | |
{ | |
this.Meshes.Add(null); | |
} | |
while (this.MeshCount < this.Meshes.Count) | |
{ | |
this.Meshes.RemoveAt(this.Meshes.Count - 1); | |
} | |
for (int i = 0; i < this.MeshCount; ++i) | |
{ | |
this.Meshes[i] = EditorGUILayout.ObjectField($"Mesh {i}", this.Meshes[i], typeof(SkinnedMeshRenderer), true) as SkinnedMeshRenderer; | |
} | |
this.NewArmature = EditorGUILayout.ObjectField("New Armature", this.NewArmature, typeof(Transform), true) as Transform; | |
this.RootBoneName = EditorGUILayout.TextField("Root Bone Name", this.RootBoneName); | |
this.IncludeInactiveBones = EditorGUILayout.Toggle("Include inactive bones", this.IncludeInactiveBones); | |
this.ContinueOnMissingBones = EditorGUILayout.Toggle("Continue on missing bones", this.ContinueOnMissingBones); | |
if (GUILayout.Button("Execute")) | |
{ | |
if (this.NewArmature != null && this.Meshes != null && !string.IsNullOrWhiteSpace(this.RootBoneName)) | |
{ | |
this.Status = "OK"; | |
for (int i = 0; i < this.MeshCount; ++i) | |
{ | |
Reassign(this.Meshes[i]); | |
} | |
if (this.Status == "OK") | |
{ | |
this.Status = "Done"; | |
} | |
} | |
else | |
{ | |
this.Status = "Missing arguments"; | |
} | |
NewArmature = null; | |
} | |
EditorGUILayout.Separator(); | |
EditorGUILayout.TextField("Status", this.Status); | |
} | |
private void Reassign(SkinnedMeshRenderer mesh) | |
{ | |
if (this.NewArmature.Find(this.RootBoneName) == null) | |
{ | |
this.Status = "Root bone not found"; | |
return; | |
} | |
bool hasMissingBones = false; | |
Transform originalRootBone = mesh.rootBone; | |
Transform[] originalBones = mesh.bones; | |
Transform[] newBones = mesh.bones; | |
Transform[] children = this.NewArmature.GetComponentsInChildren<Transform>(this.IncludeInactiveBones); | |
mesh.rootBone = this.NewArmature.Find(this.RootBoneName); | |
for (int i = 0; i < newBones.Length; ++i) | |
{ | |
Transform foundBone = children.FirstOrDefault(c => c.name == newBones[i].name); | |
if (foundBone == null) | |
{ | |
hasMissingBones = true; | |
if (!this.ContinueOnMissingBones) | |
{ | |
Debug.LogError($"Bone {newBones[i].name} not found in new armature, aborting"); | |
return; | |
} | |
Debug.LogWarning($"Bone {newBones[i].name} not found in new armature, removing from mesh"); | |
newBones[i] = null; | |
} | |
newBones[i] = foundBone; | |
} | |
if (hasMissingBones && !this.ContinueOnMissingBones) | |
{ | |
this.Status = "Bone not found"; | |
mesh.bones = originalBones; | |
mesh.rootBone = originalRootBone; | |
return; | |
} | |
mesh.bones = newBones; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment