using System.Collections; using System.Collections.Generic; using BehaviorDesigner.Runtime; using DragonLi.Core; using Mirror; using Pathfinding; using Pathfinding.RVO; using UnityEngine; public enum PlayerAIState { Borning = 0, Charge = 1, Search = 2, Run = 3, Atk = 4, Die = 99, } public enum PlayerAIType { PlayerAI1=0, PlayerAI2=1, } public class PlayerAI : Agent { private BehaviorTree _behaviorTree; public BehaviorTree behaviorTree { get { if (_behaviorTree == null) _behaviorTree = GetComponent(); return _behaviorTree; } } private Collider _collider; public Collider selfCollider { get { if (_collider == null) _collider = GetComponent(); return _collider; } } public PlayerAIState state; [Header("编号")] [SyncVar] public int id = 0; [SyncVar] public PlayerAIType type; [Header("等级")] [SyncVar] public int lvl = 0; [Header("速度")] [SyncVar] public float speed = 0; [Header("攻击力")] [SyncVar] public float atk = 0; [Header("特殊攻击1攻击力")] [SyncVar] public float SpecialAtk1 = 0; [Header("特殊攻击2攻击力")] [SyncVar] public float SpecialAtk2 = 0; [Header("目标引用 (通常由 BT 设置)")] public GameObject target = null; public GunAiComponent gun; // 行为状态(本地/服务器) private bool updateAnimatorSpeedValue = false; private bool updateAnimatorSpeedFValue = false; private bool updateAnimatorSpeedRValue = false; // AI / 行为标志(server 上驱动) private bool introPlayed = false; private bool isAttacking = false; private bool isDead = false; void Awake() { InitAnimator(); } void InitAnimator() { // 检测 Animator 参数,以便按需设置 speed / speedf / speedr if (AnimatorComponent == null) return; AnimatorControllerParameter[] parameters = AnimatorComponent.parameters; foreach (AnimatorControllerParameter val in parameters) { if (val.type == AnimatorControllerParameterType.Float) { switch (val.name) { case "speed": updateAnimatorSpeedValue = true; break; case "speedr": updateAnimatorSpeedRValue = true; break; case "speedf": updateAnimatorSpeedFValue = true; break; } } } } [Server] public virtual void OnSpawn(int id, PlayerAIType type, int lvl,GameObject target) { base.OnSpawn(); this.id = id; this.type = type; state = PlayerAIState.Borning; this.lvl = lvl; AiInfo enemyInfo = GameManager.Ins.AiInfos[id]; speed = 1; atk = 1; health = 10; originHealth = 10; aiPath.enabled = true; aiPath.maxSpeed = speed; // 初始设置(server) if (isServer) { state = PlayerAIState.Borning; if (aiPath != null) aiPath.enabled = true; if (rvoController != null) rvoController.enabled = true; if (selfCollider != null) selfCollider.enabled = true; if (behaviorTree != null) { behaviorTree.enabled = true; behaviorTree.SetVariable("target",(SharedGameObject)target); } // 初始血量已在 Agent.OnSpawn 中设置为 originHealth / health } } private void Update() { OnUpdate(); } public override void OnUpdate() { // 只有 Server/Host 驱动移动(rvo / ai),其它客户端只做视觉播放(由 Rpc 通知) if (isServer && !isDead) { // 该方法在 Agent.Update 中由 Server 调用(以前你的实现) // 这里我们保持相同更新:更新动画参数 & 旋转等(只在 Server 上操作 AI/移动) if (aiPath != null && aiPath.enabled) { UpdateAnimatorValues(aiPath.velocity); } else if (RigidbodyComponent) { UpdateAnimatorValues(RigidbodyComponent.velocity); } UpdateRotation(); } } protected void UpdateAnimatorValues(Vector3 vel) { if (AnimatorComponent != null) { if (updateAnimatorSpeedValue) { AnimatorComponent.SetFloat("speed", vel.magnitude); } Vector3 val; if (updateAnimatorSpeedFValue) { val = Vector3.Project(vel, transform.forward); float num = vel.magnitude > 0 ? val.magnitude / (vel.magnitude * (Vector3.Angle(vel, transform.forward) > 90f ? -1f : 1f)) : 0f; AnimatorComponent.SetFloat("speedf", num); } if (updateAnimatorSpeedRValue) { val = Vector3.Project(vel, transform.right); float num2 = vel.magnitude > 0 ? val.magnitude / (vel.magnitude * (Vector3.Angle(vel, transform.right) > 90f ? -1f : 1f)) : 0f; AnimatorComponent.SetFloat("speedr", num2); } } // 如果使用 Animancer 且你希望通过脚本控制 walkClip 的播放,则在 UpdateLocalVisuals 中处理(下文) } public virtual void UpdateRotation() { if (target != null) { transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(target.transform.position.ReflectVectorXOZ() - transform.position), Time.deltaTime * 10f); } } private void LateUpdate() { Vector3 pos = transform.position; pos.y = 0f; // 或者设置为地面高度 transform.position = pos; } public virtual void DoAttack() { if (!isServer) return; // 攻击判定/伤害应由 Server 执行(Host 权威) AnimatorComponent.SetInteger("state",1); //调用枪械开枪脚本 gun.AiShoot(); } public virtual void StopAttack() { if (!isServer) return; // 攻击判定/伤害应由 Server 执行(Host 权威) AnimatorComponent.SetInteger("state",0); } public virtual void EndEvent() { } public void ChangeKillEnemyTime() { behaviorTree.SetVariable("CountdownTime",(SharedFloat)10f); } public void KillEnemyEvent() { //gun.Shoot() } }