This commit is contained in:
Adam Ramberg 2020-03-12 01:30:25 +01:00
parent 68ac1850c6
commit e6ac211e70
21 changed files with 343 additions and 243 deletions

View File

@ -22,70 +22,72 @@ MonoBehaviour:
_transitionStarted: {fileID: 0}
_completeCurrentTransition: {fileID: 0}
_states:
- _id:
_usage: 0
_value: CHASING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_cooldown:
_usage: 0
_value: 0
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_subMachine: {fileID: 0}
- _id:
_usage: 0
_value: ATTACKING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_cooldown:
_usage: 0
_value: 2
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_subMachine: {fileID: 0}
_list:
- _id:
_usage: 0
_value: CHASING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_cooldown:
_usage: 0
_value: 0
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_subMachine: {fileID: 0}
- _id:
_usage: 0
_value: ATTACKING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_cooldown:
_usage: 0
_value: 2
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_subMachine: {fileID: 0}
_transitions:
- _fromState:
_usage: 0
_value: ATTACKING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_toState:
_usage: 0
_value: CHASING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_command:
_usage: 0
_value: CHASE
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_testCondition: {fileID: 0}
_raiseEventToCompleteTransition: 0
- _fromState:
_usage: 0
_value: CHASING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_toState:
_usage: 0
_value: ATTACKING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_command:
_usage: 0
_value: ATTACK
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_testCondition: {fileID: 0}
_raiseEventToCompleteTransition: 0
_list:
- _fromState:
_usage: 0
_value: CHASING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_toState:
_usage: 0
_value: ATTACKING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_command:
_usage: 0
_value: ATTACK
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_testCondition: {fileID: 0}
_raiseEventToCompleteTransition: 0
- _fromState:
_usage: 0
_value: ATTACKING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_toState:
_usage: 0
_value: CHASING
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_command:
_usage: 0
_value: CHASE
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_testCondition: {fileID: 0}
_raiseEventToCompleteTransition: 0

View File

@ -13,59 +13,15 @@ MonoBehaviour:
m_Name: GameStateMachine
m_EditorClassIdentifier:
_developerDescription:
_value: InGame
_initialValue: InGame
_oldValue: InGame
_value:
_initialValue:
_oldValue:
Changed: {fileID: 11400000, guid: 3979f8535cda044809f98bde2acbadcd, type: 2}
ChangedWithHistory: {fileID: 0}
_preChangeTransformers: []
_transitionStarted: {fileID: 0}
_completeCurrentTransition: {fileID: 0}
_states:
- _id:
_usage: 0
_value: InGame
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_cooldown:
_usage: 0
_value: 0
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_subMachine: {fileID: 0}
- _id:
_usage: 0
_value: GameOver
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_cooldown:
_usage: 0
_value: 0
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_subMachine: {fileID: 0}
_list: []
_transitions:
- _fromState:
_usage: 0
_value: InGame
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_toState:
_usage: 0
_value: GameOver
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_command:
_usage: 0
_value: SetGameOver
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
_testCondition: {fileID: 0}
_raiseEventToCompleteTransition: 0
_list: []

View File

