Example #1
0
        /// <summary>
        /// Create state machine info for a given type
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static StateMachineInfo Create(Type type)
        {
            if (_cache.TryGetValue(type, out var info))
            {
                return(info);
            }

            // Collect all info from the type
            var states      = new List <StateInfo>();
            var triggers    = new List <StateTriggerInfo>();
            var transitions = new List <StateTransitionInfo>();

            GetInfo(type, states, triggers, transitions);

            // Validate that all the states referenced were found
            foreach (var state in states)
            {
                GetStateDelegate(state, type);
            }

            info             = new StateMachineInfo();
            info.TargetType  = type;
            info.States      = states.ToArray();
            info.Triggers    = triggers.ToArray();
            info.Transitions = transitions.ToArray();
            return(info);
        }
Example #2
0
        /// <summary>
        /// Start a new state machine on the given target using the given initial state
        /// </summary>
        public static void Start(Object target, string initialState, string key, UpdateMode mode)
        {
            var sm = _stateMachinePool.Get();

            sm._sminfo             = StateMachineInfo.Create(target.GetType());
            sm._key                = key;
            sm._target             = target;
            sm._updateMode         = mode;
            sm._elapsedTimeInState = 0.0f;

            // Track all running state machines
            _stateMachines.Add(sm);

            // Set the initial state
            sm.SetState(initialState);
        }
Example #3
0
        /// <summary>
        /// Attempt to add a transition to the given transitions list
        /// </summary>
        private static StateTransitionInfo CreateTransition(StateMachineInfo info, StateInfo from, StateInfo to)
        {
            if (from == to)
            {
                return(null);
            }

            // Check for the transition method
            var methodInfo = info.TargetType.GetMethod(
                $"On{from?.Name??"Any"}To{to?.Name??"Any"}",
                BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

            if (methodInfo == null)
            {
                return(null);
            }

            return(new StateTransitionInfo
            {
                From = from,
                To = to,
                InvokeDelegate = OpenDelegate.Create(methodInfo)
            });
        }
Example #4
0
        /// <summary>
        /// Create state machine info for a given type
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static StateMachineInfo Create(Type type, Type statesType)
        {
            var typeName = type.FullName;

            if (_cache.TryGetValue(typeName, out var info))
            {
                return(info);
            }

            var values = Enum.GetValues(statesType);
            var states = new StateInfo[values.Length];

            foreach (var value in values)
            {
                var index = (int)value;
                var name  = value.ToString();

                if (index < 0 || index >= states.Length)
                {
                    throw new UnityException("State enum must be sequential and start from zero");
                }

                states[index] = new StateInfo {
                    Name = value.ToString(), Mask = (1UL << index), Index = index
                };
            }

            // Create a new state machine info
            info                   = new StateMachineInfo();
            info.TargetType        = type;
            info.States            = states;
            info._transitionStride = states.Length + 1;
            _cache.Add(typeName, info);

            // Get state method and transitions
            info._transitions = new StateTransitionInfo[states.Length * info._transitionStride];
            foreach (var stateToInfo in states)
            {
                // State method?
                var stateMethod = type.GetMethod($"On{stateToInfo.Name}", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                if (null != stateMethod)
                {
                    var parameters = stateMethod.GetParameters();
                    if (parameters.Length == 0)
                    {
                        stateToInfo.InvokeDelegate = OpenDelegate.Create(stateMethod);
                    }
                    else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(float))
                    {
                        stateToInfo.InvokeWithTimeDelegate = OpenDelegate <float> .Create(stateMethod);
                    }
                    else
                    {
                        throw new UnityException($"method for state '{stateToInfo.Name}' does not match a valid state signature");
                    }
                }

                // Add the "Any" to state transition
                info._transitions[info.GetTransitionIndex(-1, stateToInfo.Index)] = CreateTransition(info, null, stateToInfo);

                // Add transition from all other states
                foreach (var stateFromInfo in states)
                {
                    info._transitions[info.GetTransitionIndex(stateFromInfo.Index, stateToInfo.Index)] =
                        CreateTransition(info, stateFromInfo, stateToInfo);
                }
            }

            return(info);
        }