using UnityEditor;
using UnityEngine;
public static class RemoveBlendShapesByPrefix
{
// 削除したい先頭文字列。大文字小文字は無視します。
private static readonly string[] RemovePrefixes =
{
"tongue",
"brow",
"shrink",
"mouth",
"tooth",
"pupil",
"eye_under",
"eyebrow",
};
[MenuItem("Tools/Avatar/Remove BlendShapes By Prefix From Selected")]
private static void Remove()
{
var go = Selection.activeGameObject;
if (go == null)
{
Debug.LogError("SkinnedMeshRenderer が付いたオブジェクトを選択してください。");
return;
}
var smr = go.GetComponent<SkinnedMeshRenderer>();
if (smr == null || smr.sharedMesh == null)
{
Debug.LogError("選択中オブジェクトに SkinnedMeshRenderer / sharedMesh がありません。");
return;
}
var src = smr.sharedMesh;
var dst = Object.Instantiate(src);
dst.name = src.name + "_RemovedSelectedBlendShapes";
int vertexCount = src.vertexCount;
var deltaVertices = new Vector3[vertexCount];
var deltaNormals = new Vector3[vertexCount];
var deltaTangents = new Vector3[vertexCount];
dst.ClearBlendShapes();
int kept = 0;
int removed = 0;
for (int shapeIndex = 0; shapeIndex < src.blendShapeCount; shapeIndex++)
{
string shapeName = src.GetBlendShapeName(shapeIndex);
if (ShouldRemove(shapeName))
{
Debug.Log($"Remove BlendShape: {shapeName}");
removed++;
continue;
}
int frameCount = src.GetBlendShapeFrameCount(shapeIndex);
for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
{
float frameWeight = src.GetBlendShapeFrameWeight(shapeIndex, frameIndex);
src.GetBlendShapeFrameVertices(
shapeIndex,
frameIndex,
deltaVertices,
deltaNormals,
deltaTangents
);
dst.AddBlendShapeFrame(
shapeName,
frameWeight,
deltaVertices,
deltaNormals,
deltaTangents
);
}
kept++;
}
string path = EditorUtility.SaveFilePanelInProject(
"Save Mesh Without Selected BlendShapes",
dst.name + ".asset",
"asset",
"保存先を選んでください"
);
if (string.IsNullOrEmpty(path))
{
Object.DestroyImmediate(dst);
return;
}
AssetDatabase.CreateAsset(dst, path);
AssetDatabase.SaveAssets();
Undo.RecordObject(smr, "Remove BlendShapes By Prefix");
smr.sharedMesh = dst;
EditorUtility.SetDirty(smr);
Debug.Log($"BlendShape削除完了: mesh={src.name}, kept={kept}, removed={removed}, before={src.blendShapeCount}, after={dst.blendShapeCount}");
Debug.Log($"Saved: {path}");
}
private static bool ShouldRemove(string shapeName)
{
string lower = shapeName.ToLowerInvariant();
foreach (string prefix in RemovePrefixes)
{
if (lower.StartsWith(prefix.ToLowerInvariant()))
{
return true;
}
}
return false;
}
}