@ -1226,88 +1226,6 @@ MonoBehaviour:
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
--- !u!1 &1740680898 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 2421445419809145576, guid: 1326bc3a5a491414d936c2cbaaf52c53,
type: 3}
m_PrefabInstance: {fileID: 2421445420392131626}
m_PrefabAsset: {fileID: 0}
--- !u!114 &1740680904 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 2421445419809145570, guid: 1326bc3a5a491414d936c2cbaaf52c53,
type: 3}
m_PrefabInstance: {fileID: 2421445420392131626}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1740680898}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4c23750724dd48beb6147120ab31180, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &1740680906 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: -2978108162882953924, guid: 1326bc3a5a491414d936c2cbaaf52c53,
type: 3}
m_PrefabInstance: {fileID: 2421445420392131626}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1740680898}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: adacd19b642ba4bd9866612e37971b00, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &1740680909
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1740680898}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6a57cc968d2764ec0bc2de2bd308d451, type: 3}
m_Name:
m_EditorClassIdentifier:
_delay:
_usage: 0
_value: -1
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
--- !u!114 &1740680910
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1740680898}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 050ff37b5550f4b7e9bdf8b985aff484, type: 3}
m_Name:
m_EditorClassIdentifier:
_developerDescription:
_unityEventResponse:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 1740680909}
m_MethodName: DestroyImmediate
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
_actionResponses: []
_eventReference:
_usage: 3
_event: {fileID: 0}
_eventInstancer: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 1740680906}
--- !u!1001 &2421445420392131626
PrefabInstance:
m_ObjectHideFlags: 0
@ -1315,16 +1233,6 @@ PrefabInstance:
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 2421445419809145569, guid: 1326bc3a5a491414d936c2cbaaf52c53,
type: 3}
propertyPath: _enemyState._fsmInstancer
value:
objectReference: {fileID: 1740680904}
- target: {fileID: 2421445419809145569, guid: 1326bc3a5a491414d936c2cbaaf52c53,
type: 3}
propertyPath: _enemyState._usage
value: 1
objectReference: {fileID: 0}
- target: {fileID: 2421445419809145576, guid: 1326bc3a5a491414d936c2cbaaf52c53,
type: 3}
propertyPath: m_Name
@ -1385,11 +1293,6 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2421445419809145581, guid: 1326bc3a5a491414d936c2cbaaf52c53,
type: 3}
propertyPath: _enemyState._fsmInstancer
value:
objectReference: {fileID: 1740680904}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 1326bc3a5a491414d936c2cbaaf52c53, type: 3}
--- !u!1001 &7203441229205008813

View File

