using System.Collections.Generic; using BehaviorDesigner.Runtime; using BehaviorDesigner.Runtime.Tasks; using DragonLi.Core; using DragonLi.Frame; using Unity.VisualScripting; using UnityEngine; using UnityEngine.AI; public class CheckEnemyState : Conditional { public SharedInt curEnemyState; public override TaskStatus OnUpdate() { if (transform.GetComponent().enemyState == (EnemyState)curEnemyState.Value) { return TaskStatus.Success; } return TaskStatus.Failure; } } public class SetEnemyState : Action { public SharedInt curEnemyState; public override TaskStatus OnUpdate() { var enemy= transform.GetComponent(); if (enemy != null) { enemy.enemyState = (EnemyState)curEnemyState.Value; return TaskStatus.Success; } return base.OnUpdate(); } } public class MoveToPlayerNearby3 : Action { public SharedGameObject self; public SharedFloat minRange = new SharedFloat { Value = 3f }; public SharedFloat maxRange = new SharedFloat { Value = 10f }; public SharedFloat avoidRadius = new SharedFloat { Value = 2f }; public SharedLayerMask enemyLayer; public int maxAttempts = 15; private NavMeshAgent agent; private Vector3 targetPosition; public override void OnStart() { base.OnStart(); agent = GetComponent(); // 随机优先级,降低 agent 之间争路 agent.avoidancePriority = Random.Range(0, 100); agent.obstacleAvoidanceType = ObstacleAvoidanceType.HighQualityObstacleAvoidance; agent.autoBraking = false; Transform player = GameManager.Ins.player.transform; targetPosition = FindValidPosition(player); if (agent.isActiveAndEnabled) agent.SetDestination(targetPosition); } public override TaskStatus OnUpdate() { if (!agent.pathPending && agent.remainingDistance <= agent.stoppingDistance) return TaskStatus.Success; return TaskStatus.Running; } private Vector3 FindValidPosition(Transform player) { // 从 Manager 或其他地方拿到所有敌人的引用列表 List allEnemies = GameManager.Ins.curEnemyList; Vector3 bestPos = Vector3.zero; float bestScore = -1f; for (int i = 0; i < maxAttempts; i++) { // 1. 随机取点 Vector3 dir = Random.insideUnitSphere; dir.y = 0; dir.Normalize(); float dist = Random.Range(minRange.Value, maxRange.Value); Vector3 raw = player.position + dir * dist; // 2. NavMesh 采样 if (!NavMesh.SamplePosition(raw, out NavMeshHit hit, 2f, NavMesh.AllAreas)) continue; var cand = hit.position; // 3. 与玩家最小距离硬性筛掉 if (Vector3.Distance(cand, player.position) < minRange.Value) continue; // 4. 计算到其它每个敌人的最小距离 float minDistToOthers = float.MaxValue; foreach (var go in allEnemies) { if (go == null || go == self.Value) continue; float d = Vector3.Distance(cand, go.transform.position); minDistToOthers = Mathf.Min(minDistToOthers, d); if (minDistToOthers < avoidRadius.Value) break; // 太近了,提前跳出 } //5.如果通过了 avoidRadius,就直接返回 if (minDistToOthers >= avoidRadius.Value) return cand; // 6. 否则记录最佳分数点 if (minDistToOthers > bestScore) { bestScore = minDistToOthers; bestPos = cand; } } // 如果所有尝试都没严格过,也选“最远离群”的那个 if (bestScore > 0f) return bestPos; // 兜底:玩家前方一个安全距离 Vector3 fb = player.position + player.forward * minRange.Value; if (NavMesh.SamplePosition(fb, out NavMeshHit fh, 2f, NavMesh.AllAreas)) return fh.position; // 最后随机返回一个点 return player.position + Random.insideUnitSphere * (minRange.Value + 0.5f); } // 调试画出可行区域 void OnDrawGizmosSelected() { if (self == null || self.Value != gameObject) return; Gizmos.color = Color.cyan; Gizmos.DrawWireSphere(targetPosition, 0.2f); } } public class MoveToPlayerFront : Action { public SharedFloat minDistance = new SharedFloat { Value = 3f }; public SharedFloat maxDistance = new SharedFloat { Value = 5f }; public SharedFloat minAngle = new SharedFloat { Value = 30f }; public SharedFloat maxAngle = new SharedFloat { Value = 40f }; // 添加静态字典记录每个怪物的移动状态 private static Dictionary hasMoved = new Dictionary(); private NavMeshAgent agent; private bool hasReachedPosition; private Vector3 finalPosition; // 存储最终位置 // 添加静态字典记录每个敌人的移动状态 private static Dictionary hasMovedDict = new Dictionary(); private int instanceID; public override void OnAwake() { instanceID = gameObject.GetInstanceID(); } public override void OnStart() { // 检查是否已经移动过 if (hasMovedDict.ContainsKey(instanceID) && hasMovedDict[instanceID]) { hasReachedPosition = true; return; } agent = GetComponent(); agent.autoBraking = true; agent.stoppingDistance = 0.1f; // 计算玩家正前方扇形区域内的随机位置 finalPosition = CalculateFrontPosition(); if (agent.isActiveAndEnabled) { agent.SetDestination(finalPosition); hasReachedPosition = false; } } public override TaskStatus OnUpdate() { // 如果已经移动过,直接返回成功 if (hasMovedDict.ContainsKey(instanceID) && hasMovedDict[instanceID]) { return TaskStatus.Success; } if (hasReachedPosition) { //标记为已移动 hasMovedDict[instanceID] = true; return TaskStatus.Success; } // 检查是否到达目标位置 if (!agent.pathPending && agent.remainingDistance <= agent.stoppingDistance) { // 完全停止导航系统 agent.isStopped = true; agent.ResetPath(); agent.enabled = false; // 禁用导航组件 // 固定位置 transform.position = finalPosition; // 添加物理约束(如果有刚体) Rigidbody rb = GetComponent(); if (rb != null) { rb.isKinematic = true; rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } // 标记为已移动 hasMoved[gameObject] = true; hasReachedPosition = true; return TaskStatus.Success; } return TaskStatus.Running; } private Vector3 CalculateFrontPosition() { Transform player = GameManager.Ins.player.transform; Vector3 playerPos = player.position; Vector3 playerForward = player.forward; // 随机角度 (30-40度之间,随机左右侧) float randomAngle = Random.Range(minAngle.Value, maxAngle.Value) * (Random.value > 0.5f ? 1f : -1f); // 随机距离 float randomDistance = Random.Range(minDistance.Value, maxDistance.Value); // 计算方向向量 (玩家前方旋转随机角度) Quaternion rotation = Quaternion.Euler(0f, randomAngle, 0f); Vector3 direction = rotation * playerForward; // 计算目标位置 Vector3 targetPos = playerPos + direction * randomDistance; // 确保位置在NavMesh上 if (NavMesh.SamplePosition(targetPos, out NavMeshHit hit, 5f, NavMesh.AllAreas)) // 增加采样范围 { // 确保不会出现在半空中 if (Mathf.Abs(hit.position.y - playerPos.y) > 2f) { // 如果高度差太大,调整到玩家高度 return new Vector3(hit.position.x, playerPos.y, hit.position.z); } return hit.position; } // 如果采样失败,使用玩家位置(确保不会出现在半空中) return playerPos + Vector3.up * 0.1f; // 稍微高于地面 } // 当敌人被销毁时清理记录 public override void OnEnd() { if (hasMovedDict.ContainsKey(instanceID)) { hasMovedDict.Remove(instanceID); } } } public class SetAttackState : Action { public SharedBool attackState; // 添加静态字典记录每个敌人的攻击状态 private static Dictionary attackStateSet = new Dictionary(); private int instanceID; public override void OnAwake() { instanceID = gameObject.GetInstanceID(); } public override TaskStatus OnUpdate() { // 如果已经设置过攻击状态,直接返回成功 if (attackStateSet.ContainsKey(instanceID) && attackStateSet[instanceID]) { return TaskStatus.Success; } Enemy1 enemy = GetComponent(); if (enemy != null) { enemy.SetAttackState(attackState.Value); // 标记为已设置 attackStateSet[instanceID] = true; return TaskStatus.Success; } return TaskStatus.Failure; } // 当敌人被销毁时清理记录 public override void OnEnd() { if (attackStateSet.ContainsKey(instanceID)) { attackStateSet.Remove(instanceID); } } } /// /// 检测boss是否到阶段血量 /// public class CheckEnemyHp : Conditional { public SharedFloat hpIndex; public override TaskStatus OnUpdate() { var curHpIndex = transform.GetComponent().health/transform.GetComponent().maxHealth; if (curHpIndex <= hpIndex.Value) { return TaskStatus.Success; } return TaskStatus.Failure; } } public class UserSkill : Action { public Enemy EnemyObj; public SharedFloat hpIndex; public override void OnStart() { base.OnStart(); EnemyObj = transform.GetComponent(); } public override TaskStatus OnUpdate() { if (EnemyObj == null) return TaskStatus.Failure; var curHpIndex = EnemyObj.health/EnemyObj.maxHealth; if (curHpIndex <= hpIndex.Value) { EnemyObj.userSillIng = false; } var isUserIng = EnemyObj.userSillIng; if (isUserIng) return TaskStatus.Running; return TaskStatus.Success; } } public class BossIsUserSkill : Conditional { public override TaskStatus OnUpdate() { Enemy curEnemy = GetComponent(); if(curEnemy.userSillIng) return TaskStatus.Success; return TaskStatus.Failure; } } public class BossIsAttackState : Conditional { public override TaskStatus OnUpdate() { Enemy curEnemy = GetComponent(); if(curEnemy.isAttack) return TaskStatus.Success; return TaskStatus.Failure; } } public class BossIsQteAttack : Conditional { public SharedBool isQteAttack; public override TaskStatus OnUpdate() { if(isQteAttack.Value) return TaskStatus.Success; return TaskStatus.Failure; } } public class WaitAllPetDie : Action { public override TaskStatus OnUpdate() { if (GameManager.Ins.IsAllBossPetDie()) { Enemy curEnemy = GetComponent(); if (curEnemy) { curEnemy.isShield = false; curEnemy.shieldObj.SetActive(false); } return TaskStatus.Success; } return TaskStatus.Running; } } public class IsBossGunDie : Conditional { public SharedString GunIdStr; private List gunIdList; public override void OnStart() { base.OnStart(); gunIdList=new List(); string[] str=GunIdStr.Value.Split(','); foreach (var item in str) { gunIdList.Add(int.Parse(item)); } } public override TaskStatus OnUpdate() { Enemy curEnemy = GetComponent(); foreach (var id in gunIdList) { if (curEnemy.components[id] != null && !curEnemy.components[id].isDead) { return TaskStatus.Failure; } } return TaskStatus.Success; } } public class BossQteAttack : Action { private Enemy _curEnemy; public float QteTime; public SharedBool IsQteAttacked; public SharedBool IsStopQteAttacked; private float _currentQteTime; public override void OnStart() { base.OnStart(); //QteTime = 5; _curEnemy = GetComponent(); if (_curEnemy) { IsQteAttacked.Value = false; _curEnemy.StartQteAttack(); } } public override TaskStatus OnUpdate() { _currentQteTime += Time.deltaTime; if (_curEnemy.components[^1] != null && _curEnemy.components[^1].isDead) { IsStopQteAttacked.Value =true; _curEnemy.StopQteAttack(); return TaskStatus.Success; } if (_currentQteTime >= QteTime) { IsStopQteAttacked.Value =false; _curEnemy.ThreeAttackMode(); return TaskStatus.Success; } return TaskStatus.Running; } } public class CooldownTick : Action { public SharedFloat cooldownTimer; public SharedBool skillReady; public SharedFloat hp; public override TaskStatus OnUpdate() { Enemy curEnemy = GetComponent(); var curHpIndex = curEnemy.health/curEnemy.maxHealth; if (curHpIndex <= hp.Value) { skillReady.Value = false; cooldownTimer.Value = 15; return TaskStatus.Success; } if (cooldownTimer.Value > 0f) { cooldownTimer.Value -= Time.deltaTime; if (cooldownTimer.Value <= 0f) { cooldownTimer.Value = 0f; skillReady.Value = true; return TaskStatus.Success; } } return TaskStatus.Running; } } public class ReleaseSkill : Action { public SharedFloat cooldownTimer; public SharedBool skillReady; public float skillCooldown = 15f; public override void OnStart() { base.OnStart(); // 进入冷却 cooldownTimer.Value = skillCooldown; skillReady.Value = false; } } public class NormalAttack : Action { private Enemy1 enemy; public override void OnAwake() { enemy = GetComponent(); } public override void OnStart() { //// 你的普攻逻辑 //Debug.Log("执行普攻"); //Enemy curEnemy = GetComponent(); //curEnemy.Attack(); if(enemy != null && !enemy.isAttack) { enemy.Attack(); } } } public class IsSkillReady : Conditional { public SharedBool skillReady; public override TaskStatus OnUpdate() { return skillReady.Value ? TaskStatus.Success : TaskStatus.Failure; } } public class ConditionalStopQte : Conditional { public SharedBool IsStopQteAttack; public override TaskStatus OnUpdate() { if(!IsStopQteAttack.Value) return TaskStatus.Success; return TaskStatus.Failure; } }