using NodeCanvas.BehaviourTrees; using NodeCanvas.Framework; using ParadoxNotion.Design; using UnityEngine; namespace NodeCanvas.StateMachines { [Name("Sub BehaviourTree")] [Description("Execute a Behaviour Tree OnEnter. OnExit that Behavior Tree will be stoped or paused based on the relevant specified setting. You can optionaly specify a Success Event and a Failure Event which will be sent when the BT's root node status returns either of the two. If so, use alongside with a CheckEvent on a transition.")] [DropReferenceType(typeof(BehaviourTree))] [ParadoxNotion.Design.Icon("BT")] public class NestedBTState : FSMStateNested { public enum BTExecutionMode { Once, Repeat } public enum BTExitMode { StopAndRestart, PauseAndResume } [SerializeField, ExposeField, Name("Sub Tree")] private BBParameter _nestedBT = null; [Tooltip("What will happen to the BT when this state exits.")] public BTExitMode exitMode = BTExitMode.StopAndRestart; [Tooltip("Sould the BT repeat?")] public BTExecutionMode executionMode = BTExecutionMode.Repeat; [DimIfDefault, Tooltip("The event to send when the BT finish in Success.")] public string successEvent; [DimIfDefault, Tooltip("The event to send when the BT finish in Failure.")] public string failureEvent; public override BehaviourTree subGraph { get { return _nestedBT.value; } set { _nestedBT.value = value; } } public override BBParameter subGraphParameter => _nestedBT; // protected override void OnEnter() { if ( subGraph == null ) { Finish(false); return; } currentInstance = (BehaviourTree)this.CheckInstance(); currentInstance.repeat = ( executionMode == BTExecutionMode.Repeat ); currentInstance.updateInterval = 0; this.TryWriteAndBindMappedVariables(); currentInstance.StartGraph(graph.agent, graph.blackboard.parent, Graph.UpdateMode.Manual, OnFinish); OnUpdate(); } protected override void OnUpdate() { currentInstance.UpdateGraph(this.graph.deltaTime); if ( !string.IsNullOrEmpty(successEvent) && currentInstance.rootStatus == Status.Success ) { currentInstance.Stop(true); } if ( !string.IsNullOrEmpty(failureEvent) && currentInstance.rootStatus == Status.Failure ) { currentInstance.Stop(false); } } void OnFinish(bool success) { if ( this.status == Status.Running ) { this.TryReadAndUnbindMappedVariables(); if ( !string.IsNullOrEmpty(successEvent) && success ) { SendEvent(successEvent); } if ( !string.IsNullOrEmpty(failureEvent) && !success ) { SendEvent(failureEvent); } Finish(success); } } protected override void OnExit() { if ( currentInstance != null ) { if ( this.status == Status.Running ) { this.TryReadAndUnbindMappedVariables(); } if ( exitMode == BTExitMode.StopAndRestart ) { currentInstance.Stop(); } else { currentInstance.Pause(); } } } } }