Files
BABA_YAGA/Assets/Scripts/AI NPC/EnemyAI.cs
manhduyhoang90 3567c55534 Update EnemyAI.cs
2026-06-04 09:24:20 +07:00

176 lines
3.8 KiB
C#

using System.Collections.Generic;
using UnityEngine;
public class EnemyAI : MonoBehaviour
{
[Header("References")]
public Transform player;
[Header("Detection")]
public float detectRange = 10f;
public float moveSpeed = 3f;
public float rotateSpeed = 50f;
[Header("Artifact")]
public bool playerHasArtifact;
[Header("Laser")]
public GameObject laserPrefab;
public Transform firePoint;
public float minShootDelay = 1f;
public float maxShootDelay = 3f;
private float nextShootTime;
public Node behaviorTreeRoot;
private void Start()
{
player = GameObject.FindGameObjectWithTag("Player").transform;
nextShootTime = Time.time + Random.Range(minShootDelay, maxShootDelay);
InitBehaviorTree();
}
private void Update()
{
behaviorTreeRoot?.Evaluate();
}
private void InitBehaviorTree()
{
// Player có artifact -> focus + shoot
var laserSequence = new Sequence(new List<Node>
{
new TaskNode(CheckHasArtifact),
new TaskNode(ActionFocusAndShoot)
});
// Thấy player -> chạy tới
var chaseSequence = new Sequence(new List<Node>
{
new TaskNode(CheckCanSeePlayer),
new TaskNode(ActionMoveToPlayer)
});
// Không thấy ai -> scan
var scanNode = new TaskNode(ActionRotationScan);
behaviorTreeRoot = new Selector(new List<Node>
{
laserSequence,
chaseSequence,
scanNode
});
}
#region CONDITIONS
private NodeState CheckHasArtifact()
{
return playerHasArtifact
? NodeState.Success
: NodeState.Failure;
}
private NodeState CheckCanSeePlayer()
{
if (player == null)
return NodeState.Failure;
float distance =
Vector3.Distance(transform.position, player.position);
if (distance <= detectRange)
{
return NodeState.Success;
}
return NodeState.Failure;
}
#endregion
#region ACTIONS
private NodeState ActionRotationScan()
{
Debug.Log("Scanning...");
transform.Rotate(
Vector3.up,
rotateSpeed * Time.deltaTime);
return NodeState.Running;
}
private NodeState ActionMoveToPlayer()
{
if (player == null)
return NodeState.Failure;
Debug.Log("Chasing Player");
Vector3 dir =
(player.position - transform.position).normalized;
transform.position +=
dir *
moveSpeed *
Time.deltaTime;
return NodeState.Running;
}
private NodeState ActionFocusAndShoot()
{
if (player == null)
return NodeState.Failure;
// Focus player
Vector3 dir =
player.position - transform.position;
dir.y = 0f;
if (dir != Vector3.zero)
{
Quaternion targetRotation =
Quaternion.LookRotation(dir);
transform.rotation =
Quaternion.Slerp(
transform.rotation,
targetRotation,
5f * Time.deltaTime);
}
// Shoot with random delay
if (Time.time >= nextShootTime)
{
ShootLaser();
nextShootTime =
Time.time +
Random.Range(minShootDelay, maxShootDelay);
}
return NodeState.Running;
}
private void ShootLaser()
{
if (laserPrefab == null || firePoint == null)
return;
Instantiate(
laserPrefab,
firePoint.position,
firePoint.rotation);
Debug.Log("Laser Shot!");
}
#endregion
}