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();
        }
示例#2
0
        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);
        }