Rabbit.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.AI;
  5. public class Rabbit : TargetAnimal
  6. {
  7. //动画播放器
  8. AnimationPlayer ap;
  9. //寻路代理
  10. NavMeshAgent agent;
  11. //血量
  12. [System.NonSerialized] public int hp = 1;
  13. [SerializeField] Material[] materials;
  14. public void ChangeColorByType(int type) {
  15. GetComponentInChildren<SkinnedMeshRenderer>().material = materials[type - 1];
  16. }
  17. void Awake()
  18. {
  19. ap = GetComponent<AnimationPlayer>();
  20. agent = GetComponent<NavMeshAgent>();
  21. }
  22. void Start()
  23. {
  24. //不同个体动画播放速度差异化
  25. ap.speed = Random.value * 0.2f + 0.8f;
  26. //初始动画
  27. playAniForIdle();
  28. //初始化自动策略
  29. InitAutoStrategy();
  30. }
  31. void Update()
  32. {
  33. //寻路过程监测
  34. if (HasCloseToDestination()) {
  35. OnReachDestination();
  36. } else {
  37. OnMovingToDestination();
  38. }
  39. UpdateAction();
  40. UpdateActionTime();
  41. UpdateAutoStrategy();
  42. }
  43. public void Disappear() {
  44. Destroy(this.gameObject);
  45. }
  46. public override void OnHit(Arrow arrow, Vector3 hitPoint, string partName)
  47. {
  48. arrow.Head().position = hitPoint + arrow.transform.forward * 0.1f;
  49. arrow.Hit();
  50. if (partName == "Leg" || partName == "Ear") hp -= 1;
  51. else if (partName == "Body") hp -= 2;
  52. else if (partName == "Head") hp -= 3;
  53. if (hp <= 0) {
  54. Die(arrow);
  55. } else {
  56. Hurt();
  57. }
  58. }
  59. void Die(Arrow arrow) {
  60. if (dead) return;
  61. arrow.onDoNextShoot += delegate() {
  62. Disappear();
  63. };
  64. dead = true;
  65. this.agent.enabled = false;
  66. PuaseAutoStrategy();
  67. onDie?.Invoke(this);
  68. AudioMgr.ins.PlayAnimalEffect("rabbit_injured", AudioMgr.GetAudioSource(this.gameObject));
  69. }
  70. void Hurt() {
  71. RunAwayFromHunter();
  72. addHurtFlag();
  73. PuaseAutoStrategy();
  74. AudioMgr.ins.PlayAnimalEffect("rabbit_injured", AudioMgr.GetAudioSource(this.gameObject));
  75. }
  76. JC.CS.CountLocker hurtFlag = new JC.CS.CountLocker();
  77. void addHurtFlag() {
  78. hurtFlag.Lock();
  79. Invoke("clearOneHurtFlag", 5);
  80. }
  81. void clearOneHurtFlag() {
  82. hurtFlag.Unlock();
  83. if (hurtFlag.IsReleased()) {
  84. onHurtFlagTimeout();
  85. }
  86. }
  87. void onHurtFlagTimeout() {
  88. if (!dead) ResumeAutoStrategy();
  89. }
  90. //是否已经死亡
  91. bool dead = false;
  92. //是否处于移动状态
  93. bool _moving = false;
  94. bool moving {
  95. get {
  96. return _moving;
  97. }
  98. set {
  99. if (_moving && !value) {
  100. movingTime = 0;
  101. }
  102. if (!_moving && value) stayingTime = 0;
  103. _moving = value;
  104. }
  105. }
  106. //实时记录“单次移动的持续时间”
  107. float movingTime = 0;
  108. //实时停留时间
  109. float stayingTime = 0;
  110. //启动寻路
  111. void SetDestination(Vector3 pos) {
  112. moving = true;
  113. this.agent.destination = pos;
  114. }
  115. //寻路过程
  116. void OnMovingToDestination() {
  117. if (!moving) return;
  118. }
  119. //寻路结束
  120. void OnReachDestination() {
  121. if (!moving) return;
  122. moving = false;
  123. }
  124. //是否已经接近目的地(寻路完成判断)
  125. bool HasCloseToDestination() {
  126. if (!moving) return true;
  127. if (Vector3.Distance(this.agent.nextPosition, this.agent.destination) < 0.15f) {
  128. return true;
  129. }
  130. if (movingTime > 0.1f && this.agent.velocity.magnitude < 0.05f) {
  131. return true;
  132. }
  133. return false;
  134. }
  135. //更新动作
  136. void UpdateAction() {
  137. if (dead) {
  138. if (!isAniDie()) playAniDie();
  139. } else if (moving) {
  140. if (!isAniJump()) playAniJump();
  141. } else {
  142. if (!IsAniForIdle()) {
  143. playAniForIdle();
  144. }
  145. }
  146. }
  147. //记录动作时间
  148. void UpdateActionTime() {
  149. if (moving) {
  150. movingTime += Time.deltaTime;
  151. } else {
  152. stayingTime += Time.deltaTime;
  153. }
  154. }
  155. float willStayTime;
  156. float willMoveTime;
  157. bool autoMoving = false;
  158. float autoMovingTime;
  159. bool autoStrategy = true;
  160. //自动策略的更新逻辑
  161. void UpdateAutoStrategy() {
  162. if (!autoStrategy) return;
  163. if (stayingTime > willStayTime) {
  164. autoMoving = true;
  165. RandomMove();
  166. RandomWillStayTime();
  167. }
  168. if (autoMoving) {
  169. // if (moving) {
  170. // autoMovingTime += Time.deltaTime;
  171. // } else if (autoMovingTime < willMoveTime) {
  172. // RandomMove();
  173. // } else if (autoMovingTime >= willMoveTime) {
  174. // Stay();
  175. // RandomWillMoveTime();
  176. // autoMoving = false;
  177. // autoMovingTime = 0;
  178. // }
  179. if (!moving) {
  180. Stay();
  181. RandomWillMoveTime();
  182. autoMoving = false;
  183. autoMovingTime = 0;
  184. } else {
  185. autoMovingTime += Time.deltaTime;
  186. }
  187. }
  188. }
  189. void InitAutoStrategy() {
  190. autoStrategy = true;
  191. this.willStayTime = 3 + Random.value * 4;
  192. RandomWillMoveTime();
  193. }
  194. void PuaseAutoStrategy() {
  195. this.autoStrategy = false;
  196. }
  197. void ResumeAutoStrategy() {
  198. this.autoStrategy = true;
  199. RandomWillStayTime();
  200. RandomWillMoveTime();
  201. this.autoMoving = false;
  202. this.autoMovingTime = 0;
  203. }
  204. void RandomWillStayTime() {
  205. this.willStayTime = Random.value * 2 + 10;
  206. }
  207. void RandomWillMoveTime() {
  208. this.willMoveTime = Random.value * 2 + 3;
  209. }
  210. //逃跑远离猎人
  211. void RunAwayFromHunter()
  212. {
  213. Vector3 backVec = GetPointerHunterToMe();
  214. SetDestination(transform.position + backVec.normalized * 5);
  215. }
  216. [System.NonSerialized] public float baseDistance = 10;
  217. [System.NonSerialized] public float baseDistanceMoveRange = 3;
  218. //随机移动
  219. void RandomMove() {
  220. Vector3 standardPointer = animalsBaseT.forward;
  221. Vector3 pointerWithLen = standardPointer.normalized * (baseDistance + Random.value * baseDistanceMoveRange);
  222. pointerWithLen = Quaternion.AngleAxis(-30f + Random.value * 60f, Vector3.up) * pointerWithLen;
  223. Vector3 newPos = animalsBaseT.position + pointerWithLen;
  224. // GameObject.Find("BBAA").transform.position = newPos;
  225. // GameObject.Find("BBBA").transform.LookAt(GameObject.Find("BBAA").transform);
  226. SetDestination(newPos);
  227. }
  228. //停留
  229. void Stay() {
  230. if (moving) {
  231. this.agent.destination = this.agent.nextPosition;
  232. OnReachDestination();
  233. }
  234. }
  235. //当前动画索引
  236. int curAnimIndex = 0;
  237. void playAniEat() {
  238. ap.play(curAnimIndex = 0, WrapMode.Loop);
  239. }
  240. bool isAniEat() {
  241. return curAnimIndex == 0;
  242. }
  243. void playAniDie() {
  244. ap.play(curAnimIndex = 2, WrapMode.Once);
  245. }
  246. bool isAniDie() {
  247. return curAnimIndex == 2;
  248. }
  249. void playAniJump() {
  250. ap.play(curAnimIndex = 7, WrapMode.Loop);
  251. }
  252. bool isAniJump() {
  253. return curAnimIndex == 7;
  254. }
  255. bool IsAniForIdle() {
  256. return curAnimIndex == 0 || curAnimIndex == 4 || curAnimIndex == 5 || curAnimIndex == 6;
  257. }
  258. int[] idleIndexes = {0, 4, 5, 6};
  259. void playAniForIdle() {
  260. curAnimIndex = idleIndexes[Random.Range(0, idleIndexes.Length)];
  261. ap.play(curAnimIndex, WrapMode.Loop);
  262. }
  263. //委托
  264. public System.Action<Rabbit> onDie;
  265. }