@ -1,5 +1,3 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityAtoms.Editor;
@ -9,8 +7,9 @@ namespace UnityAtoms.BaseAtoms.Editor
/// <summary>
/// A custom property drawer for AtomBaseVariableList.
/// </summary>
[CustomPropertyDrawer(typeof(AtomListAttribute))]
[CustomPropertyDrawer(typeof(AtomBaseVariableList))]
public class AtomBaseVariableListDrawer : PropertyDrawer
public class AtomListDrawer : PropertyDrawer
{
static int INDEX_LABEL_WIDTH = 16;
static int BUTTON_WIDTH = 24;
@ -24,8 +23,10 @@ namespace UnityAtoms.BaseAtoms.Editor
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
AtomListAttribute atomListAttr = attribute as AtomListAttribute;
var propertyHeight = EditorGUIUtility.singleLineHeight + LINE_BOTTOM_MARGIN + DRAWER_MARGIN * 2f;
var listProperty = property.FindPropertyRelative(SERIALIZED_LIST_PROPNAME);
var listProperty = property.FindPropertyRelative(atomListAttr != null && !string.IsNullOrWhiteSpace(atomListAttr.ChildPropName) ? atomListAttr.ChildPropName : SERIALIZED_LIST_PROPNAME);
var length = listProperty.arraySize;
for (var i = 0; i < length; ++i)
@ -40,6 +41,8 @@ namespace UnityAtoms.BaseAtoms.Editor
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
AtomListAttribute atomListAttr = attribute as AtomListAttribute;
label = EditorGUI.BeginProperty(position, label, property);
var proColor = new Color(83f / 255f, 83f / 255f, 83f / 255f);
var basicColor = new Color(174f / 255f, 174f / 255f, 174f / 255f);
@ -49,7 +52,7 @@ namespace UnityAtoms.BaseAtoms.Editor
EditorGUI.indentLevel = 0;
EditorGUI.BeginChangeCheck();
var listArrayProperty = property.FindPropertyRelative(SERIALIZED_LIST_PROPNAME);
var listArrayProperty = property.FindPropertyRelative(atomListAttr != null && !string.IsNullOrWhiteSpace(atomListAttr.ChildPropName) ? atomListAttr.ChildPropName : SERIALIZED_LIST_PROPNAME);
var restRect = new Rect();
var initialPosition = new Rect(position);
@ -59,7 +62,7 @@ namespace UnityAtoms.BaseAtoms.Editor
var labelPosition = IMGUIUtils.SnipRectH(initialPosition, initialPosition.width - BUTTON_WIDTH, out restRect);
labelPosition.height = EditorGUIUtility.singleLineHeight + LINE_BOTTOM_MARGIN;
EditorGUI.PrefixLabel(initialPosition, new GUIContent(LIST_LABEL_NAME));
EditorGUI.PrefixLabel(initialPosition, new GUIContent(atomListAttr != null ? (atomListAttr.Label ?? label.text) : LIST_LABEL_NAME));
var addButtonPosition = IMGUIUtils.SnipRectH(restRect, restRect.width, out restRect);
addButtonPosition.height = EditorGUIUtility.singleLineHeight;
@ -83,7 +86,7 @@ namespace UnityAtoms.BaseAtoms.Editor
EditorGUI.PrefixLabel(indexLabelPos, new GUIContent(i.ToString()));
var itemPos = IMGUIUtils.SnipRectH(restRect, linePosition.width - BUTTON_WIDTH - INDEX_LABEL_WIDTH - GUTTER * 2, out restRect, GUTTER);
EditorGUI.PropertyField(itemPos, itemProp, GUIContent.none, false);
EditorGUI.PropertyField(itemPos, itemProp, GUIContent.none, atomListAttr != null ? atomListAttr.IncludeChildrenForItems : false);
var removeButtonPosition = new Rect(restRect);
removeButtonPosition.height = EditorGUIUtility.singleLineHeight;
@ -93,7 +96,7 @@ namespace UnityAtoms.BaseAtoms.Editor
indexToDelete = i;
}
linePosition.y += EditorGUIUtility.singleLineHeight + LINE_BOTTOM_MARGIN;
linePosition.y += EditorGUI.GetPropertyHeight(itemProp) + LINE_BOTTOM_MARGIN;
}
if (insertIndex != -1)
@ -101,6 +104,8 @@ namespace UnityAtoms.BaseAtoms.Editor
if (listArrayProperty != null)
{
listArrayProperty.InsertArrayElementAtIndex(insertIndex);
var newProp = listArrayProperty.GetArrayElementAtIndex(insertIndex);
newProp.isExpanded = true;
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 01e2d4c866bf1461f99e3ffd89dc8882
guid: d0d49408cf0e24375a9b017fc4210a94
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 93604d20e8e8f4a7da3af79e4303a48f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
using System.Collections.Generic;
using UnityEngine;
namespace UnityAtoms.BaseAtoms
{
/// <summary>
/// Needed in order to create a property drawer for a List / Array. See this for more info: https://answers.unity.com/questions/605875/custompropertydrawer-for-array-types-in-43.html
/// </summary>
/// <typeparam name="T">Type used in list.</typeparam>
public abstract class AtomListWrapper<T>
{
public List<T> List { get => _list; }
[SerializeField]
private List<T> _list;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cbf386e8976ba4aeebf2c157c511166f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ed96ad5d334a847438fd3f164b941c3f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
using UnityEngine;
namespace UnityAtoms.BaseAtoms
{
public class AtomListAttribute : PropertyAttribute
{
public string Label { get; set; }
public string ChildPropName { get; set; }
public bool IncludeChildrenForItems { get; set; }
public AtomListAttribute(string label = null, string childPropName = "_list", bool includeChildrenForItems = true)
{
Label = label;
ChildPropName = childPropName;
IncludeChildrenForItems = includeChildrenForItems;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c9cdeac56b0004a4c88add9ed1f3d6a7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -67,7 +67,7 @@ namespace UnityAtoms.Editor
GUILayout.Space(2);
if (GUILayout.Button("Raise", GUILayout.Width(raiseButtonWidth), GUILayout.Height(EditorGUIUtility.singleLineHeight)))
{
evt.GetType().GetMethod("Raise", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { atomTarget.BaseValue });
evt.GetType().GetMethod("RaiseEditor", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { atomTarget.BaseValue });
}
}
@ -85,7 +85,7 @@ namespace UnityAtoms.Editor
{
var oldValueProp = serializedObject.FindProperty("_oldValue");
object oldValue = oldValueProp.GetPropertyValue();
evt.GetType().GetMethod("Raise", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { (object)(new P() { Item1 = (T)atomTarget.BaseValue, Item2 = (T)oldValue }) });
evt.GetType().GetMethod("RaiseEditor", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { (object)(new P() { Item1 = (T)atomTarget.BaseValue, Item2 = (T)oldValue }) });
}
}

View File

@ -66,6 +66,12 @@ namespace UnityAtoms
AddToReplayBuffer(item);
}
/// <summary>
/// Used in editor scipts since Raise is ambigious when using reflection to get method.
/// </summary>
/// <param name="item"></param>
public void RaiseEditor(T item) => Raise(item);
/// <summary>
/// Register handler to be called when the Event triggers.
/// </summary>

View File

@ -16,6 +16,12 @@ namespace UnityAtoms
return default(T);
}
public static bool Exists<T>(this IList<T> list, Func<T, bool> func)
{
var first = list.First<T>(func);
return first != null ? true : false;
}
public static GameObject GetOrInstantiate(this IList<GameObject> list, UnityEngine.Object prefab, Vector3 position, Quaternion quaternion, Func<GameObject, bool> condition)
{
var component = list.First(condition);

View File

@ -0,0 +1,81 @@
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityAtoms.Editor;
using UnityAtoms.BaseAtoms;
namespace UnityAtoms.FSM.Editor
{
/// <summary>
/// Custom property drawer for type `FiniteStateMachine`.
/// </summary>
[CustomEditor(typeof(FiniteStateMachine))]
public sealed class FiniteStateMachineEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(serializedObject.FindProperty("_developerDescription"));
EditorGUILayout.Space();
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.PropertyField(serializedObject.FindProperty("_initialValue"), true);
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.PropertyField(serializedObject.FindProperty("_value"), true);
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.PropertyField(serializedObject.FindProperty("_oldValue"), true);
EditorGUI.EndDisabledGroup();
const int raiseButtonWidth = 52;
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("Changed"));
var changed = serializedObject.FindProperty("Changed").objectReferenceValue;
if (changed != null && changed is AtomEventBase evt && target is AtomBaseVariable atomTarget)
{
GUILayout.Space(2);
if (GUILayout.Button("Raise", GUILayout.Width(raiseButtonWidth), GUILayout.Height(EditorGUIUtility.singleLineHeight)))
{
evt.GetType().GetMethod("RaiseEditor", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { atomTarget.BaseValue });
}
}
}
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("ChangedWithHistory"));
var changedWithHistory = serializedObject.FindProperty("ChangedWithHistory").objectReferenceValue;
if (changedWithHistory != null && changedWithHistory is AtomEventBase evt && target is AtomBaseVariable atomTarget)
{
GUILayout.Space(2);
if (GUILayout.Button("Raise", GUILayout.Width(raiseButtonWidth), GUILayout.Height(EditorGUIUtility.singleLineHeight)))
{
var oldValueProp = serializedObject.FindProperty("_oldValue");
object oldValue = oldValueProp.GetPropertyValue();
evt.GetType().GetMethod("RaiseEditor", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { (object)(new StringPair() { Item1 = (string)atomTarget.BaseValue, Item2 = (string)oldValue }) });
}
}
}
var transitionStartedProp = serializedObject.FindProperty("_transitionStarted");
EditorGUILayout.PropertyField(transitionStartedProp, new GUIContent() { tooltip = "Event raised when a transition is started.", text = transitionStartedProp.displayName }, true);
var completeCurrentTransitionProp = serializedObject.FindProperty("_completeCurrentTransition");
EditorGUILayout.PropertyField(completeCurrentTransitionProp, new GUIContent() { tooltip = "A Bool Event that is passed along in the Transition Started event (an event that is required when using this event). The transition needs also to be marked with 'Raise Event To Complete Transition in order to use this event.'", text = completeCurrentTransitionProp.displayName }, true);
EditorGUILayout.PropertyField(serializedObject.FindProperty("_states"), true);
EditorGUILayout.PropertyField(serializedObject.FindProperty("_transitions"), true);
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7c9dfec58f1704690b369ef9580bb07e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
using System;
using UnityAtoms.BaseAtoms;
namespace UnityAtoms.FSM
{
[Serializable]
public class FSMStateListWrapper : AtomListWrapper<FSMState> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2aa0cb2bd8023434aab0a911accf16e4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityAtoms.BaseAtoms;
using UnityAtoms;
namespace UnityAtoms.FSM
{
@ -18,20 +18,19 @@ namespace UnityAtoms.FSM
get
{
var state = GetState(_value);
return state.SubMachine != null ? state.SubMachine.Value : _value;
return state != null && state.SubMachine != null ? state.SubMachine.Value : _value;
}
set => Dispatch(value);
}
public FSMTransitionDataEvent TransitionStarted { get => _transitionStarted; set => _transitionStarted = value; }
public BoolEvent CompleteCurrentTransition { get => _completeCurrentTransition; set => _completeCurrentTransition = value; }
public override string InitialValue { get => _states != null && _states.Count > 0 ? _states[0].Id : ""; }
public override string InitialValue { get => _states?.List != null && _states.List.Count > 0 ? _states.List[0].Id : ""; }
/// <summary>
/// Gets a boolean value indicating if the state machine is currently transitioning.
/// </summary>
public bool IsTransitioning { get => _currentTransition != null; }
[SerializeField]
private FSMTransitionDataEvent _transitionStarted = default(FSMTransitionDataEvent);
@ -39,10 +38,12 @@ namespace UnityAtoms.FSM
private BoolEvent _completeCurrentTransition = default(BoolEvent);
[SerializeField]
private List<FSMState> _states;
[AtomList]
private FSMStateListWrapper _states;
[SerializeField]
private List<Transition> _transitions;
[AtomList]
private TransitionListWrapper _transitions;
private bool _isUpdatingState = false;
private Transition _currentTransition = null;
@ -165,12 +166,12 @@ namespace UnityAtoms.FSM
public override void Reset(bool shouldTriggerEvents = false)
{
// TODO: Validate transitions and states
Validate();
// Set all timers to the same as the cooldown
for (var i = 0; i < _states.Count; ++i)
for (var i = 0; i < _states.List.Count; ++i)
{
_states[i].Timer = _states[i].Cooldown;
_states.List[i].Timer = _states.List[i].Cooldown;
}
if (!_resetOnNextTransitionCompleted && !IsTransitioning)
@ -238,6 +239,24 @@ namespace UnityAtoms.FSM
protected override bool ValueEquals(string other) => false; // Always trigger events even if changing to the same state as previous
private void Validate()
{
for (var i = 0; i < _transitions.List.Count; ++i)
{
var transition = _transitions.List[i];
if (!_states.List.Exists((s) => s.Id == transition.FromState))
{
Debug.LogError($"Transition with From State {transition.FromState} can't be found in the defined states.");
}
if (!_states.List.Exists((s) => s.Id == transition.ToState))
{
Debug.LogError($"Transition with To State {transition.ToState} can't be found in the defined states.");
}
}
}
private void EndCurrentTransition()
{
if (_resetOnNextTransitionCompleted)
@ -268,11 +287,11 @@ namespace UnityAtoms.FSM
private void ResetAllSubMachines()
{
for (var i = 0; i < _states.Count; ++i)
for (var i = 0; i < _states.List.Count; ++i)
{
if (_states[i].SubMachine != null)
if (_states.List[i].SubMachine != null)
{
_states[i].SubMachine.Reset();
_states.List[i].SubMachine.Reset();
}
}
}
@ -286,9 +305,9 @@ namespace UnityAtoms.FSM
{
// Update timers and call OnStateCooldown handlers if applicable
var currentValue = Value;
for (var i = 0; i < _states.Count; ++i)
for (var i = 0; i < _states.List.Count; ++i)
{
var state = _states[i];
var state = _states.List[i];
if (state.Cooldown > 0f)
{
var isCurrent = state.Id == currentValue;
@ -336,9 +355,9 @@ namespace UnityAtoms.FSM
{
Transition ret = null;
for (var i = 0; i < _transitions.Count; ++i)
for (var i = 0; i < _transitions.List.Count; ++i)
{
var transition = _transitions[i];
var transition = _transitions.List[i];
if (command == transition.Command && _currentFlatValue == transition.FromState)
{
return transition;
@ -350,15 +369,15 @@ namespace UnityAtoms.FSM
private FSMState GetState(string id)
{
for (var i = 0; i < _states.Count; ++i)
for (var i = 0; i < _states.List.Count; ++i)
{
if (_states[i].Id == id)
if (_states.List[i].Id == id)
{
return _states[i];
return _states.List[i];
}
}
throw new System.Exception($"State with id {id} could not be found.");
return null;
}
}
}

View File

@ -0,0 +1,8 @@
using System;
using UnityAtoms.BaseAtoms;
namespace UnityAtoms.FSM
{
[Serializable]
public class TransitionListWrapper : AtomListWrapper<Transition> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5a7a3f96d68ef4e3d9637bb1f4634554
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: