#if GRAPH_DESIGNER
/// ---------------------------------------------
/// Behavior Designer
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.BehaviorDesigner.Runtime.Tasks
{
using Opsive.BehaviorDesigner.Runtime.Systems;
using Opsive.GraphDesigner.Runtime.Variables;
using Opsive.Shared.Utility;
using System.Collections.Generic;
using Unity.Entities;
using UnityEngine;
using static Opsive.BehaviorDesigner.Runtime.BehaviorTreeData;
///
/// The base class for a Mono task.
///
public abstract class Task : ISavableTask
{
protected GameObject m_GameObject;
protected Transform m_Transform;
protected BehaviorTree m_BehaviorTree;
protected ushort m_RuntimeIndex;
protected virtual GameObject gameObject { get => m_GameObject; }
protected virtual Transform transform { get => m_Transform; }
private TaskStatus m_Status;
internal TaskStatus Status { get => m_Status; set => m_Status = value; }
///
/// Adds the task to the behavior tree buffer.
///
/// The world that the task runs in.
/// The entity that the task is connected to.
/// The ID of the behavior tree running the task.
/// The index of the task.
public virtual void AddBufferElement(World world, Entity entity, int behaviorTreeID, ushort index)
{
DynamicBuffer buffer;
if (world.EntityManager.HasBuffer(entity)) {
buffer = world.EntityManager.GetBuffer(entity);
} else {
buffer = world.EntityManager.AddBuffer(entity);
}
buffer.Add(new TaskObjectComponent()
{
Index = index,
});
}
///
/// Clears all component buffers from the behavior tree buffer.
///
/// The world that the task runs in.
/// The entity that the task is connected to.
public virtual void ClearBufferElement(World world, Entity entity)
{
DynamicBuffer buffer;
if (world.EntityManager.HasBuffer(entity)) {
buffer = world.EntityManager.GetBuffer(entity);
buffer.Clear();
}
}
///
/// Resets the task values back to their default.
///
public virtual void Reset() { }
///
/// Initializes the base task parameters.
///
/// A reference to the owning BehaviorTree.
/// The runtime index of the node.
internal virtual void Initialize(BehaviorTree behaviorTree, ushort runtimeIndex)
{
if (!Application.isPlaying) {
return;
}
m_BehaviorTree = behaviorTree;
m_GameObject = m_BehaviorTree.gameObject;
m_Transform = m_BehaviorTree.transform;
m_RuntimeIndex = runtimeIndex;
m_BehaviorTree.OnBehaviorTreeStarted += OnBehaviorTreeStarted;
m_BehaviorTree.OnBehaviorTreeStopped += OnBehaviorTreeStopped;
m_BehaviorTree.OnBehaviorTreeDestroyed += OnDestroy;
if (ReceiveCollisionEnterCallback) { m_BehaviorTree.OnBehaviorTreeCollisionEnter += OnCollisionEnter; }
if (ReceiveCollisionExitCallback) { m_BehaviorTree.OnBehaviorTreeCollisionExit += OnCollisionExit; }
if (ReceiveCollisionEnter2DCallback) { m_BehaviorTree.OnBehaviorTreeCollisionEnter2D += OnCollisionEnter2D; }
if (ReceiveCollisionExit2DCallback) { m_BehaviorTree.OnBehaviorTreeCollisionExit2D += OnCollisionExit2D; }
if (ReceiveTriggerEnterCallback) { m_BehaviorTree.OnBehaviorTreeTriggerEnter += OnTriggerEnter; }
if (ReceiveTriggerExitCallback) { m_BehaviorTree.OnBehaviorTreeTriggerExit += OnTriggerExit; }
if (ReceiveTriggerEnter2DCallback) { m_BehaviorTree.OnBehaviorTreeTriggerEnter2D += OnTriggerEnter2D; }
if (ReceiveTriggerExit2DCallback) { m_BehaviorTree.OnBehaviorTreeTriggerExit2D += OnTriggerExit2D; }
if (ReceiveControllerColliderHitCallback) { m_BehaviorTree.OnBehaviorTreeControllerColliderHit += OnControllerColliderHit; }
OnAwake();
}
///
/// Callback when the behavior tree is initialized.
///
public virtual void OnAwake() { }
///
/// Callback when the behavior tree is started.
///
public virtual void OnBehaviorTreeStarted() { }
///
/// Callback when the behavior tree is started.
///
[System.Obsolete("Task.OnStarted has been deprecated. Use Task.OnBehaviorTreeStarted instead.")]
public virtual void OnStarted() { }
///
/// Callback when the task is started.
///
public virtual void OnStart() { }
///
/// Executes the task logic. Returns a TaskStatus indicating how the behavior tree flow should proceed.
///
/// The status of the task.
public virtual TaskStatus OnUpdate() { return TaskStatus.Success; }
///
/// Callback when the task stops.
///
public virtual void OnEnd() { }
///
/// Calls Unity's GetComponent method.
///
/// The retrieved component (can be null).
protected T GetComponent()
{
return gameObject.GetComponent();
}
///
/// Calls Unity's GetComponent method.
///
/// The component type that should be retrieved.
/// The retrieved component (can be null).
protected Component GetComponent(System.Type type)
{
return gameObject.GetComponent(type);
}
///
/// Calls Unity's TryGetComponent method.
///
/// The type of component that should be retireved.
/// The retrieved component.
protected void TryGetComponent(out T component) where T : Component
{
gameObject.TryGetComponent(out component);
}
///
/// Calls Unity's TryGetComponent method.
///
/// The type of component to get.
/// The retrieved component.
protected void TryGetComponent(System.Type type, out Component component)
{
gameObject.TryGetComponent(type, out component);
}
protected void StartCoroutine(string methodName) { m_BehaviorTree.StartTaskCoroutine(this, methodName); }
protected Coroutine StartCoroutine(System.Collections.IEnumerator routine) { return m_BehaviorTree.StartCoroutine(routine); }
protected Coroutine StartCoroutine(string methodName, object value) { return m_BehaviorTree.StartTaskCoroutine(this, methodName, value); }
protected void StopCoroutine(string methodName) { m_BehaviorTree.StopTaskCoroutine(methodName); }
protected void StopCoroutine(System.Collections.IEnumerator routine) { m_BehaviorTree.StopCoroutine(routine); }
protected void StopAllCoroutines() { m_BehaviorTree.StopAllTaskCoroutines(); }
protected virtual bool ReceiveCollisionEnterCallback => false;
///
/// Callback when OnCollisionEnter is triggered. This callback will only be received when ReceiveCollisionEnterCallback is true.
///
/// The resulting collision.
protected virtual void OnCollisionEnter(Collision collision) { }
protected virtual bool ReceiveCollisionExitCallback => false;
///
/// Callback when OnCollisionExit is triggered. This callback will only be received when ReceiveCollisionExitCallback is true.
///
/// The resulting collision.
protected virtual void OnCollisionExit(Collision collision) { }
protected virtual bool ReceiveCollisionEnter2DCallback => false;
///
/// Callback when OnCollisionEnter2D is triggered. This callback will only be received when ReceiveCollisionEnter2DCallback is true.
///
/// The resulting collision.
protected virtual void OnCollisionEnter2D(Collision2D collision) { }
protected virtual bool ReceiveCollisionExit2DCallback => false;
///
/// Callback when OnCollisionExit2D is triggered. This callback will only be received when ReceiveCollisionExit2DCallback is true.
///
/// The resulting collision.
protected virtual void OnCollisionExit2D(Collision2D collision) { }
protected virtual bool ReceiveTriggerEnterCallback => false;
///
/// Callback when OnTriggerEnter is triggered. This callback will only be received when ReceiveTriggerEnterCallback is true.
///
/// The overlapping collider.
protected virtual void OnTriggerEnter(Collider other) { }
protected virtual bool ReceiveTriggerExitCallback => false;
///
/// Callback when OnTriggerExit is triggered. This callback will only be received when ReceiveTriggerExitCallback is true.
///
/// The overlapping collider.
protected virtual void OnTriggerExit(Collider other) { }
protected virtual bool ReceiveTriggerEnter2DCallback => false;
///
/// Callback when OnTriggerEnter2D is triggered. This callback will only be received when ReceiveTriggerEnter2DCallback is true.
///
/// The overlapping collider.
protected virtual void OnTriggerEnter2D(Collider2D other) { }
protected virtual bool ReceiveTriggerExit2DCallback => false;
///
/// Callback when OnTriggerExit2D is triggered. This callback will only be received when ReceiveTriggerExit2DCallback is true.
///
/// The overlapping collider.
protected virtual void OnTriggerExit2D(Collider2D other) { }
protected virtual bool ReceiveControllerColliderHitCallback => false;
///
/// Callback when OnControllerColliderHit is triggered. This callback will only be received when ReceiveControllerColliderHitCallback is true.
///
/// The hit result.
protected virtual void OnControllerColliderHit(ControllerColliderHit hit) { }
///
/// Editor method which will draw the gizmos.
///
/// A reference to the behavior tree component.
internal void OnDrawGizmos(BehaviorTree behaviorTree)
{
if (m_BehaviorTree == null) {
m_BehaviorTree = behaviorTree;
m_Transform = behaviorTree.transform;
m_GameObject = behaviorTree.gameObject;
}
OnDrawGizmos();
}
///
/// Callback when OnDrawGizmos is triggered.
///
protected virtual void OnDrawGizmos() { }
///
/// Editor method which will draw the selected gizmos.
///
/// A reference to the behavior tree component.
internal void OnDrawGizmosSelected(BehaviorTree behaviorTree)
{
if (m_BehaviorTree == null) {
m_BehaviorTree = behaviorTree;
m_Transform = behaviorTree.transform;
m_GameObject = behaviorTree.gameObject;
}
OnDrawGizmosSelected();
}
///
/// Callback when OnDrawGizmosSelected is triggered.
///
protected virtual void OnDrawGizmosSelected() { }
///
/// Callback when the behavior tree is stopped.
///
/// Is the behavior tree paused?
public virtual void OnBehaviorTreeStopped(bool paused) { }
///
/// Callback when the behavior tree is stopped.
///
/// Is the behavior tree paused?
[System.Obsolete("Task.OnStopped has been deprecated. Use Task.OnBehaviorTreeStopped instead.")]
public virtual void OnStopped(bool paused) { }
///
/// Callback when the behavior tree is destroyed.
///
public virtual void OnDestroy()
{
if (m_BehaviorTree == null) {
return;
}
m_BehaviorTree.OnBehaviorTreeStarted -= OnBehaviorTreeStarted;
m_BehaviorTree.OnBehaviorTreeStopped -= OnBehaviorTreeStopped;
m_BehaviorTree.OnBehaviorTreeDestroyed -= OnDestroy;
if (ReceiveCollisionEnterCallback) { m_BehaviorTree.OnBehaviorTreeCollisionEnter -= OnCollisionEnter; }
if (ReceiveCollisionExitCallback) { m_BehaviorTree.OnBehaviorTreeCollisionExit -= OnCollisionExit; }
if (ReceiveCollisionEnter2DCallback) { m_BehaviorTree.OnBehaviorTreeCollisionEnter2D -= OnCollisionEnter2D; }
if (ReceiveCollisionExit2DCallback) { m_BehaviorTree.OnBehaviorTreeCollisionExit2D -= OnCollisionExit2D; }
if (ReceiveTriggerEnterCallback) { m_BehaviorTree.OnBehaviorTreeTriggerEnter -= OnTriggerEnter; }
if (ReceiveTriggerExitCallback) { m_BehaviorTree.OnBehaviorTreeTriggerExit -= OnTriggerExit; }
if (ReceiveTriggerEnter2DCallback) { m_BehaviorTree.OnBehaviorTreeTriggerEnter2D -= OnTriggerEnter2D; }
if (ReceiveTriggerExit2DCallback) { m_BehaviorTree.OnBehaviorTreeTriggerExit2D -= OnTriggerExit2D; }
if (ReceiveControllerColliderHitCallback) { m_BehaviorTree.OnBehaviorTreeControllerColliderHit -= OnControllerColliderHit; }
}
///
/// Overrides ToString providing a nicer string value of the task.
///
/// The overloaded ToString value.
public override string ToString()
{
return GetType().Name;
}
///
/// Specifies the type of reflection that should be used to save the task.
///
/// The index of the sub-task. This is used for the task set allowing each contained task to have their own save type.
public virtual MemberVisibility GetSaveReflectionType(int index) { return MemberVisibility.Public; }
///
/// Returns the current task state.
///
/// The DOTS world.
/// The DOTS entity.
/// The current task state.
public virtual object Save(World world, Entity entity)
{
return null;
}
///
/// Loads the previous task state.
///
/// The previous task state.
/// The DOTS world.
/// The DOTS entity.
public virtual void Load(object saveData, World world, Entity entity) { }
///
/// Loads the previous task state.
///
/// The previous task state.
/// The DOTS world.
/// The DOTS entity.
/// A reference to the map between the VariableAssignment and SharedVariable.
/// A reference to the list of task references that need to be resolved later.
public virtual void Load(object saveData, World world, Entity entity, Dictionary variableByNameMap,
ref ResizableArray taskReferences)
{
Load(saveData, world, entity);
}
}
///
/// A blob asset that stores the indicies array.
///
public struct IndiciesBlob
{
[Tooltip("The indicies of the tasks.")]
public BlobArray Indicies;
}
}
#endif