|
@@ -27,7 +27,6 @@ public class Yeji : TargetAnimal
|
|
|
animator = GetComponent<Animator>();
|
|
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 {
|
|
@@ -42,7 +41,7 @@ public class Yeji : TargetAnimal
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void OnDestroy() {
|
|
void OnDestroy() {
|
|
|
- ReleaseLandLock();
|
|
|
|
|
|
|
+ tryReleaseOccupyTree();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Update()
|
|
void Update()
|
|
@@ -145,12 +144,11 @@ public class Yeji : TargetAnimal
|
|
|
|
|
|
|
|
float toFlyHeight = 2f;
|
|
float toFlyHeight = 2f;
|
|
|
float canStandTime = 3f;
|
|
float canStandTime = 3f;
|
|
|
|
|
+ float canFlyStayTime = 3f;
|
|
|
//能够在前几棵树徘徊
|
|
//能够在前几棵树徘徊
|
|
|
[System.NonSerialized] public int canFlyTreeCount = 4;
|
|
[System.NonSerialized] public int canFlyTreeCount = 4;
|
|
|
- //将会绕树转
|
|
|
|
|
- bool willMoveRoundTree = false;
|
|
|
|
|
- Queue<Vector3> roundTreePostions = new Queue<Vector3>();
|
|
|
|
|
- //随机移动
|
|
|
|
|
|
|
+ const float downSpeed = 2.0f;
|
|
|
|
|
+ //更新逻辑-起飞降落
|
|
|
void UpdateFlyUpDown() {
|
|
void UpdateFlyUpDown() {
|
|
|
if (state.up && state.landing) { //起飞阶段
|
|
if (state.up && state.landing) { //起飞阶段
|
|
|
AnimatorStateInfo animatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
|
AnimatorStateInfo animatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
|
@@ -159,7 +157,6 @@ public class Yeji : TargetAnimal
|
|
|
if (animatorStateInfo.normalizedTime >= 1.0) {
|
|
if (animatorStateInfo.normalizedTime >= 1.0) {
|
|
|
state.landing = false;
|
|
state.landing = false;
|
|
|
state.flying = true;
|
|
state.flying = true;
|
|
|
- Invoke("ReleaseLandLock", Random.value * 3f + 1.0f);
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return;
|
|
return;
|
|
@@ -178,7 +175,7 @@ public class Yeji : TargetAnimal
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
if (state.down && state.flying) { //下降阶段
|
|
if (state.down && state.flying) { //下降阶段
|
|
|
- float nextH = currentHeight - Time.deltaTime * 2f;
|
|
|
|
|
|
|
+ float nextH = currentHeight - Time.deltaTime * downSpeed;
|
|
|
if (nextH <= 0) { //下降完成
|
|
if (nextH <= 0) { //下降完成
|
|
|
nextH = 0;
|
|
nextH = 0;
|
|
|
state.landing = true;
|
|
state.landing = true;
|
|
@@ -203,9 +200,18 @@ public class Yeji : TargetAnimal
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- float willFlyTime;
|
|
|
|
|
- float flyingTime;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ TreeAreaRecorder.AreaInfo targetAreaInfo;
|
|
|
|
|
+ bool hasCheckFlyDown = false;
|
|
|
void UpdateBehavior() {
|
|
void UpdateBehavior() {
|
|
|
|
|
+ if (state.flyStaying) {
|
|
|
|
|
+ canFlyStayTime -= Time.deltaTime;
|
|
|
|
|
+ if (canFlyStayTime <= 0) {
|
|
|
|
|
+ state.flyStaying = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (state.standing) {
|
|
if (state.standing) {
|
|
|
canStandTime -= Time.deltaTime;
|
|
canStandTime -= Time.deltaTime;
|
|
|
if (canStandTime <= 0) {
|
|
if (canStandTime <= 0) {
|
|
@@ -217,48 +223,37 @@ public class Yeji : TargetAnimal
|
|
|
if (state.landing) return;
|
|
if (state.landing) return;
|
|
|
|
|
|
|
|
if (state.flying && !state.down && !state.up) {
|
|
if (state.flying && !state.down && !state.up) {
|
|
|
- flyingTime += Time.deltaTime;
|
|
|
|
|
- if (flyingTime >= willFlyTime && DoLandLock()) {
|
|
|
|
|
- flyingTime = 0;
|
|
|
|
|
- state.down = true;
|
|
|
|
|
|
|
+ if (!hasCheckFlyDown) {
|
|
|
|
|
+ float downNeedTime = flyPlaneHeight / downSpeed;
|
|
|
|
|
+ float keyDistance = this.agent.speed * downNeedTime; //触发下降的水平距离阈值
|
|
|
|
|
+ if (Vector3.Distance(this.transform.position, this.agent.destination) < keyDistance) {
|
|
|
|
|
+ hasCheckFlyDown = true;
|
|
|
|
|
+ if (Random.value < 0.6 && tryOccupyTree()) {
|
|
|
|
|
+ state.down = true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ state.flyStaying = true;
|
|
|
|
|
+ canFlyStayTime = 4f + Random.value * 2f;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (moving) return;
|
|
if (moving) return;
|
|
|
|
|
|
|
|
- if (willMoveRoundTree && roundTreePostions.Count > 0) {
|
|
|
|
|
- Vector3 pos = roundTreePostions.Dequeue();
|
|
|
|
|
- SetDestination(pos);
|
|
|
|
|
- return;
|
|
|
|
|
- } else {
|
|
|
|
|
- willMoveRoundTree = false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //规划下一次行动路线
|
|
|
|
|
- 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);
|
|
|
|
|
|
|
+ //飞向别的树
|
|
|
|
|
+ #region
|
|
|
|
|
+ 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);
|
|
|
}
|
|
}
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- TreeAreaRecorder.AreaInfo areaInfo = areaInfos[Random.Range(1, canFlyTreeCount)];
|
|
|
|
|
- Vector3 newPos = YejiHuntGameMode.CalculateNewPosByTreePos(animalsBaseT, flyPlaneHeight, areaInfo);
|
|
|
|
|
- SetDestination(newPos);
|
|
|
|
|
|
|
+ System.Array.Sort(areaInfos, new ComparerAreaInfosByDistance());
|
|
|
|
|
+ TreeAreaRecorder.AreaInfo areaInfo = areaInfos[Random.Range(1, canFlyTreeCount)];
|
|
|
|
|
+ Vector3 newPos = YejiHuntGameMode.CalculateNewPosByTreePos(animalsBaseT, flyPlaneHeight, areaInfo);
|
|
|
|
|
+ SetDestination(newPos);
|
|
|
|
|
+ targetAreaInfo = areaInfo;
|
|
|
|
|
+ hasCheckFlyDown = false;
|
|
|
|
|
+ #endregion
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
class ComparerAreaInfosByDistance : IComparer {
|
|
class ComparerAreaInfosByDistance : IComparer {
|
|
@@ -276,45 +271,49 @@ public class Yeji : TargetAnimal
|
|
|
state.up = true;
|
|
state.up = true;
|
|
|
toFlyHeight = RandomOnePreHeight();
|
|
toFlyHeight = RandomOnePreHeight();
|
|
|
animator.CrossFade("FlyFromGround", 0.1f);
|
|
animator.CrossFade("FlyFromGround", 0.1f);
|
|
|
- RandomWillFlyTime();
|
|
|
|
|
|
|
+ tryReleaseOccupyTree();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ bool tryOccupyTree() {
|
|
|
|
|
+ if (targetAreaInfo == null) return false;
|
|
|
|
|
+ if (targetAreaInfo.occupy != null) return false;
|
|
|
|
|
+ else {
|
|
|
|
|
+ targetAreaInfo.occupy = this;
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- void RandomWillFlyTime() {
|
|
|
|
|
- willFlyTime = 4 + Random.value * 3f;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ void tryReleaseOccupyTree() {
|
|
|
|
|
+ if (targetAreaInfo != null && targetAreaInfo.occupy != null && targetAreaInfo.occupy.Equals(this)) {
|
|
|
|
|
+ targetAreaInfo.occupy = null;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
static float[] preFlyHeights;
|
|
static float[] preFlyHeights;
|
|
|
- static int[] preFlyHeightCools;
|
|
|
|
|
|
|
+ static bool[] preFlyHeightCools;
|
|
|
public static void InitPreHeights() {
|
|
public static void InitPreHeights() {
|
|
|
- preFlyHeights = new float[]{2, 2.5f, 3, 3.5f, 4f};
|
|
|
|
|
- preFlyHeightCools = new int[]{0, 0, 0, 0, 0};
|
|
|
|
|
|
|
+ preFlyHeights = new float[]{1.7f, 2.2f};
|
|
|
|
|
+ preFlyHeightCools = new bool[]{false, false};
|
|
|
}
|
|
}
|
|
|
public static float RandomOnePreHeight() {
|
|
public static float RandomOnePreHeight() {
|
|
|
List<int> indexes = new List<int>();
|
|
List<int> indexes = new List<int>();
|
|
|
for (int i = 0; i < preFlyHeightCools.Length; i++) {
|
|
for (int i = 0; i < preFlyHeightCools.Length; i++) {
|
|
|
- if (preFlyHeightCools[i] > 0) preFlyHeightCools[i] = preFlyHeightCools[i] - 1;
|
|
|
|
|
- if (preFlyHeightCools[i] == 0) {
|
|
|
|
|
|
|
+ if (!preFlyHeightCools[i]) {
|
|
|
indexes.Add(i);
|
|
indexes.Add(i);
|
|
|
}
|
|
}
|
|
|
|
|
+ if (preFlyHeightCools[i]) preFlyHeightCools[i] = false;
|
|
|
}
|
|
}
|
|
|
int index = indexes[Random.Range(0, indexes.Count)];
|
|
int index = indexes[Random.Range(0, indexes.Count)];
|
|
|
- preFlyHeightCools[index] = 3;
|
|
|
|
|
|
|
+ preFlyHeightCools[index] = true;
|
|
|
return preFlyHeights[index];
|
|
return preFlyHeights[index];
|
|
|
}
|
|
}
|
|
|
- public static bool landLocked = false; //着陆锁,禁止地上同时存在两只鸟,避免穿模
|
|
|
|
|
- private bool myLandLocked = false;
|
|
|
|
|
- public bool DoLandLock() {
|
|
|
|
|
- if (landLocked) return false;
|
|
|
|
|
- return myLandLocked = landLocked = true;
|
|
|
|
|
- }
|
|
|
|
|
- public void ReleaseLandLock() {
|
|
|
|
|
- if (!myLandLocked) return;
|
|
|
|
|
- myLandLocked = landLocked = false;
|
|
|
|
|
- }
|
|
|
|
|
#endregion
|
|
#endregion
|
|
|
|
|
|
|
|
//状态
|
|
//状态
|
|
|
[System.Serializable]
|
|
[System.Serializable]
|
|
|
public class State {
|
|
public class State {
|
|
|
public bool standing = false;
|
|
public bool standing = false;
|
|
|
|
|
+ public bool flyStaying = false;
|
|
|
[SerializeField] private bool _dead;
|
|
[SerializeField] private bool _dead;
|
|
|
public bool dead {
|
|
public bool dead {
|
|
|
get { return _dead; }
|
|
get { return _dead; }
|