Wolf.cs 25 KB

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