using System.Collections.Generic; using UnityEngine; public class EnemyAI : MonoBehaviour { [Range(0, 100)] public float hp; [Range(0, 100)] public float distanceToPlayer; public bool isAttackReady; public Node behaviorTreeRoot; // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { InitBehaviorTree(); } // Update is called once per frame void Update() { if (behaviorTreeRoot != null) { behaviorTreeRoot.Evaluate(); } } void InitBehaviorTree() { var survivalSequences = new Sequence(new List { new TaskNode(CheckLowHealth), new TaskNode(ActionFleeAndHeal) }); var meleeSequences = new Sequence(new List { new TaskNode(CheckMeleeRange), new TaskNode(ActionSmash) }); var rangeSequence = new Sequence(new List { new TaskNode(CheckAttackRange), // khoang cach new TaskNode(CheckAttackReady), // Mp new TaskNode(ActionShoot) // tan cong }); var chaseAction = new TaskNode(ActionChase); behaviorTreeRoot = new Selector(new List { survivalSequences, // song sot meleeSequences, // tan cong gan rangeSequence, // tan cong xa chaseAction // duoi theo }); } private NodeState ActionChase() { // logic Debug.Log("Chasing the player..."); return NodeState.Running; } private NodeState ActionShoot() { Debug.Log("Shooting at the player..."); return NodeState.Running; } private NodeState CheckAttackReady() { Debug.Log("Checking if attack is ready..."); return NodeState.Failure; } private NodeState CheckAttackRange() { Debug.Log("Checking if player is in attack range..."); return NodeState.Failure; } private NodeState ActionSmash() { Debug.Log("Smashing the player..."); return NodeState.Success; } private NodeState CheckMeleeRange() { if(distanceToPlayer < 2f) return NodeState.Success; return NodeState.Failure; } private NodeState ActionFleeAndHeal() { Debug.Log("Flee and heal the player..."); return NodeState.Success; } private NodeState CheckLowHealth() { if (hp < 30f) return NodeState.Success; return NodeState.Failure; } }