Files
BABA_YAGA/Assets/Scripts/AI NPC/EnemyAI.cs

176 lines
3.8 KiB
C#
Raw Normal View History

2026-05-30 17:41:31 +07:00
using System.Collections.Generic;
using UnityEngine;
public class EnemyAI : MonoBehaviour
{
2026-06-03 13:42:09 +07:00
[Header("References")]
2026-05-30 17:41:31 +07:00
public Transform player;
2026-06-03 13:42:09 +07:00
[Header("Detection")]
2026-05-30 17:41:31 +07:00
public float detectRange = 10f;
public float moveSpeed = 3f;
public float rotateSpeed = 50f;
2026-06-03 13:42:09 +07:00
[Header("Artifact")]
public bool playerHasArtifact;
[Header("Laser")]
public GameObject laserPrefab;
public Transform firePoint;
public float minShootDelay = 1f;
public float maxShootDelay = 3f;
private float nextShootTime;
2026-05-30 17:41:31 +07:00
public Node behaviorTreeRoot;
2026-06-03 13:42:09 +07:00
private void Start()
2026-05-30 17:41:31 +07:00
{
2026-06-04 09:24:20 +07:00
player = GameObject.FindGameObjectWithTag("Player").transform;
2026-06-03 13:42:09 +07:00
nextShootTime = Time.time + Random.Range(minShootDelay, maxShootDelay);
2026-05-30 17:41:31 +07:00
InitBehaviorTree();
}
2026-06-04 09:24:20 +07:00
2026-06-03 13:42:09 +07:00
private void Update()
2026-05-30 17:41:31 +07:00
{
2026-06-03 13:42:09 +07:00
behaviorTreeRoot?.Evaluate();
2026-05-30 17:41:31 +07:00
}
2026-06-03 13:42:09 +07:00
private void InitBehaviorTree()
2026-05-30 17:41:31 +07:00
{
2026-06-03 13:42:09 +07:00
// 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
2026-05-30 17:41:31 +07:00
var chaseSequence = new Sequence(new List<Node>
{
new TaskNode(CheckCanSeePlayer),
new TaskNode(ActionMoveToPlayer)
});
2026-06-03 13:42:09 +07:00
// Không thấy ai -> scan
var scanNode = new TaskNode(ActionRotationScan);
2026-05-30 17:41:31 +07:00
behaviorTreeRoot = new Selector(new List<Node>
{
2026-06-03 13:42:09 +07:00
laserSequence,
2026-05-30 17:41:31 +07:00
chaseSequence,
2026-06-03 13:42:09 +07:00
scanNode
2026-05-30 17:41:31 +07:00
});
}
2026-06-03 13:42:09 +07:00
#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
2026-05-30 17:41:31 +07:00
private NodeState ActionRotationScan()
{
2026-06-03 13:42:09 +07:00
Debug.Log("Scanning...");
transform.Rotate(
Vector3.up,
rotateSpeed * Time.deltaTime);
2026-05-30 17:41:31 +07:00
return NodeState.Running;
}
private NodeState ActionMoveToPlayer()
{
2026-06-03 13:42:09 +07:00
if (player == null)
return NodeState.Failure;
Debug.Log("Chasing Player");
Vector3 dir =
(player.position - transform.position).normalized;
transform.position +=
dir *
moveSpeed *
Time.deltaTime;
2026-05-30 17:41:31 +07:00
return NodeState.Running;
}
2026-06-03 13:42:09 +07:00
private NodeState ActionFocusAndShoot()
2026-05-30 17:41:31 +07:00
{
if (player == null)
return NodeState.Failure;
2026-06-03 13:42:09 +07:00
// 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);
2026-05-30 17:41:31 +07:00
}
2026-06-03 13:42:09 +07:00
// Shoot with random delay
if (Time.time >= nextShootTime)
2026-05-30 17:41:31 +07:00
{
2026-06-03 13:42:09 +07:00
ShootLaser();
nextShootTime =
Time.time +
Random.Range(minShootDelay, maxShootDelay);
2026-05-30 17:41:31 +07:00
}
2026-06-03 13:42:09 +07:00
return NodeState.Running;
2026-05-30 17:41:31 +07:00
}
2026-06-03 13:42:09 +07:00
private void ShootLaser()
{
if (laserPrefab == null || firePoint == null)
return;
Instantiate(
laserPrefab,
firePoint.position,
firePoint.rotation);
Debug.Log("Laser Shot!");
}
#endregion
2026-05-30 17:41:31 +07:00
}