Wolf.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.AI;
  5. using DG.Tweening;
  6. /* 动物组件-野狼 */
  7. public class Wolf : TargetAnimal
  8. {
  9. //动画播放器
  10. AnimationPlayer ap;
  11. //寻路代理
  12. NavMeshAgent agent;
  13. //血量
  14. [System.NonSerialized] public int hp = 1;
  15. void Awake()
  16. {
  17. wolfSet.Add(this);
  18. state = new State();
  19. ap = GetComponent<AnimationPlayer>();
  20. agent = GetComponent<NavMeshAgent>();
  21. this.onlineHandler.InitOnAwake(this);
  22. if (GameMgr.ins) {
  23. GameObject stoneObstacle = GameMgr.ins.transform.Find("StoneObstacle").gameObject;
  24. if (!stoneObstacle.activeSelf) stoneObstacle.SetActive(true);
  25. }
  26. }
  27. void Start()
  28. {
  29. if (onlineHandler.isMirror) return;
  30. initAniListener();
  31. }
  32. static int _avoidancePriority = 0;
  33. static int avoidancePriority {
  34. get {
  35. if (_avoidancePriority < 50) {
  36. _avoidancePriority++;
  37. } else {
  38. _avoidancePriority = 1;
  39. }
  40. return _avoidancePriority;
  41. }
  42. }
  43. void Update()
  44. {
  45. this.onlineHandler.Update();
  46. if (this.onlineHandler.isMirror) {
  47. UpdateOutline();
  48. return;
  49. }
  50. //寻路过程监测
  51. if (HasCloseToDestination()) {
  52. OnReachDestination();
  53. }
  54. UpdateAutoStrategy();
  55. UpdateAction();
  56. UpdateOutline();
  57. }
  58. void OnDestroy() {
  59. wolfSet.Remove(this);
  60. WolfActGrid.ins.areaMatrix.releaseOccupy(this);
  61. }
  62. //可选皮肤材质
  63. [SerializeField] Material[] materials;
  64. [SerializeField] Material[] outlineMaterials;
  65. [System.NonSerialized] public int colorType = -1;
  66. public void ChangeColorByType(int type) {
  67. colorType = type;
  68. if (skinnedMeshRenderer == null) skinnedMeshRenderer = GetComponentInChildren<SkinnedMeshRenderer>();
  69. baseMaterial = materials[type - 1];
  70. outlineMaterial = outlineMaterials[type - 1];
  71. skinnedMeshRenderer.material = baseMaterial;
  72. }
  73. Material baseMaterial;
  74. Material outlineMaterial;
  75. SkinnedMeshRenderer skinnedMeshRenderer = null;
  76. bool hasOutLine = false;
  77. void UpdateOutline() {
  78. Camera camera = Camera.main;
  79. if (!camera) return;
  80. float distance = Vector3.Distance(this.transform.position, camera.transform.position);
  81. if (distance > 20) {
  82. if (!hasOutLine) {
  83. hasOutLine = true;
  84. skinnedMeshRenderer.material = outlineMaterial;
  85. }
  86. } else {
  87. if (hasOutLine) {
  88. hasOutLine = false;
  89. skinnedMeshRenderer.material = baseMaterial;
  90. }
  91. }
  92. }
  93. public override void OnHit(Arrow arrow, Vector3 hitPoint, string partName)
  94. {
  95. arrow.Head().position = hitPoint + arrow.transform.forward * 0.1f;
  96. arrow.Hit();
  97. if (onlineHandler.isMirror) {
  98. onlineHandler.onHitData = onlineHandler.uid.ToString() + "," + partName;
  99. return;
  100. }
  101. OnHitLogic(arrow, partName);
  102. }
  103. public void OnHitLogic(Arrow arrow, string partName) {
  104. int hurtValue = 0;
  105. if (partName == "Leg" || partName == "Tail") {
  106. hurtValue = 2;
  107. }
  108. else if (partName == "Body") {
  109. hurtValue = 3;
  110. }
  111. else if (partName == "Head") {
  112. hurtValue = 10;
  113. }
  114. hp -= hurtValue;
  115. GameEventCenter.ins.onTargetAnimalHurt?.Invoke(this, hurtValue);
  116. if (hp > 0) {
  117. Hurt();
  118. } else {
  119. Die(arrow);
  120. }
  121. }
  122. void Die(Arrow arrow) {
  123. if (state.dead) return;
  124. if (arrow != null) {
  125. arrow.onDoNextShoot += delegate() {
  126. Destroy(this.gameObject);
  127. };
  128. } else {
  129. //需要借住关卡的GameMode来清除
  130. onlineHandler.onDoNextShootWillDestroy = true;
  131. }
  132. state.ResetActionState();
  133. state.dead = true;
  134. this.agent.enabled = false;
  135. onDie?.Invoke(this);
  136. AudioMgr.ins.PlayAnimalEffect("wolf_die", AudioMgr.GetAudioSource(this.gameObject));
  137. this.onlineHandler.deadID++;
  138. }
  139. void Hurt() {
  140. if (!state.attacking) {
  141. if (Random.value < 0.2f) {
  142. CancelLockTarget();
  143. state.ResetActionState();
  144. state.lockingTarget = true;
  145. needAmbush = false;
  146. } else {
  147. //未锁定目标阶段时被击退,因为可能会再次满足z路径条件,因此需要重置Z路径记录
  148. if (!state.lockingTarget) ResetZPathRecord();
  149. CancelLockTarget(1);
  150. RunAwayFromHunter();
  151. }
  152. }
  153. AudioMgr.ins.PlayAnimalEffect("wolf_injured", AudioMgr.GetAudioSource(this.gameObject));
  154. this.onlineHandler.injuredID++;
  155. }
  156. void SetAgentStopped(bool value) { //要捕捉错误,不然会报错
  157. try { this.agent.isStopped = value; } catch (System.Exception) {}
  158. }
  159. //启动寻路
  160. void SetDestination(Vector3 pos) {
  161. state.ResetActionState();
  162. state.moving = true;
  163. SetAgentStopped(false);
  164. if (useRunbackPoint) {
  165. useRunbackPoint = false;
  166. WolfActGrid.ins.areaMatrix.releaseOccupy(this);
  167. } else {
  168. bool occupySuccess = WolfActGrid.ins.areaMatrix.occupyPos(pos, this);
  169. if (!occupySuccess) {
  170. pos = transform.position;
  171. }
  172. }
  173. this.agent.destination = pos;
  174. }
  175. //寻路结束
  176. void OnReachDestination() {
  177. if (!state.moving) return;
  178. SetAgentStopped(true);
  179. state.ResetActionState();
  180. }
  181. //是否已经接近目的地(寻路完成判断)
  182. bool HasCloseToDestination() {
  183. if (!state.moving) return true;
  184. if (Vector3.Distance(this.agent.nextPosition, this.agent.destination) < 0.25f) {
  185. return true;
  186. }
  187. if (state.movingTime > 0.1f && this.agent.velocity.magnitude < 0.05f) {
  188. return true;
  189. }
  190. return false;
  191. }
  192. int lastAutoType;
  193. float willStayTime;
  194. bool willAttack = false;
  195. bool hasRunAround = false;
  196. int needRunAroundCount = 0;
  197. bool hasRunToHunter = false;
  198. //取消锁定状态
  199. //cancelType==1时,表示触发逃跑
  200. void CancelLockTarget(int cancelType = 0) {
  201. if (!state.lockingTarget) return;
  202. state.lockingTarget = false;
  203. if (cancelType == 1) state.lockingTarget = true;
  204. RandomWillStayTime();
  205. willAttack = false;
  206. hasRunAround = false;
  207. if (cancelType == 1) hasRunAround = true;
  208. needRunAroundCount = 0;
  209. if (cancelType == 1) needRunAroundCount = 2;
  210. hasRunToHunter = false;
  211. if (cancelType == 1) hasRunToHunter = true;
  212. }
  213. //帧更新逻辑-自动策略
  214. void UpdateAutoStrategy() {
  215. if (state.dead) return;
  216. if (state.lockingTarget) {
  217. // if (state.attacking) {
  218. // this.transform.LookAt(this.hunterPosition);
  219. // }
  220. if (!hasRunToHunter) {
  221. hasRunToHunter = true;
  222. RunToAttackHunter(true);
  223. willAttack = true;
  224. return;
  225. }
  226. if (!state.moving && !state.attacking) {
  227. if (willAttack) {
  228. willAttack = false;
  229. Attack();
  230. needRunAroundCount = 3;
  231. return;
  232. }
  233. if (needRunAroundCount > 0) {
  234. needRunAroundCount--;
  235. useRunbackPoint = !hasRunAround;
  236. RunAroundHunter(!hasRunAround);
  237. hasRunAround = true;
  238. return;
  239. }
  240. if (hasRunAround) {
  241. hasRunAround = false;
  242. RunToAttackHunter(false);
  243. }
  244. willAttack = true;
  245. return;
  246. }
  247. return;
  248. }
  249. //以下为未锁定目标时的自动策略
  250. if (state.staying) {
  251. if (state.stayingTime > willStayTime) {
  252. MoveSlowlyInZPath();
  253. }
  254. return;
  255. }
  256. if (state.moving) {
  257. lastAutoType = 2;
  258. }
  259. if (!state.staying && !state.moving) {
  260. if (lastAutoType == 1 || lastAutoType == 0) {
  261. MoveSlowlyInZPath();
  262. } else {
  263. if (!canCreateZPath && zPathPoints.Count == 0) {
  264. MoveSlowlyInZPath();//内含判断,状态将会转化为锁定目标
  265. } else {
  266. RandomWillStayTime();
  267. Stay(true);
  268. }
  269. }
  270. }
  271. }
  272. void RandomWillStayTime() {
  273. this.willStayTime = Random.value * 4 + 2;
  274. // this.willStayTime = 0;
  275. }
  276. void LookAtHunter() {
  277. this.transform.LookAt(hunterPosition);
  278. }
  279. bool needAmbush = true;
  280. //攻击
  281. void Attack() {
  282. state.ResetActionState();
  283. state.attacking = true;
  284. curAnimIndex = -1; /*注意:这样可避免狼两次使用同一攻击动作而第二次无法播放的情况 */
  285. int hurtValue = 2;
  286. if (canAttackID == "A") {
  287. int avoidancePriority = this.agent.avoidancePriority;
  288. float baseoffset = this.agent.baseOffset;
  289. Vector3 hunterPos = hunterPosition;
  290. Vector3 jumpPoint = default; //起跳点
  291. Vector3 landPoint = default; //落地点
  292. Vector3 displace = default; //位移
  293. Sequence seq = DOTween.Sequence();
  294. //伏击动作 + 转头
  295. Quaternion ambushQuaStart = transform.rotation;
  296. Vector3 rotateDir = hunterPos - transform.position; rotateDir.y = 0;
  297. Quaternion ambushQuaEnd = Quaternion.FromToRotation(Vector3.forward, rotateDir);
  298. float needRotateAngle = Quaternion.Angle(ambushQuaStart, ambushQuaEnd);
  299. this.agent.avoidancePriority = 0;
  300. if (needRotateAngle > 20) {
  301. state.ambushRotating = true;
  302. seq.Append(DOTween.To(() => 0f, value => {
  303. transform.rotation = Quaternion.Lerp(ambushQuaStart, ambushQuaEnd, value);
  304. }, 1f, needRotateAngle / 180f * 0.5f));
  305. } else {
  306. ambushQuaEnd = ambushQuaStart;
  307. }
  308. seq.AppendCallback(delegate() {
  309. state.ambushRotating = false;
  310. if (needAmbush) state.ambushing = true;
  311. });
  312. if (needAmbush) {
  313. seq.Append(DOTween.To(() => 0f, value => {
  314. this.transform.rotation = ambushQuaEnd;
  315. }, 1f, 2f));
  316. }
  317. seq.AppendCallback(delegate() {
  318. if (state.dead) {
  319. seq.Kill();
  320. return;
  321. }
  322. needAmbush = true;
  323. state.ambushing = false;
  324. state.attackA = true;
  325. #region //起点和终点计算
  326. jumpPoint = this.transform.position;
  327. hunterPos.y = jumpPoint.y;
  328. Vector3 deltaPointer = jumpPoint - hunterPos;
  329. landPoint = hunterPos + deltaPointer.normalized * 1f;
  330. displace = landPoint - jumpPoint;
  331. #endregion
  332. });
  333. //跳跃
  334. seq.Append(DOTween.To(() => 0f, value => {
  335. this.transform.position = jumpPoint + displace * value;
  336. LookAtHunter();
  337. if (value < 0.5) {
  338. this.agent.baseOffset = baseoffset + value;
  339. } else {
  340. this.agent.baseOffset = baseoffset + (1 - value);
  341. if (!state.dead && state.attackA) {
  342. state.attackA = false;
  343. playAniJumpDown();
  344. }
  345. }
  346. }, 1f, 0.8f));
  347. seq.AppendCallback(delegate() {
  348. this.agent.avoidancePriority = avoidancePriority;
  349. this.transform.position = landPoint;
  350. LookAtHunter();
  351. if (!state.dead) onAttack?.Invoke(this, hurtValue);
  352. });
  353. seq.Append(DOTween.To(() => 0f, value => {
  354. this.transform.position = landPoint;
  355. LookAtHunter();
  356. }, 1f, 0.3f));
  357. seq.AppendCallback(delegate() {
  358. if (!state.dead) stopAniJumpDown(); //停止动画,则动画自带的位移也停止变化
  359. this.transform.position = landPoint;
  360. LookAtHunter();
  361. });
  362. seq.Append(DOTween.To(() => 0f, value => {
  363. this.transform.position = landPoint;
  364. LookAtHunter();
  365. }, 1f, 0.1f)); //通过dotween是它不被动画的位移影响;
  366. seq.AppendCallback(delegate() {
  367. state.ResetActionState();
  368. });
  369. } else if (canAttackID == "B") {
  370. state.attackB = true;
  371. hurtValue = 3;
  372. onAttack?.Invoke(this, hurtValue);
  373. }
  374. }
  375. //逃跑远离猎人
  376. void RunAwayFromHunter()
  377. {
  378. Vector3 backVec = GetPointerHunterToMe();
  379. SetDestination(transform.position + backVec.normalized * 6);
  380. state.moveQuickly = true;
  381. this.agent.speed = 5f;
  382. }
  383. //跑到能攻击玩家的坐标点
  384. string canAttackID = null;
  385. void RunToAttackHunter(bool quickly) {
  386. float needDistance;
  387. Vector3 displace = GetPointerHunterToMe().normalized;
  388. // if (Random.value < 0.33f) {
  389. // needDistance = 2;
  390. // canAttackID = "B";
  391. // } else {
  392. needDistance = 11.5f;
  393. canAttackID = "A";
  394. // }
  395. Vector3 newPos = animalsBaseT.position + displace * needDistance;
  396. SetDestination(newPos);
  397. state.moveSlowly = !quickly;
  398. state.moveQuickly = quickly;
  399. agent.speed = quickly ? 5f : 0.8f;
  400. }
  401. //在敌人身边奔跑徘徊
  402. bool useRunbackPoint = false;
  403. void RunAroundHunter(bool quickly) {
  404. Vector3 newPos;
  405. if (useRunbackPoint) {
  406. newPos = WolfActGrid.ins.GetRunBackPointAfterPounce();
  407. } else {
  408. float baseDistance = 13;
  409. float baseDistanceMoveRange = 5;
  410. Vector3 standardPointer = animalsBaseT.forward;
  411. Vector3 pointerWithLen = standardPointer.normalized * (baseDistance + Random.value * baseDistanceMoveRange);
  412. pointerWithLen = Quaternion.AngleAxis(Random.Range(-14f, 14f), Vector3.up) * pointerWithLen;
  413. newPos = animalsBaseT.position + pointerWithLen;
  414. }
  415. SetDestination(newPos);
  416. state.moveSlowly = !quickly;
  417. state.moveQuickly = quickly;
  418. agent.speed = quickly ? 5f : 0.8f;
  419. }
  420. //Z字型路径
  421. Queue<Vector3> zPathPoints = new Queue<Vector3>();
  422. bool canCreateZPath = true;
  423. void ResetZPathRecord() {
  424. zPathPoints.Clear();
  425. canCreateZPath = true;
  426. }
  427. void MoveSlowlyInZPath() {
  428. if (zPathPoints.Count > 0) {
  429. SetDestination(zPathPoints.Dequeue());
  430. state.moveSlowly = true;
  431. agent.speed = 0.8f;
  432. return;
  433. }
  434. if (!canCreateZPath) {
  435. state.lockingTarget = true;
  436. return;
  437. }
  438. //构建Z字型路径
  439. zPathPoints.Clear();
  440. Vector3 standardVec = animalsBaseT.forward;
  441. Vector3 hunterPos = animalsBaseT.position;
  442. Vector3 myPos = this.transform.position;
  443. float minDistance = 13;
  444. float maxDistance = 25;
  445. while (true) {
  446. myPos.y = hunterPos.y;
  447. float distance = Vector3.Distance(myPos, hunterPos);
  448. if (distance > minDistance) {
  449. Vector3 vecToMyPos = myPos - hunterPos;
  450. //判断位置在猎人左边还是右边
  451. float crossY = Vector3.Cross(standardVec, vecToMyPos).y;
  452. float nextAngle;
  453. if (crossY >= 0) { //在右边
  454. nextAngle = Random.Range(-14f, -10f);//下次就向左边走
  455. } else { //在左边
  456. nextAngle = Random.Range(10f, 14f);;//下次就向右边走
  457. }
  458. float nextDistance = distance - Random.Range(3.5f, 4.5f);
  459. if (nextDistance > maxDistance) {
  460. nextDistance = maxDistance;
  461. }
  462. if (nextDistance < minDistance) {
  463. nextDistance = minDistance;
  464. }
  465. if (Mathf.Abs(nextDistance - distance) < 1.2f) {
  466. break;
  467. }
  468. Vector3 displace = (Quaternion.AngleAxis(nextAngle, Vector3.up) * standardVec) * nextDistance;
  469. myPos = hunterPos + displace;
  470. zPathPoints.Enqueue(myPos);
  471. // Debug.Log(Quaternion.AngleAxis(-180f, Vector3.up) * (myPos - hunterPos));
  472. } else {
  473. break;
  474. }
  475. }
  476. canCreateZPath = false;
  477. }
  478. //停留
  479. void Stay(bool correct = false) {
  480. if (state.moving || correct) {
  481. this.agent.destination = this.agent.nextPosition;
  482. SetAgentStopped(true);
  483. }
  484. state.ResetActionState();
  485. state.staying = true;
  486. }
  487. //动画播放
  488. [System.NonSerialized] public int curAnimIndex = -1;
  489. void playAniStay() {
  490. ap.play(curAnimIndex = 7, WrapMode.Loop);
  491. }
  492. bool isAniStay() {
  493. return curAnimIndex == 7;
  494. }
  495. void playAniMoveSlowly() {
  496. ap.play(curAnimIndex = 5, WrapMode.Loop);
  497. }
  498. bool isAniMoveSlowly() {
  499. return curAnimIndex == 5;
  500. }
  501. void playAniMoveQuickly() {
  502. ap.play(curAnimIndex = 4, WrapMode.Loop);
  503. }
  504. bool isAniMoveQuickly() {
  505. return curAnimIndex == 4;
  506. }
  507. void playAniAmbush() {
  508. ap.play(curAnimIndex = 3, WrapMode.Loop);
  509. }
  510. bool isAniAmbush() {
  511. return curAnimIndex == 3;
  512. }
  513. void playAniAttakA() {
  514. ap.play(curAnimIndex = 1, WrapMode.Once);
  515. }
  516. bool isAniAttakA() {
  517. return curAnimIndex == 1;
  518. }
  519. void playAniJumpDown() {
  520. ap.play(curAnimIndex = 6, WrapMode.Once);
  521. }
  522. void stopAniJumpDown() {
  523. ap.StopAnimation(6);
  524. }
  525. void playAniAttakB() {
  526. ap.play(curAnimIndex = 0, WrapMode.Once);
  527. }
  528. bool isAniAttakB() {
  529. return curAnimIndex == 0;
  530. }
  531. void playAniDie() {
  532. ap.play(curAnimIndex = 2, WrapMode.Once);
  533. }
  534. bool isAniDie() {
  535. return curAnimIndex == 2;
  536. }
  537. void initAniListener() {
  538. this.ap.completeCallback = delegate(AnimationPlayerCompleteResult res) {
  539. if (res.index == 0) {
  540. this.state.ResetActionState();
  541. }
  542. };
  543. }
  544. //帧更新逻辑-通过状态更新动作动画
  545. void UpdateAction() {
  546. if (state.staying) {
  547. state.stayingTime += Time.deltaTime;
  548. if (!isAniStay()) playAniStay();
  549. }
  550. else if (state.moving) {
  551. state.movingTime += Time.deltaTime;
  552. if (state.moveSlowly && !isAniMoveSlowly()) playAniMoveSlowly();
  553. if (state.moveQuickly && !isAniMoveQuickly()) playAniMoveQuickly();
  554. }
  555. else if (state.attacking) {
  556. if (state.ambushRotating && !isAniMoveQuickly()) playAniMoveQuickly();
  557. if (state.ambushing && !isAniAmbush()) playAniAmbush();
  558. if (state.attackA && !isAniAttakA()) playAniAttakA();
  559. if (state.attackB && !isAniAttakB()) playAniAttakB();
  560. }
  561. else if (state.dead) {
  562. if (!isAniDie()) playAniDie();
  563. }
  564. }
  565. //状态
  566. [System.Serializable]
  567. public class State {
  568. //动作区
  569. public bool staying = false;
  570. public bool moving = false;
  571. public bool moveSlowly = false; //慢走
  572. public bool moveQuickly = false; //跑动
  573. public bool attacking = false;
  574. public bool ambushRotating = false; //扑击前的转身
  575. public bool ambushing = false; //扑击前的伏击状态
  576. public bool attackA = false; //扑击
  577. public bool attackB = false; //撕咬
  578. public bool dead = false;
  579. public float stayingTime = 0;
  580. public float movingTime = 0;
  581. //特定区
  582. public bool lockingTarget = false; //锁定目标,只有锁定目标后,才能调用攻击接口,这是给自己的规定
  583. //重置动作区状态
  584. public void ResetActionState() {
  585. this.staying = false;
  586. this.moving = false;
  587. this.moveSlowly = false;
  588. this.moveQuickly = false;
  589. this.attacking = false;
  590. this.ambushRotating = false;
  591. this.ambushing = false;
  592. this.attackA = false;
  593. this.attackB = false;
  594. this.dead = false;
  595. this.stayingTime = 0;
  596. this.movingTime = 0;
  597. }
  598. }
  599. [SerializeField] public State state;
  600. //委托
  601. public System.Action<Wolf> onDie;
  602. public System.Action<Wolf, int> onAttack;
  603. #region 联机附加部分
  604. public static HashSet<Wolf> wolfSet = new HashSet<Wolf>();
  605. public OnlineHandler onlineHandler = new OnlineHandler();
  606. public class OnlineHandler {
  607. Wolf animal;
  608. public int uid;
  609. public bool isMirror;
  610. public WolfSyncData outputSyncData;
  611. public void InitOnAwake(Wolf animal) {
  612. this.animal = animal;
  613. if (isMirror) {
  614. GameObject.Destroy(this.animal.agent);
  615. }
  616. }
  617. public void Update() {
  618. if (isMirror) {
  619. if (inputSyncData == null) return;
  620. if (!hasUpdateBySyncData) {
  621. this.animal.transform.position = syncPosition;
  622. this.animal.transform.rotation = syncRotation;
  623. hasUpdateBySyncData = true;
  624. } else {
  625. this.animal.transform.position = Vector3.Lerp(this.animal.transform.position, syncPosition, Time.deltaTime * 15);
  626. this.animal.transform.rotation = Quaternion.Lerp(this.animal.transform.rotation, syncRotation, Time.deltaTime * 15);
  627. }
  628. if (this.animal.colorType != inputSyncData.ct) {
  629. this.animal.ChangeColorByType(inputSyncData.ct);
  630. }
  631. if (inputSyncData.ai != this.animal.curAnimIndex) {
  632. this.animal.curAnimIndex = inputSyncData.ai;
  633. if (this.animal.isAniStay()) {
  634. this.animal.playAniStay();
  635. } else if (this.animal.isAniMoveSlowly()) {
  636. this.animal.playAniMoveSlowly();
  637. } else if (this.animal.isAniMoveQuickly()) {
  638. this.animal.playAniMoveQuickly();
  639. } else if (this.animal.isAniAmbush()) {
  640. this.animal.playAniAmbush();
  641. } else if (this.animal.curAnimIndex >= 0) {
  642. this.animal.ap.play(this.animal.curAnimIndex, WrapMode.Once);
  643. }
  644. }
  645. if (inputSyncData.ii != injuredID) {
  646. injuredID = inputSyncData.ii;
  647. AudioMgr.ins.PlayAnimalEffect("wolf_injured", AudioMgr.GetAudioSource(this.animal.gameObject));
  648. }
  649. if (inputSyncData.di != deadID) {
  650. deadID = inputSyncData.di;
  651. AudioMgr.ins.PlayAnimalEffect("wolf_die", AudioMgr.GetAudioSource(this.animal.gameObject));
  652. }
  653. return;
  654. }
  655. if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
  656. if (outputSyncData == null) outputSyncData = new WolfSyncData();
  657. outputSyncData.SetData(this.animal);
  658. }
  659. }
  660. private WolfSyncData _inputSyncData;
  661. public WolfSyncData inputSyncData {
  662. get {
  663. return _inputSyncData;
  664. }
  665. set {
  666. _inputSyncData = value;
  667. uid = value.id;
  668. syncRotation.x = value.rx;
  669. syncRotation.y = value.ry;
  670. syncRotation.z = value.rz;
  671. syncRotation.w = value.rw;
  672. syncPosition.x = value.px;
  673. syncPosition.y = value.py;
  674. syncPosition.z = value.pz;
  675. }
  676. }
  677. private Quaternion syncRotation;
  678. private Vector3 syncPosition;
  679. private bool hasUpdateBySyncData = false;
  680. public bool isInvalid = false; //外部运算用的
  681. public string onHitData = null;
  682. public bool onDoNextShootWillDestroy = false;
  683. public int injuredID = 0;
  684. public int deadID = 0;
  685. }
  686. #endregion
  687. public override int GetOnlineID() {
  688. return onlineHandler.uid;
  689. }
  690. }