Skip to content

Instantly share code, notes, and snippets.

@Invertex
Last active January 23, 2024 13:48
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Invertex/21d1ede1d5fa722afbfa6c36ce37d411 to your computer and use it in GitHub Desktop.
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.
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