using ShotSimulator.Tool; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; namespace ShotSimulator.Target { public enum AIBehaviorState { None, Stand, Crouch } public class AIHumanoidShotTarget : HumanoidShotTarget { private AIBehaviorState current_BehaviorState; [SerializeField] private NavMeshAgent m_NavMeshAgent; [SerializeField] private Vector3 current_TargetPos; private bool toBoundary; private List m_HidePositions; private float m_HideProbability; private Vector3 maxBoundaryPos; private Vector3 minBoundaryPos; private TimeTask m_AIBehaviorStateChangeTimer; private float m_CrouchTimeProportion; public Animator m_Animator; public GameObject brokenFragment; public Animator m_ShieldAnimator; public GameObject m_ShieldObj; private void Start() { IsRunning = true; StartAIBehaviorState(); SetCurrentTargetPos(); } public void InitHide(List hidePositions, float hideProbability) { m_HidePositions = hidePositions; m_HideProbability = hideProbability; } public void InitBoundaryPosition(Vector3 min, Vector3 max) { minBoundaryPos = min; maxBoundaryPos = max; } public void SetCrouchTimeProportion(float crouchTimeProportion) { m_CrouchTimeProportion = crouchTimeProportion; } public void SetSpeed(float speed) { m_NavMeshAgent.speed = speed; } private new void Update() { if (!IsRunning) return; base.Update(); if(Vector2.Distance(new Vector2(transform.position.x,transform.position.z), new Vector2(current_TargetPos.x, current_TargetPos.z)) <= 0.5f) { SetCurrentTargetPos(); } } private void SetCurrentTargetPos() { if (!m_NavMeshAgent.enabled) { m_NavMeshAgent.enabled = true; } if (!toBoundary) { toBoundary = ExtraTool.IsProbabolityInclusive(m_HideProbability) ? false : true; } if (toBoundary) { float x = Random.Range(minBoundaryPos.x, maxBoundaryPos.x); float z = Random.Range(minBoundaryPos.z, maxBoundaryPos.z); current_TargetPos = new Vector3(x, -2f, z); } else { current_TargetPos = m_HidePositions[Random.Range(0, m_HidePositions.Count)]; } m_NavMeshAgent.SetDestination(current_TargetPos); } private void StartAIBehaviorState() { AIBehaviorState nextState = ExtraTool.IsProbabolityInclusive(m_CrouchTimeProportion) ? AIBehaviorState.Crouch : AIBehaviorState.Stand; if (current_BehaviorState != nextState) { current_BehaviorState = nextState; SwitchAIBehaviorState(current_BehaviorState); } m_AIBehaviorStateChangeTimer = TimerSystem.GetInstance().AddTimeTask(StartAIBehaviorState, 5f); } private void SwitchAIBehaviorState(AIBehaviorState state) { switch (state) { case AIBehaviorState.Stand: m_Animator.SetTrigger("idle"); break; case AIBehaviorState.Crouch: m_Animator.SetTrigger("squat"); break; } } public override void CauseHumanoidPartReduceHP(HumanoidPartShotTarget part) { base.CauseHumanoidPartReduceHP(part); if ((m_MaxHealth - Health) == 1) { m_ShieldAnimator.gameObject.SetActive(true); m_ShieldObj.SetActive(false); } } private void OnDestroy() { TimerSystem.GetInstance().RemoveTimeTask(m_AIBehaviorStateChangeTimer); if (Health <= 0) { GameObject effectObj = Instantiate(Resources.Load("Prefabs/BrokenEffect"), transform.position + new Vector3(0, 0.5f, 0), Quaternion.identity); effectObj.transform.localScale = Vector3.one * 2; SpawnDebris(); } } private void SpawnDebris() { brokenFragment.transform.SetParent(null); brokenFragment.SetActive(true); foreach (Transform child in brokenFragment.transform) { // 随机选择碎片预制体 GameObject selectedDebris = child.gameObject; // 生成参数设置 Vector3 spawnPos = transform.position + Random.insideUnitSphere * 0.5f; Quaternion spawnRot = Random.rotation; selectedDebris.transform.position = spawnPos; selectedDebris.transform.rotation = spawnRot; // 添加物理组件 Rigidbody rb = selectedDebris.GetComponent(); if (rb == null) rb = selectedDebris.AddComponent(); // 施加随机方向力 Vector3 randomDir = new Vector3(Random.Range(-1f, 1f), Random.Range(0.5f, 1f), Random.Range(-1f, 1f)).normalized; float force = Random.Range(5f, 15f); rb.AddForce(randomDir * force, ForceMode.Impulse); // 添加随机旋转 rb.AddTorque(Random.insideUnitSphere * 50f, ForceMode.Impulse); } Destroy(brokenFragment, 0.5f); } public void SetPause(bool pause) { IsRunning = !pause; m_AIBehaviorStateChangeTimer.pause = pause; m_NavMeshAgent.isStopped = pause; } } }