using UnityEngine; using System.Collections; using System.Collections.Generic; [RequireComponent(typeof(CubeClash_ZibuController))] public class CubeClash_ZibuAI : MonoBehaviour { [Header("AI Settings")] public float moveSpeed = 3f; public float decisionInterval = 2f; public float bumpRange = 2.5f; public float roamRadius = 5f; [Header("Arena Bounds")] public Transform arenaCube; private Bounds arenaBounds; private CubeClash_ZibuController zibuController; private Rigidbody rb; private CubeClash_ZibuController target; private Vector3 roamTarget; private float decisionTimer; private bool isBumpCooling = false; private CubeClash_ZibuController lastTarget; void Awake() { zibuController = GetComponent(); rb = GetComponent(); zibuController.isPlayerControlled = false; if (arenaCube != null) { arenaBounds = new Bounds(arenaCube.position, arenaCube.localScale); } PickRoamTarget(); } void Update() { decisionTimer += Time.deltaTime; if (decisionTimer >= decisionInterval) { decisionTimer = 0f; PickTargetOrRoam(); } if (target != null) { // move generally towards target, but still bump direction is forward MoveTowards(target.transform.position); TryBumpTarget(); } else { MoveTowards(roamTarget); if (Vector3.Distance(transform.position, roamTarget) < 1f) { PickRoamTarget(); } } } void PickTargetOrRoam() { List allZibus = CubeClash_ZibuController.AllZibus; if (allZibus.Count > 1) { List candidates = new List(); foreach (var z in allZibus) { if (z != zibuController && z != lastTarget) candidates.Add(z); } if (candidates.Count > 0) { int index = Random.Range(0, candidates.Count); target = candidates[index]; return; } } target = null; PickRoamTarget(); } void MoveTowards(Vector3 destination) { Vector3 dir = (destination - transform.position).normalized; Vector3 move = new Vector3(dir.x, 0, dir.z) * moveSpeed; rb.velocity = new Vector3(move.x, rb.velocity.y, move.z); if (dir.magnitude > 0.1f) { // flatten direction on Y axis dir.y = 0; // smooth rotate only around Y Quaternion targetRot = Quaternion.LookRotation(dir, Vector3.up); transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, Time.deltaTime * 5f); } } void PickRoamTarget() { Vector3 randomOffset = new Vector3(Random.Range(-roamRadius, roamRadius), 0, Random.Range(-roamRadius, roamRadius)); roamTarget = transform.position + randomOffset; if (arenaCube != null) { arenaBounds = new Bounds(arenaCube.position, arenaCube.localScale); roamTarget.x = Mathf.Clamp(roamTarget.x, arenaBounds.min.x + 1f, arenaBounds.max.x - 1f); roamTarget.z = Mathf.Clamp(roamTarget.z, arenaBounds.min.z + 1f, arenaBounds.max.z - 1f); roamTarget.y = transform.position.y; } } void TryBumpTarget() { if (isBumpCooling || target == null) return; float dist = Vector3.Distance(transform.position, target.transform.position); if (dist <= bumpRange) { Vector3 toTarget = (target.transform.position - transform.position).normalized; float dot = Vector3.Dot(transform.forward, toTarget); if (dot > 0.7f) { StartCoroutine(BumpWithDelay()); } } } IEnumerator BumpWithDelay() { isBumpCooling = true; yield return new WaitForSeconds(Random.Range(0.1f, 0.4f)); zibuController.PerformBump(transform.forward); // after bump: forget target & roam somewhere else lastTarget = target; target = null; PickRoamTarget(); yield return new WaitForSeconds(Random.Range(1f, 2f)); isBumpCooling = false; } }