Skip to content

Instantly share code, notes, and snippets.

@StagPoint
Created December 5, 2021 18:50
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StagPoint/2e6ced25f91246c5b95f23537704b3c0 to your computer and use it in GitHub Desktop.
Save StagPoint/2e6ced25f91246c5b95f23537704b3c0 to your computer and use it in GitHub Desktop.
Unity editor script that adds existing AnimationClip assets to the AnimationController asset that uses them, cutting down on clutter and making it easier to manage your controllers and their associated animation clips.
namespace StagPoint.EditorUtils
{
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;
/// <summary>
/// Adds existing AnimationClip assets to an existing AnimationController asset that uses them.
/// To use, select the animations and controller in the Project window, right click and select "Add Animations To Controller".
/// Each AnimationClip asset that has a corresponding State in the AnimatorController will be added to the Controller asset.
/// </summary>
public static class AddAnimationClipsToControllerAsset
{
[MenuItem( "Assets/Add Animation Clips To Controller", validate = true )]
public static bool ValidateProcessSelection()
{
var selectionCount = Selection.objects.Length;
if( selectionCount < 2 )
{
return false;
}
var hasSingleAnimatorControllerSelected = Selection.objects.Count( x => x is AnimatorController ) == 1;
var restOfSelectionsAreAnimationClips = Selection.objects.Count( x => x is AnimationClip ) == selectionCount - 1;
return hasSingleAnimatorControllerSelected && restOfSelectionsAreAnimationClips;
}
[MenuItem( "Assets/Add Animation Clips To Controller" )]
public static void ProcessSelection()
{
var controller = Selection.objects.First( x => x is AnimatorController ) as AnimatorController;
var stateMachine = controller.layers[ 0 ].stateMachine;
var states = stateMachine.states.Select( x => x.state ).ToArray();
var controllerPath = AssetDatabase.GetAssetPath( controller );
foreach( var obj in Selection.objects )
{
if( obj is AnimationClip && obj != controller )
{
var originalClip = obj as AnimationClip;
var state = states.FirstOrDefault( x => x.motion == originalClip );
if( state == null )
{
Debug.LogWarning( $"Could not find a state corresponding to clip '{obj.name}'. Skipping." );
continue;
}
Debug.Log( $"State '{state.name}' uses animation clip '{obj.name}'. Adding it to '{controllerPath}'" );
// For some reason I'm unable to directly add the AnimationClip to the AnimatorController, but creating
// a clone (and replacing the reference in the State) works just fine.
var newClip = (AnimationClip)AnimationClip.Instantiate( obj );
newClip.name = obj.name;
state.motion = newClip;
// Delete the original AnimationClip.
AssetDatabase.DeleteAsset( AssetDatabase.GetAssetPath( obj ) );
AssetDatabase.AddObjectToAsset( newClip, controllerPath );
}
}
EditorUtility.SetDirty( controller );
AssetDatabase.SaveAssets();
AssetDatabase.ImportAsset( controllerPath );
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment