using NodeCanvas.Framework; using ParadoxNotion.Design; using UnityEngine; namespace NodeCanvas.BehaviourTrees { /// BehaviourTrees are used to create advanced AI and logic based on simple rules. [GraphInfo( packageName = "NodeCanvas", docsURL = "https://nodecanvas.paradoxnotion.com/documentation/", resourcesURL = "https://nodecanvas.paradoxnotion.com/downloads/", forumsURL = "https://nodecanvas.paradoxnotion.com/forums-page/" )] [CreateAssetMenu(menuName = "ParadoxNotion/NodeCanvas/Behaviour Tree Asset")] public class BehaviourTree : Graph { ///---------------------------------------------------------------------------------------------- [System.Serializable] class DerivedSerializationData { public bool repeat; public float updateInterval; } public override object OnDerivedDataSerialization() { var data = new DerivedSerializationData(); data.repeat = this.repeat; data.updateInterval = this.updateInterval; return data; } public override void OnDerivedDataDeserialization(object data) { if ( data is DerivedSerializationData ) { this.repeat = ( (DerivedSerializationData)data ).repeat; this.updateInterval = ( (DerivedSerializationData)data ).updateInterval; } } ///---------------------------------------------------------------------------------------------- ///Should the tree repeat forever? [System.NonSerialized] public bool repeat = true; ///The frequency in seconds for the tree to repeat if set to repeat. [System.NonSerialized] public float updateInterval = 0; ///Raised when the root status of the behaviour is changed public static event System.Action onRootStatusChanged; private float intervalCounter; private Status _rootStatus = Status.Resting; ///The last status of the root node public Status rootStatus { get { return _rootStatus; } private set { if ( _rootStatus != value ) { _rootStatus = value; if ( onRootStatusChanged != null ) { onRootStatusChanged(this, value); } } } } ///---------------------------------------------------------------------------------------------- public override System.Type baseNodeType => typeof(BTNode); public override bool requiresAgent => true; public override bool requiresPrimeNode => true; public override bool isTree => true; public override bool allowBlackboardOverrides => true; sealed public override bool canAcceptVariableDrops => false; public override ParadoxNotion.PlanarDirection flowDirection => ParadoxNotion.PlanarDirection.Vertical; ///---------------------------------------------------------------------------------------------- protected override void OnGraphStarted() { intervalCounter = updateInterval; rootStatus = primeNode.status; } protected override void OnGraphUpdate() { if ( intervalCounter >= updateInterval ) { intervalCounter = 0; if ( Tick(agent, blackboard) != Status.Running && !repeat ) { Stop(rootStatus == Status.Success); } } if ( updateInterval > 0 ) { intervalCounter += Time.deltaTime; } } ///Tick the tree once for the provided agent and with the provided blackboard Status Tick(Component agent, IBlackboard blackboard) { if ( rootStatus != Status.Running ) { primeNode.Reset(); } return rootStatus = primeNode.Execute(agent, blackboard); } ///---------------------------------------------------------------------------------------------- ///---------------------------------------UNITY EDITOR------------------------------------------- #if UNITY_EDITOR [UnityEditor.MenuItem("Tools/ParadoxNotion/NodeCanvas/Create/Behaviour Tree Asset", false, 0)] static void Editor_CreateGraph() { var newGraph = EditorUtils.CreateAsset(); UnityEditor.Selection.activeObject = newGraph; } #endif } }