using UnityEngine;
using Lightbug.Utilities;
namespace Lightbug.CharacterControllerPro.Implementation
{
///
/// This class is responsable for detecting inputs and managing character actions.
///
[AddComponentMenu("Character Controller Pro/Implementation/Character/Character Brain")]
[DefaultExecutionOrder(int.MinValue)]
public class CharacterBrain : MonoBehaviour
{
[Tooltip("Indicates when actions should be consumed.\n\n" +
"FixedUpdate (recommended): use this when the gameplay logic needs to run during FixedUpdate.\n\n" +
"Update: use this when the gameplay logic needs to run every frame during Update.")]
public UpdateModeType UpdateMode = UpdateModeType.FixedUpdate;
[BooleanButton("Brain type", "Player", "AI", true)]
[SerializeField]
bool isAI = false;
[Condition("isAI", ConditionAttribute.ConditionType.IsFalse)]
[Expand]
[SerializeField]
InputHandlerSettings inputHandlerSettings = new InputHandlerSettings();
[Condition("isAI", ConditionAttribute.ConditionType.IsTrue)]
[SerializeField]
CharacterAIBehaviour aiBehaviour = null;
[Expand]
[ReadOnly]
[SerializeField]
CharacterActions characterActions = new CharacterActions();
// ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
// ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
public enum UpdateModeType { FixedUpdate, Update }
CharacterAIBehaviour currentAIBehaviour = null;
bool firstUpdateFlag = false;
///
/// Gets the current brain mode (AI or Human).
///
public bool IsAI => isAI;
///
/// Gets the current actions values from the brain.
///
public CharacterActions CharacterActions => characterActions;
///
/// Sets the internal CharacterActions value.
///
public void SetAction(CharacterActions characterActions) => this.characterActions = characterActions;
///
/// Sets the type of brain.
///
public void SetBrainType(bool isAI)
{
characterActions.Reset();
if (isAI)
SetAIBehaviour(aiBehaviour);
this.isAI = isAI;
}
///
/// Sets the player's input handler.
///
public void SetInputHandler(InputHandler inputHandler)
{
if (inputHandler == null)
return;
inputHandlerSettings.InputHandler = inputHandler;
characterActions.Reset();
}
///
/// Sets the AI behaviour type.
///
public void SetAIBehaviour(CharacterAIBehaviour aiBehaviour)
{
if (aiBehaviour == null)
return;
currentAIBehaviour?.ExitBehaviour(Time.deltaTime);
characterActions.Reset();
currentAIBehaviour = aiBehaviour;
currentAIBehaviour.EnterBehaviour(Time.deltaTime);
}
public void UpdateBrainValues(float dt)
{
if (Time.timeScale == 0)
return;
if (IsAI)
UpdateAIBrainValues(dt);
else
UpdateHumanBrainValues(dt);
}
void UpdateHumanBrainValues(float dt)
{
characterActions.SetValues(inputHandlerSettings.InputHandler);
characterActions.Update(dt);
}
void UpdateAIBrainValues(float dt)
{
currentAIBehaviour?.UpdateBehaviour(dt);
characterActions.SetValues(currentAIBehaviour.characterActions);
characterActions.Update(dt);
}
#region Unity's messages
protected virtual void Awake()
{
characterActions.InitializeActions();
inputHandlerSettings.Initialize(gameObject);
}
protected virtual void OnEnable()
{
characterActions.InitializeActions();
characterActions.Reset();
}
protected virtual void OnDisable()
{
characterActions.Reset();
}
void Start()
{
SetBrainType(isAI);
}
protected virtual void FixedUpdate()
{
firstUpdateFlag = true;
if (UpdateMode == UpdateModeType.FixedUpdate)
{
UpdateBrainValues(0f);
}
}
protected virtual void Update()
{
float dt = Time.deltaTime;
if (UpdateMode == UpdateModeType.FixedUpdate)
{
if (firstUpdateFlag)
{
firstUpdateFlag = false;
characterActions.Reset();
}
}
else
{
characterActions.Reset();
}
UpdateBrainValues(dt);
}
#endregion
}
}