public static void MergeControllers(this AnimatorController source, params AnimatorController[] controllers) { if (string.IsNullOrWhiteSpace(AssetDatabase.GetAssetPath(source))) { throw new InvalidOperationException($"{source} must be persistent at the filesystem"); } var destLayers = new List <AnimatorControllerLayer>(); foreach (var controller in controllers) { foreach (var parameter in controller.parameters) { if (source.HasParameter(parameter.name)) { continue; } source.AddParameter(parameter.name, parameter.type); } if (controller.layers.Length == 0) { continue; } var layers = controller.layers; layers.First().defaultWeight = 1.0f; destLayers.AddRange(layers.Select(layer => layer.CloneDeep())); } if (destLayers.Select(w => w.name).Distinct().Count() != destLayers.Count) { foreach (var duplicate in destLayers.Duplicate(w => w.name)) { var count = 1; var index = destLayers.Select((w, i) => (Value: w, Index: w)).Where(w => w.Value.name == duplicate).ToList(); foreach (var(layer, i) in index) { layer.name = $"{layer.name} - {count++}"; } } } source.layers = destLayers.ToArray(); // add instances to controller foreach (var stateMachine in destLayers.Select(w => w.stateMachine).Where(w => w != null)) { AssetDatabase.AddObjectToAsset(stateMachine, source); } foreach (var state in InstanceCache <AnimatorState> .Caches) { AssetDatabase.AddObjectToAsset(state, source); } foreach (var stateMachine in InstanceCache <AnimatorStateMachine> .Caches) { AssetDatabase.AddObjectToAsset(stateMachine, source); } foreach (var transition in InstanceCache <AnimatorStateTransition> .Caches) { AssetDatabase.AddObjectToAsset(transition, source); } foreach (var behaviour in InstanceCache <StateMachineBehaviour> .Caches) { AssetDatabase.AddObjectToAsset(behaviour, source); } // Cleanup All Caches InstanceCache <AnimatorState> .Clear(); InstanceCache <AnimatorStateMachine> .Clear(); InstanceCache <AnimatorStateTransition> .Clear(); InstanceCache <StateMachineBehaviour> .Clear(); }
public static AnimatorState CloneDeep(this AnimatorState source) { var dest = new AnimatorState { cycleOffset = source.cycleOffset, cycleOffsetParameter = source.cycleOffsetParameter, cycleOffsetParameterActive = source.cycleOffsetParameterActive, iKOnFeet = source.iKOnFeet, mirror = source.mirror, mirrorParameter = source.mirrorParameter, mirrorParameterActive = source.mirrorParameterActive, motion = source.motion, speed = source.speed, speedParameter = source.speedParameter, speedParameterActive = source.speedParameterActive, tag = source.tag, timeParameter = source.timeParameter, timeParameterActive = source.timeParameterActive, writeDefaultValues = source.writeDefaultValues, name = source.name, hideFlags = source.hideFlags }; foreach (var sourceTransition in source.transitions.Where(w => w.isExit)) { var transition = dest.AddExitTransition(false); sourceTransition.ApplyTo(transition); InstanceCache <AnimatorStateTransition> .SafeRegister(sourceTransition.GetInstanceID(), transition); } foreach (var sourceTransition in source.transitions.Where(w => !w.isExit)) { AnimatorStateTransition transition = null; if (sourceTransition.destinationStateMachine != null) { transition = dest.AddTransition(InstanceCache <AnimatorStateMachine> .FindOrCreate(sourceTransition.destinationStateMachine, w => w.CloneDeep())); } if (sourceTransition.destinationState != null) { transition = dest.AddTransition(InstanceCache <AnimatorState> .FindOrCreate(sourceTransition.destinationState, w => w.CloneDeep())); } if (transition == null) { throw new ArgumentNullException(nameof(transition)); } sourceTransition.ApplyTo(transition); InstanceCache <AnimatorStateTransition> .SafeRegister(sourceTransition.GetInstanceID(), transition); } foreach (var sourceBehaviour in source.behaviours) { var behaviour = dest.AddStateMachineBehaviour(sourceBehaviour.GetType()); sourceBehaviour.ApplyTo(behaviour); InstanceCache <StateMachineBehaviour> .SafeRegister(behaviour.GetInstanceID(), behaviour); } return(dest); }
public static AnimatorStateMachine CloneDeep(this AnimatorStateMachine source) { var dest = new AnimatorStateMachine { defaultState = InstanceCache <AnimatorState> .FindOrCreate(source.defaultState, w => w.CloneDeep()), anyStatePosition = source.anyStatePosition, entryPosition = source.entryPosition, exitPosition = source.exitPosition, parentStateMachinePosition = source.parentStateMachinePosition, hideFlags = source.hideFlags, name = source.name }; foreach (var sourceState in source.states) { dest.AddState(InstanceCache <AnimatorState> .FindOrCreate(sourceState.state, w => w.CloneDeep()), sourceState.position); } foreach (var sourceTransition in source.anyStateTransitions) { AnimatorStateTransition transition = null; if (sourceTransition.destinationStateMachine != null) { transition = dest.AddAnyStateTransition(InstanceCache <AnimatorStateMachine> .FindOrCreate(sourceTransition.destinationStateMachine, w => w.CloneDeep())); } if (sourceTransition.destinationState != null) { transition = dest.AddAnyStateTransition(InstanceCache <AnimatorState> .FindOrCreate(sourceTransition.destinationState, w => w.CloneDeep())); } if (transition == null) { throw new ArgumentNullException(nameof(transition)); } sourceTransition.ApplyTo(transition); InstanceCache <AnimatorStateTransition> .SafeRegister(sourceTransition.GetInstanceID(), transition); } foreach (var sourceTransition in source.entryTransitions) { AnimatorTransition transition = null; if (sourceTransition.destinationStateMachine != null) { transition = dest.AddEntryTransition(InstanceCache <AnimatorStateMachine> .FindOrCreate(sourceTransition.destinationStateMachine, w => w.CloneDeep())); } if (sourceTransition.destinationState != null) { transition = dest.AddEntryTransition(InstanceCache <AnimatorState> .FindOrCreate(sourceTransition.destinationState, w => w.CloneDeep())); } if (transition == null) { throw new ArgumentNullException(nameof(transition)); } sourceTransition.ApplyTo(transition); InstanceCache <AnimatorTransition> .SafeRegister(sourceTransition.GetInstanceID(), transition); } foreach (var sourceBehaviour in source.behaviours) { var behaviour = dest.AddStateMachineBehaviour(sourceBehaviour.GetType()); sourceBehaviour.ApplyTo(behaviour); InstanceCache <StateMachineBehaviour> .SafeRegister(behaviour.GetInstanceID(), behaviour); } foreach (var sourceStateMachine in source.stateMachines) { dest.AddStateMachine(InstanceCache <AnimatorStateMachine> .FindOrCreate(sourceStateMachine.stateMachine, w => w.CloneDeep()), sourceStateMachine.position); } return(dest); }