Gameplay Ingredients是一组用于 Unity 游戏的运行时和编辑器工具:一组脚本的集合,可在制作游戏和原型时简化简单的任务。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

125 行
4.0 KiB

using NaughtyAttributes;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using GameplayIngredients.Actions;
namespace GameplayIngredients.StateMachines
{
[HelpURL(Help.URL + "state-machines")]
[AdvancedHierarchyIcon("Packages/net.peeweek.gameplay-ingredients/Icons/Misc/ic-StateMachine.png")]
public class StateMachine : MonoBehaviour
{
[StateMachineState]
public string DefaultState;
[ReorderableList, NonNullCheck]
public State[] States = new State[0];
public State CurrentState { get { return m_CurrentState; } }
State m_CurrentState;
[Button("Create New State")]
private void AddNewState()
{
var newState = new GameObject($"State {States.Length}");
var state = newState.AddComponent<State>();
newState.transform.parent = transform;
newState.transform.localPosition = Vector3.zero;
newState.transform.localRotation = Quaternion.identity;
newState.transform.localScale = Vector3.one;
States = States.Concat(new State[] { state }).ToArray();
if (m_CurrentState == null)
m_CurrentState = state;
}
[Button("Reset State Objects")]
private void UpdateFromState()
{
foreach(var state in States)
{
state.gameObject.SetActive(state == States.FirstOrDefault(o => o.StateName == DefaultState));
}
}
[Button("Create/Update SetStateAction Components")]
private void UpdateSetStateActionComponents()
{
var components = this.GetComponents<SetStateAction>();
foreach (var state in States)
{
if (!components.Any(o => o.state == state.StateName))
{
var action = gameObject.AddComponent<SetStateAction>();
action.state = state.StateName;
action.StateMachine = this;
}
}
var todelete = GetComponents<SetStateAction>().Where(a => !States.Any(s => s.StateName == a.state)).ToArray();
for (int i = 0; i < todelete.Length; i++)
{
DestroyImmediate(todelete[i]);
}
components = this.GetComponents<SetStateAction>();
foreach(var action in components)
{
action.Name = $"Set State {action.state}";
}
}
void Start()
{
foreach (var state in States)
{
if(state.gameObject.activeSelf)
state.gameObject.SetActive(false);
}
SetState(DefaultState);
}
public void SetState(string stateName)
{
State newState = States.FirstOrDefault(o => o.StateName == stateName);
if(newState != null)
{
if (m_CurrentState != null)
{
// Call Exit Actions
Callable.Call(m_CurrentState.OnStateExit, gameObject);
// Then finally disable old state
m_CurrentState.gameObject.SetActive(false);
}
// Switch Active new state
newState.gameObject.SetActive(true);
// Then Set new current state
m_CurrentState = newState;
// Finally, call State enter
Callable.Call(m_CurrentState.OnStateEnter, gameObject);
}
else
Debug.LogWarning(string.Format("{0} : Trying to set unknown state {1}", gameObject.name, stateName), gameObject);
}
void Update()
{
if (GameplayIngredientsSettings.currentSettings.allowUpdateCalls
&& m_CurrentState != null
&& m_CurrentState.OnStateUpdate != null
&& m_CurrentState.OnStateUpdate.Length > 0)
{
Callable.Call(m_CurrentState.OnStateUpdate, this.gameObject);
}
}
}
}