Last active
April 18, 2025 16:17
-
-
Save Invertex/21d1ede1d5fa722afbfa6c36ce37d411 to your computer and use it in GitHub Desktop.
Automatically creates and applies a full mask to all clips in a Humanoid rig so that all parts of the animation are maintained.
This file contains hidden or 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 UnityEngine; | |
using UnityEditor; | |
using System.Linq; | |
namespace Invertex.Unity.Editor.Importing | |
{ | |
/// <summary> | |
/// This script will automatically generate an AvatarMask that will enable a Humanoid animation to animate all parts of your asset. | |
/// It will assign it to every clip in a new asset or every existing clip on an asset. | |
/// USAGE: Place in an "Editor" folder somewhere in your assets. | |
/// Replace the values of 'restrictToPathsContaining' with the paths you want to restrict this script to (or make it just a single "" to do project wide, but not advised.) | |
/// </summary> | |
public class AutoMaskHumanoidRigsProcessor : AssetPostprocessor | |
{ | |
//Change this to the path you want to restrict this script to. | |
//Ideally the name of the folder that has your custom animations | |
private static readonly string[] restrictToPathsContaining = { "_Game/Characters/", "/SomeOtherLocation/" }; | |
private static bool forceHumanoid = true; //Force new models to import as Humanoid | |
void OnPostprocessModel(GameObject g) | |
{ | |
ModelImporter modelImporter = (assetImporter as ModelImporter); | |
if (modelImporter == null | |
|| !restrictToPathsContaining.Any((restrictPath) => assetPath.Contains(restrictPath)) | |
|| !modelImporter.importAnimation) { return; } | |
if(modelImporter.animationType != ModelImporterAnimationType.Human) | |
{ | |
if(modelImporter.importSettingsMissing && forceHumanoid) { modelImporter.animationType = ModelImporterAnimationType.Human; } | |
else { return; } | |
} | |
ModelImporterClipAnimation[] clipAnimations = modelImporter.clipAnimations; | |
//If clipAnimations is 0, no changes to animations have been made yet, import the default clips | |
if(clipAnimations.Length == 0) { clipAnimations = modelImporter.defaultClipAnimations; } | |
//Create a single Mask for all the Humanoid animations to reference instead of wasting space with a new mask for each | |
var mask = new AvatarMask() { name = $"{g.name}_Mask_All"}; | |
mask.AddTransformPath(g.transform); | |
//Store it in the asset so we don't lose reference to it | |
context.AddObjectToAsset(mask.GetHashCode().ToString(), mask); | |
for (int i = 0; i < clipAnimations.Length; i++) | |
{ | |
var clip = clipAnimations[i]; | |
clip.maskType = ClipAnimationMaskType.CopyFromOther; | |
clip.maskSource = mask; | |
} | |
modelImporter.clipAnimations = clipAnimations; //In case we're working on the default array, assign it back | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment