|
@@ -6,7 +6,7 @@ using UnityEngine.AI;
|
|
|
public class Yeji : TargetAnimal
|
|
public class Yeji : TargetAnimal
|
|
|
{
|
|
{
|
|
|
//动画播放器
|
|
//动画播放器
|
|
|
- AnimationPlayer ap;
|
|
|
|
|
|
|
+ Animator animator;
|
|
|
//寻路代理
|
|
//寻路代理
|
|
|
NavMeshAgent agent;
|
|
NavMeshAgent agent;
|
|
|
//血量
|
|
//血量
|
|
@@ -18,13 +18,16 @@ public class Yeji : TargetAnimal
|
|
|
currentHeight = value;
|
|
currentHeight = value;
|
|
|
float agentBaseOffset = value - flyPlaneHeight;
|
|
float agentBaseOffset = value - flyPlaneHeight;
|
|
|
this.agent.baseOffset = agentBaseOffset / 1.2f;//因为agent的baseoffset会受节点的scale影响
|
|
this.agent.baseOffset = agentBaseOffset / 1.2f;//因为agent的baseoffset会受节点的scale影响
|
|
|
|
|
+ state.flying = currentHeight > 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Awake()
|
|
void Awake()
|
|
|
{
|
|
{
|
|
|
- ap = GetComponent<AnimationPlayer>();
|
|
|
|
|
|
|
+ state.animal = this;
|
|
|
|
|
+ animator = GetComponent<Animator>();
|
|
|
agent = GetComponent<NavMeshAgent>();
|
|
agent = GetComponent<NavMeshAgent>();
|
|
|
this.agent.avoidancePriority = avoidancePriority;
|
|
this.agent.avoidancePriority = avoidancePriority;
|
|
|
|
|
+ RandomWillFlyTime();
|
|
|
}
|
|
}
|
|
|
static int _avoidancePriority = 0;
|
|
static int _avoidancePriority = 0;
|
|
|
static int avoidancePriority {
|
|
static int avoidancePriority {
|
|
@@ -38,10 +41,8 @@ public class Yeji : TargetAnimal
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void Start()
|
|
|
|
|
- {
|
|
|
|
|
- //初始化自动策略
|
|
|
|
|
- InitAutoStrategy();
|
|
|
|
|
|
|
+ void OnDestroy() {
|
|
|
|
|
+ ReleaseLandLock();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Update()
|
|
void Update()
|
|
@@ -52,276 +53,312 @@ public class Yeji : TargetAnimal
|
|
|
} else {
|
|
} else {
|
|
|
OnMovingToDestination();
|
|
OnMovingToDestination();
|
|
|
}
|
|
}
|
|
|
- UpdateAction();
|
|
|
|
|
- UpdateActionTime();
|
|
|
|
|
UpdateAutoStrategy();
|
|
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();
|
|
|
|
|
|
|
+ #region 被击触发
|
|
|
|
|
+ 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 Die(Arrow arrow) {
|
|
|
|
|
+ if (state.dead) return;
|
|
|
|
|
+ arrow.onDoNextShoot += delegate() {
|
|
|
|
|
+ Destroy(this.gameObject);
|
|
|
|
|
+ };
|
|
|
|
|
+ this.animator.speed = 1;
|
|
|
|
|
+ state.dead = true;
|
|
|
|
|
+ this.agent.enabled = false;
|
|
|
|
|
+ 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;
|
|
|
|
|
|
|
+ void Hurt() {
|
|
|
|
|
+ CancelStand();
|
|
|
|
|
+ AudioMgr.ins.PlayAnimalEffect("bird_injured", AudioMgr.GetAudioSource(this.gameObject));
|
|
|
}
|
|
}
|
|
|
- set {
|
|
|
|
|
- if (_moving != value) {
|
|
|
|
|
|
|
+ #endregion
|
|
|
|
|
+
|
|
|
|
|
+ #region 寻路导航
|
|
|
|
|
+ bool _moving;
|
|
|
|
|
+ bool moving {
|
|
|
|
|
+ get { return _moving; }
|
|
|
|
|
+ set {
|
|
|
movingTime = 0;
|
|
movingTime = 0;
|
|
|
- stayingTime = 0;
|
|
|
|
|
|
|
+ _moving = value;
|
|
|
}
|
|
}
|
|
|
- _moving = value;
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ float movingTime;
|
|
|
|
|
+ //启动寻路
|
|
|
|
|
+ void SetDestination(Vector3 pos) {
|
|
|
|
|
+ moving = true;
|
|
|
|
|
+ this.agent.destination = pos;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- //实时记录“单次移动的持续时间”
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ //寻路过程
|
|
|
|
|
+ void OnMovingToDestination() {
|
|
|
|
|
+ if (!moving) return;
|
|
|
|
|
+ movingTime += Time.deltaTime;
|
|
|
}
|
|
}
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- //更新动作
|
|
|
|
|
- void UpdateAction() {
|
|
|
|
|
- if (dead) {
|
|
|
|
|
- if (!isAniDie()) playAniDie();
|
|
|
|
|
- } else if (standing) {
|
|
|
|
|
- if (!isAniStand()) playAniStand();
|
|
|
|
|
- } else {
|
|
|
|
|
- if (!isAniFly()) playAniFly();
|
|
|
|
|
|
|
+ //寻路结束
|
|
|
|
|
+ void OnReachDestination() {
|
|
|
|
|
+ if (!moving) return;
|
|
|
|
|
+ moving = false;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- //记录动作时间
|
|
|
|
|
- void UpdateActionTime() {
|
|
|
|
|
- if (moving) {
|
|
|
|
|
- movingTime += Time.deltaTime;
|
|
|
|
|
- } else {
|
|
|
|
|
- stayingTime += Time.deltaTime;
|
|
|
|
|
|
|
+ //是否已经接近目的地(寻路完成判断)
|
|
|
|
|
+ bool HasCloseToDestination() {
|
|
|
|
|
+ if (!moving) return true;
|
|
|
|
|
+ return movingTime > 0.1 && this.agent.velocity.magnitude < 0.05f;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- 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<Vector3> roundTreePostions = new Queue<Vector3>();
|
|
|
|
|
- //随机移动
|
|
|
|
|
- void RandomMove() {
|
|
|
|
|
- if (dead) return;
|
|
|
|
|
|
|
+ //停止寻路
|
|
|
|
|
+ void StopNavigation() {
|
|
|
|
|
+ if (!moving) return;
|
|
|
|
|
+ this.agent.destination = this.agent.nextPosition;
|
|
|
|
|
+ this.agent.velocity = Vector3.zero;
|
|
|
|
|
+ this.transform.position = this.agent.destination;
|
|
|
|
|
+ OnReachDestination();
|
|
|
|
|
+ }
|
|
|
|
|
+ #endregion
|
|
|
|
|
|
|
|
- if (moving) {
|
|
|
|
|
- if (toUp) {
|
|
|
|
|
- float nextFlyHeight = currentHeight + Time.deltaTime * 1f;
|
|
|
|
|
- if (nextFlyHeight > toFlyHeight) {
|
|
|
|
|
|
|
+ #region 自动逻辑
|
|
|
|
|
+ //自动策略的更新逻辑
|
|
|
|
|
+ void UpdateAutoStrategy() {
|
|
|
|
|
+ if (state.dead) return;
|
|
|
|
|
+ UpdateFlyUpDown();
|
|
|
|
|
+ UpdateBehavior();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ float toFlyHeight = 2f;
|
|
|
|
|
+ float canStandTime = 3f;
|
|
|
|
|
+ //能够在前几棵树徘徊
|
|
|
|
|
+ [System.NonSerialized] public int canFlyTreeCount = 4;
|
|
|
|
|
+ //将会绕树转
|
|
|
|
|
+ bool willMoveRoundTree = false;
|
|
|
|
|
+ Queue<Vector3> roundTreePostions = new Queue<Vector3>();
|
|
|
|
|
+ //随机移动
|
|
|
|
|
+ void UpdateFlyUpDown() {
|
|
|
|
|
+ if (state.up && state.landing) { //起飞阶段
|
|
|
|
|
+ AnimatorStateInfo animatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
|
|
|
|
+ bool isTakeOff = animatorStateInfo.IsName("FlyFromGround");
|
|
|
|
|
+ if (isTakeOff) {
|
|
|
|
|
+ if (animatorStateInfo.normalizedTime >= 1.0) {
|
|
|
|
|
+ state.landing = false;
|
|
|
|
|
+ state.flying = true;
|
|
|
|
|
+ Invoke("ReleaseLandLock", Random.value * 3f + 1.0f);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (state.up && state.flying) { //上升阶段
|
|
|
|
|
+ float surplusHeight = toFlyHeight - currentHeight;
|
|
|
|
|
+ float smoothValue = surplusHeight / toFlyHeight;
|
|
|
|
|
+ float nextFlyHeight = currentHeight + Time.deltaTime * (1f + 2.5f * smoothValue);
|
|
|
|
|
+ this.animator.speed = 1f + 2f * smoothValue;
|
|
|
|
|
+ if (nextFlyHeight >= toFlyHeight) { //上升完成
|
|
|
nextFlyHeight = toFlyHeight;
|
|
nextFlyHeight = toFlyHeight;
|
|
|
- toUp = false;
|
|
|
|
|
|
|
+ this.animator.speed = 1;
|
|
|
|
|
+ state.up = false;
|
|
|
}
|
|
}
|
|
|
SetFlyHeight(nextFlyHeight);
|
|
SetFlyHeight(nextFlyHeight);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- if (toLand) {
|
|
|
|
|
- float nextH = currentHeight - Time.deltaTime * 1.5f;
|
|
|
|
|
- if (nextH < 0) {
|
|
|
|
|
|
|
+ if (state.down && state.flying) { //下降阶段
|
|
|
|
|
+ float nextH = currentHeight - Time.deltaTime * 2f;
|
|
|
|
|
+ if (nextH <= 0) { //下降完成
|
|
|
nextH = 0;
|
|
nextH = 0;
|
|
|
- toLand = false;
|
|
|
|
|
- //进入站立状态
|
|
|
|
|
- standing = true;
|
|
|
|
|
- canStandTime = 2f + Random.value * 3f;
|
|
|
|
|
- Stay();
|
|
|
|
|
|
|
+ state.landing = true;
|
|
|
|
|
+ state.flying = false;
|
|
|
|
|
+ StopNavigation();
|
|
|
}
|
|
}
|
|
|
SetFlyHeight(nextH);
|
|
SetFlyHeight(nextH);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (standing) {
|
|
|
|
|
- canStandTime -= Time.deltaTime;
|
|
|
|
|
- if (canStandTime <= 0) {
|
|
|
|
|
- CancelStand();
|
|
|
|
|
|
|
+ if (state.down && state.landing) { //着落阶段
|
|
|
|
|
+ AnimatorStateInfo animatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
|
|
|
|
+ bool isLand = animatorStateInfo.IsName("LandOnGround");
|
|
|
|
|
+ if (isLand) {
|
|
|
|
|
+ if (animatorStateInfo.normalizedTime >= 1.0) {
|
|
|
|
|
+ state.down = false;
|
|
|
|
|
+ //进入站立状态
|
|
|
|
|
+ state.standing = true;
|
|
|
|
|
+ canStandTime = 2f + Random.value * 3f;
|
|
|
|
|
+ animator.CrossFade("IdleOnGround2", 0.2f);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
- return;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+ float willFlyTime;
|
|
|
|
|
+ float flyingTime;
|
|
|
|
|
+ void UpdateBehavior() {
|
|
|
|
|
+ if (state.standing) {
|
|
|
|
|
+ canStandTime -= Time.deltaTime;
|
|
|
|
|
+ if (canStandTime <= 0) {
|
|
|
|
|
+ CancelStand();
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (willMoveRoundTree && roundTreePostions.Count > 0) {
|
|
|
|
|
- Vector3 pos = roundTreePostions.Dequeue();
|
|
|
|
|
- SetDestination(pos);
|
|
|
|
|
- return;
|
|
|
|
|
- } else {
|
|
|
|
|
- willMoveRoundTree = false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (state.landing) return;
|
|
|
|
|
+
|
|
|
|
|
+ if (state.flying && !state.down && !state.up) {
|
|
|
|
|
+ flyingTime += Time.deltaTime;
|
|
|
|
|
+ if (flyingTime >= willFlyTime && DoLandLock()) {
|
|
|
|
|
+ flyingTime = 0;
|
|
|
|
|
+ state.down = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (moving) 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;
|
|
|
|
|
|
|
+ //规划下一次行动路线
|
|
|
|
|
+ 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);
|
|
|
|
|
+ }
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+ TreeAreaRecorder.AreaInfo areaInfo = areaInfos[Random.Range(1, canFlyTreeCount)];
|
|
|
|
|
+ Vector3 newPos = YejiHuntGameMode.CalculateNewPosByTreePos(animalsBaseT, flyPlaneHeight, areaInfo);
|
|
|
|
|
+ SetDestination(newPos);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- //规划下一次行动路线
|
|
|
|
|
- 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);
|
|
|
|
|
|
|
+ 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;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- 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);
|
|
|
|
|
|
|
+ void CancelStand() {
|
|
|
|
|
+ if (!state.standing) return;
|
|
|
|
|
+ state.standing = false;
|
|
|
|
|
+ state.up = true;
|
|
|
|
|
+ toFlyHeight = RandomOnePreHeight();
|
|
|
|
|
+ animator.CrossFade("FlyFromGround", 0.1f);
|
|
|
|
|
+ RandomWillFlyTime();
|
|
|
|
|
+ }
|
|
|
|
|
+ void RandomWillFlyTime() {
|
|
|
|
|
+ willFlyTime = 4 + Random.value * 3f;
|
|
|
|
|
+ }
|
|
|
|
|
+ static float[] preFlyHeights;
|
|
|
|
|
+ static int[] preFlyHeightCools;
|
|
|
|
|
+ public static void InitPreHeights() {
|
|
|
|
|
+ preFlyHeights = new float[]{2, 2.5f, 3, 3.5f, 4f};
|
|
|
|
|
+ preFlyHeightCools = new int[]{0, 0, 0, 0, 0};
|
|
|
|
|
+ }
|
|
|
|
|
+ public static float RandomOnePreHeight() {
|
|
|
|
|
+ List<int> indexes = new List<int>();
|
|
|
|
|
+ for (int i = 0; i < preFlyHeightCools.Length; i++) {
|
|
|
|
|
+ if (preFlyHeightCools[i] > 0) preFlyHeightCools[i] = preFlyHeightCools[i] - 1;
|
|
|
|
|
+ if (preFlyHeightCools[i] == 0) {
|
|
|
|
|
+ indexes.Add(i);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- RandomMove();
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ int index = indexes[Random.Range(0, indexes.Count)];
|
|
|
|
|
+ preFlyHeightCools[index] = 3;
|
|
|
|
|
+ return preFlyHeights[index];
|
|
|
}
|
|
}
|
|
|
- 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;
|
|
|
|
|
|
|
+ public static bool landLocked = false; //着陆锁,禁止地上同时存在两只鸟,避免穿模
|
|
|
|
|
+ private bool myLandLocked = false;
|
|
|
|
|
+ public bool DoLandLock() {
|
|
|
|
|
+ if (landLocked) return false;
|
|
|
|
|
+ return myLandLocked = landLocked = true;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //停留
|
|
|
|
|
- void Stay() {
|
|
|
|
|
- if (moving) {
|
|
|
|
|
- this.agent.destination = this.agent.nextPosition;
|
|
|
|
|
- OnReachDestination();
|
|
|
|
|
|
|
+ public void ReleaseLandLock() {
|
|
|
|
|
+ if (!myLandLocked) return;
|
|
|
|
|
+ myLandLocked = landLocked = false;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
+ #endregion
|
|
|
|
|
|
|
|
- //取消站在地上
|
|
|
|
|
- void CancelStand() {
|
|
|
|
|
- if (standing) {
|
|
|
|
|
- standing = false;
|
|
|
|
|
- toUp = true;
|
|
|
|
|
- toFlyHeight = 1.5f + Random.value * 2.5f;
|
|
|
|
|
|
|
+ //状态
|
|
|
|
|
+ [System.Serializable]
|
|
|
|
|
+ public class State {
|
|
|
|
|
+ public bool standing = false;
|
|
|
|
|
+ [SerializeField] private bool _dead;
|
|
|
|
|
+ public bool dead {
|
|
|
|
|
+ get { return _dead; }
|
|
|
|
|
+ set {
|
|
|
|
|
+ _dead = value;
|
|
|
|
|
+ animal.animator.SetBool("dead", value);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+ [SerializeField] private bool _down;
|
|
|
|
|
+ public bool down {
|
|
|
|
|
+ get { return _down; }
|
|
|
|
|
+ set {
|
|
|
|
|
+ _down = value;
|
|
|
|
|
+ animal.animator.SetBool("down", value);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ [SerializeField] private bool _landing;
|
|
|
|
|
+ public bool landing {
|
|
|
|
|
+ get { return _landing; }
|
|
|
|
|
+ set {
|
|
|
|
|
+ _landing = value;
|
|
|
|
|
+ animal.animator.SetBool("landing", value);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ [SerializeField] private bool _up;
|
|
|
|
|
+ public bool up {
|
|
|
|
|
+ get { return _up; }
|
|
|
|
|
+ set {
|
|
|
|
|
+ _up = value;
|
|
|
|
|
+ animal.animator.SetBool("up", value);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ [SerializeField] private bool _flying;
|
|
|
|
|
+ public bool flying {
|
|
|
|
|
+ get { return _flying; }
|
|
|
|
|
+ set {
|
|
|
|
|
+ _flying = value;
|
|
|
|
|
+ animal.animator.SetBool("flying", value);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ public Yeji animal;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- //当前动画索引
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ [SerializeField] public State state = new State();
|
|
|
|
|
|
|
|
//委托
|
|
//委托
|
|
|
public System.Action<Yeji> onDie;
|
|
public System.Action<Yeji> onDie;
|