Rabbit.cs 7.7 KB

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