using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class Yeji : TargetAnimal { //动画播放器 AnimationPlayer ap; //寻路代理 NavMeshAgent agent; //血量 [System.NonSerialized] public int hp = 3; [System.NonSerialized] public TreeAreaRecorder treeAreaRecorder; [System.NonSerialized] public float flyPlaneHeight = 5; float currentHeight = 0; public void SetFlyHeight(float value) { currentHeight = value; float agentBaseOffset = value - flyPlaneHeight; this.agent.baseOffset = agentBaseOffset / 1.2f;//因为agent的baseoffset会受节点的scale影响 } void Awake() { ap = GetComponent(); agent = GetComponent(); this.agent.avoidancePriority = avoidancePriority; } static int _avoidancePriority = 0; static int avoidancePriority { get { if (_avoidancePriority < 50) { _avoidancePriority++; } else { _avoidancePriority = 1; } return _avoidancePriority; } } void Start() { //初始化自动策略 InitAutoStrategy(); } void Update() { //寻路过程监测 if (HasCloseToDestination()) { OnReachDestination(); } else { OnMovingToDestination(); } UpdateAction(); UpdateActionTime(); UpdateAutoStrategy(); } public void Disappear() { Destroy(this.gameObject); } public override void OnHit(Arrow arrow, Vector3 hitPoint, string partName) { arrow.Head().position = hitPoint + arrow.transform.forward * 0.1f; arrow.Hit(); if (partName == "Wing") { hp -= 1; this.agent.speed /= 2f; } else if (partName == "Body") hp -= 2; else if (partName == "Head") hp -= 3; if (hp <= 0) { Die(arrow); } else { Hurt(); } } void Die(Arrow arrow) { if (dead) return; arrow.onDoNextShoot += delegate() { Disappear(); }; dead = true; this.agent.enabled = false; PuaseAutoStrategy(); onDie?.Invoke(this); AudioMgr.ins.PlayAnimalEffect("bird_die", AudioMgr.GetAudioSource(this.gameObject)); AudioMgr.ins.PlayCheer(true); if (currentHeight < 1.5f) { arrow.arrowCameraComp.arrowCameraTemplate.SendMsg(0, null); } } void Hurt() { CancelStand(); AudioMgr.ins.PlayAnimalEffect("bird_injured", AudioMgr.GetAudioSource(this.gameObject)); } //站立状态 bool standing = false; //是否已经死亡 [System.NonSerialized] public bool dead = false; //是否处于移动状态 bool _moving = false; bool moving { get { return _moving; } set { if (_moving != value) { movingTime = 0; stayingTime = 0; } _moving = value; } } //实时记录“单次移动的持续时间” float movingTime = 0; //实时停留时间 float stayingTime = 0; //启动寻路 void SetDestination(Vector3 pos) { moving = true; this.agent.destination = pos; } //寻路过程 void OnMovingToDestination() { if (!moving) return; } //寻路结束 void OnReachDestination() { if (!moving) return; moving = false; } //是否已经接近目的地(寻路完成判断) bool HasCloseToDestination() { if (!moving) return true; if (movingTime > 0.1) { if (this.agent.velocity.magnitude < 0.05f) { return true; } } return false; } //更新动作 void UpdateAction() { if (dead) { if (!isAniDie()) playAniDie(); } else if (standing) { if (!isAniStand()) playAniStand(); } else { if (!isAniFly()) playAniFly(); } } //记录动作时间 void UpdateActionTime() { if (moving) { movingTime += Time.deltaTime; } else { stayingTime += Time.deltaTime; } } bool autoStrategy = true; //自动策略的更新逻辑 void UpdateAutoStrategy() { if (!autoStrategy) return; RandomMove(); } void InitAutoStrategy() { autoStrategy = true; } void PuaseAutoStrategy() { autoStrategy = false; } //逃跑远离猎人 void RunAwayFromHunter() { Vector3 backVec = GetPointerHunterToMe(); SetDestination(transform.position + backVec.normalized * 5); } float toFlyHeight = 1.5f; float canStandTime = 3f; bool toUp = false; bool toLand = false; //能够在前几棵树徘徊 [System.NonSerialized] public int canFlyTreeCount = 4; //将会绕树转 bool willMoveRoundTree = false; Queue roundTreePostions = new Queue(); //随机移动 void RandomMove() { if (dead) return; if (moving) { if (toUp) { float nextFlyHeight = currentHeight + Time.deltaTime * 1f; if (nextFlyHeight > toFlyHeight) { nextFlyHeight = toFlyHeight; toUp = false; } SetFlyHeight(nextFlyHeight); return; } if (toLand) { float nextH = currentHeight - Time.deltaTime * 1.5f; if (nextH < 0) { nextH = 0; toLand = false; //进入站立状态 standing = true; canStandTime = 2f + Random.value * 3f; Stay(); } SetFlyHeight(nextH); return; } return; } if (standing) { canStandTime -= Time.deltaTime; if (canStandTime <= 0) { CancelStand(); } return; } if (willMoveRoundTree && roundTreePostions.Count > 0) { Vector3 pos = roundTreePostions.Dequeue(); SetDestination(pos); return; } else { willMoveRoundTree = false; } bool isOnLand = currentHeight < 0.001f; if (!isOnLand) { if (Random.value < 0.5) { toLand = true; return; } } //规划下一次行动路线 Vector3 myPos = this.transform.position; TreeAreaRecorder.AreaInfo[] areaInfos = treeAreaRecorder.copyAreaInfos(canFlyTreeCount); for (int i = 0; i < canFlyTreeCount; i++) { areaInfos[i].teamCompareValue = areaInfos[i].distanceInHorizontal(myPos); } System.Array.Sort(areaInfos, new ComparerAreaInfosByDistance()); //如果离这棵树比较近,有几率使其绕着树转 TreeAreaRecorder.AreaInfo firstAreaInfo = areaInfos[0]; bool isNearTree4th = areaInfos.Length == 4 && firstAreaInfo == treeAreaRecorder.getValidAreaInfo(3); if (!isNearTree4th && firstAreaInfo.teamCompareValue < firstAreaInfo.radius + 1.5f && Random.value < 0.5) { willMoveRoundTree = true; Vector3 treePos = areaInfos[0].transform.position; treePos.y = myPos.y; Vector3 pointer = myPos - treePos; roundTreePostions.Clear(); int direction = Random.value >= 0.5 ? 1 : -1; for (int i = 1; i <= 6; i++) { roundTreePostions.Enqueue(treePos + Quaternion.AngleAxis(i * 60 * direction, Vector3.up) * pointer); } RandomMove(); return; } TreeAreaRecorder.AreaInfo areaInfo = areaInfos[Random.Range(1, canFlyTreeCount)]; Vector3 newPos = YejiHuntGameMode.CalculateNewPosByTreePos(animalsBaseT, flyPlaneHeight, areaInfo); SetDestination(newPos); } class ComparerAreaInfosByDistance : IComparer { public int Compare(object x, object y) { TreeAreaRecorder.AreaInfo a = (TreeAreaRecorder.AreaInfo)x; TreeAreaRecorder.AreaInfo b = (TreeAreaRecorder.AreaInfo)y; if (a.teamCompareValue - b.teamCompareValue > 0) return 1; if (a.teamCompareValue - b.teamCompareValue < 0) return -1; else return 0; } } //停留 void Stay() { if (moving) { this.agent.destination = this.agent.nextPosition; OnReachDestination(); } } //取消站在地上 void CancelStand() { if (standing) { standing = false; toUp = true; toFlyHeight = 1.5f + Random.value * 2.5f; } } //当前动画索引 int curAnimIndex = -1; void playAniDie() { ap.play(curAnimIndex = 1, WrapMode.Once); } bool isAniDie() { return curAnimIndex == 1; } void playAniFly() { ap.play(curAnimIndex = 0, WrapMode.Loop); } bool isAniFly() { return curAnimIndex == 0; } void playAniStand() { ap.play(curAnimIndex = 2, WrapMode.Loop); } bool isAniStand() { return curAnimIndex == 2; } //委托 public System.Action onDie; }