AttackController.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System;
  5. using Sirenix.OdinInspector;
  6. using System.Linq;
  7. //攻击所附带的状态
  8. public enum AttackEffect
  9. {
  10. //控制
  11. FloatState = 0, //漂浮
  12. BlowUp = 1, //击飞
  13. ShotDown = 2, //击落
  14. Stun = 3, //击晕
  15. //非控制
  16. Armor = 100, //穿甲
  17. ChangeDamage = 101, //更改攻击力
  18. Vulnerable = 102, //易伤
  19. SustainedInjury = 103, //持续伤害
  20. Burn = 104, //灼烧
  21. //中毒
  22. //麻痹
  23. }
  24. [Serializable]
  25. public class AttackInfo
  26. {
  27. public int damage;
  28. public Vector3 attackDir;
  29. public AttackEffect[] attackEffect;
  30. //漂浮
  31. [Serializable]
  32. public struct FloatState
  33. {
  34. public float time; //漂浮时间
  35. public Vector2 upTime; //上升最大耗时
  36. public Vector2 backSpeed; //往后退的速度
  37. public Vector2 rotateSpeed; //旋转速度
  38. public Vector2 height; //上升高度
  39. }
  40. private bool ShowFloatStateValue()
  41. {
  42. return attackEffect.Contains(AttackEffect.FloatState);
  43. }
  44. [Header("漂浮")]
  45. [ShowIf("ShowFloatStateValue")]
  46. public FloatState floatState;
  47. //击飞
  48. [Serializable]
  49. public struct BlowUp
  50. {
  51. public Vector3 dir; //击打的方向
  52. public float force; //击打的力
  53. public float time; //落地后眩晕时间
  54. }
  55. private bool ShowBlowUpValue()
  56. {
  57. return attackEffect.Contains(AttackEffect.BlowUp);
  58. }
  59. [Header("击飞")]
  60. [ShowIf("ShowBlowUpValue")]
  61. public BlowUp blowUp;
  62. //击落
  63. [Serializable]
  64. public struct ShotDown
  65. {
  66. public Vector3 dir; //击打的方向
  67. public float force; //击打的力
  68. public float time; //落地后眩晕时间
  69. }
  70. private bool ShowShotDownValue()
  71. {
  72. return attackEffect.Contains(AttackEffect.ShotDown);
  73. }
  74. [Header("击落")]
  75. [ShowIf("ShowShotDownValue")]
  76. public ShotDown shotDown;
  77. //击晕
  78. [Serializable]
  79. public struct Stun
  80. {
  81. public float time; //击晕时间
  82. }
  83. private bool ShowStunValue()
  84. {
  85. return attackEffect.Contains(AttackEffect.Stun);
  86. }
  87. [Header("击晕")]
  88. [ShowIf("ShowStunValue")]
  89. public Stun stun;
  90. //穿甲
  91. [Serializable]
  92. public struct Armor
  93. {
  94. public float rate; //穿甲率
  95. }
  96. private bool ShowArmorValue()
  97. {
  98. return attackEffect.Contains(AttackEffect.Armor);
  99. }
  100. [Header("穿甲")]
  101. [ShowIf("ShowArmorValue")]
  102. public Armor armor;
  103. //增加和减少攻击力
  104. [Serializable]
  105. public struct ChangeDamage
  106. {
  107. public float rate; //增加或减少攻击倍率
  108. }
  109. private bool ShowChangeDamageValue()
  110. {
  111. return attackEffect.Contains(AttackEffect.ChangeDamage);
  112. }
  113. [Header("更改攻击力")]
  114. [ShowIf("ShowChangeDamageValue")]
  115. public ChangeDamage changeDamage;
  116. //持续伤害
  117. [Serializable]
  118. public struct SustainedInjury
  119. {
  120. public float damage; //每次造成的伤害数值
  121. }
  122. private bool ShowSustainedInjuryValue()
  123. {
  124. return attackEffect.Contains(AttackEffect.SustainedInjury);
  125. }
  126. [Header("持续伤害")]
  127. [ShowIf("ShowSustainedInjuryValue")]
  128. public SustainedInjury sustainedInjury;
  129. public void CopyTo(AttackInfo ai)
  130. {
  131. ai.damage = damage;
  132. ai.attackDir = attackDir;
  133. ai.blowUp = blowUp;
  134. ai.shotDown = shotDown;
  135. ai.stun = stun;
  136. ai.armor = armor;
  137. ai.changeDamage = changeDamage;
  138. ai.sustainedInjury = sustainedInjury;
  139. }
  140. }
  141. public class AttackController : MonoBehaviour
  142. {
  143. //攻击类型
  144. public enum AttackType
  145. {
  146. Melee = 0, //近战
  147. Shoot = 1, //射击
  148. Special = 2, //非普攻
  149. Dash = 3, //英灵刺客,后面请删掉
  150. }
  151. [System.Serializable]
  152. public struct SpineAniKey
  153. {
  154. public string aniName;
  155. public List<AttackKeyType> keys;
  156. }
  157. public enum KeyType
  158. {
  159. AttackStart,
  160. AttackEnd,
  161. }
  162. [System.Serializable]
  163. public struct AttackKeyType
  164. {
  165. public int attackMethod;
  166. public KeyType attackType;
  167. public string startKeyName;
  168. public float startKeyTime;
  169. public KeyType endType;
  170. public string endKeyName;
  171. public float endKeyTime;
  172. }
  173. [System.Serializable]
  174. public struct AttackMethod
  175. {
  176. [Header("起手式id=0,行军式id>=1")]
  177. public int id;
  178. [Header("攻击名称")]
  179. public string attackName;
  180. [Header("攻击类型")]
  181. public AttackType attackType;
  182. [Header("攻击特效")]
  183. public GameObject attackEffect;
  184. [Header("攻击参数")]
  185. public AttackInfo attackInfo;
  186. public AttackTrigger attackTrigger;
  187. [Header("攻击距离")]
  188. public float attackDistance;
  189. [ShowIf("needToChange")]
  190. public float maxAttackDis, minAttackDis;
  191. public bool needToChange;
  192. [Header("目标")]
  193. public List<TargetType> targetTypes;
  194. public bool canHitFly;
  195. public int armorPiercing; //穿甲率
  196. [Header("远程单位")]
  197. [ShowIf("attackType",AttackType.Shoot)]
  198. public GameObject bulletPrefab; //子弹
  199. [ShowIf("attackType", AttackType.Shoot)]
  200. public List<Transform> shootPos; //子弹发射位置
  201. [ShowIf("attackType", AttackType.Shoot)]
  202. public bool shootTrack; //是否初始时瞄准目标
  203. [ShowIf("attackType", AttackType.Shoot)]
  204. public bool shootAlwaysTrack; //是否始终追踪
  205. [Header("特殊攻击")]
  206. [ShowIf("attackType", AttackType.Special)]
  207. public GameObject skillPrefab;
  208. [HideInInspector]
  209. public SpecialSkills skill;
  210. }
  211. private Character owner;
  212. [Header("所有攻击帧事件及时间")]
  213. public List<SpineAniKey> attackKeys;
  214. public List<float> keyTimes; //所有的帧事件时间
  215. [DisplayOnly]
  216. public float attackTime; //攻击剩余时间
  217. [HideInInspector]
  218. public float attackKeyCount; //攻击进行时间
  219. [HideInInspector]
  220. public float nextStartKeyTime, nextEndKeyTime;
  221. [HideInInspector]
  222. public int curKeyNum; //当前锁定到第几个帧事件
  223. [Header("攻击类型")]
  224. public AttackType attackType;
  225. [Header("攻击参数")]
  226. [DisplayOnly]
  227. public int curDamage;
  228. [HideInInspector]
  229. public bool canHitFly;
  230. [HideInInspector]
  231. public int armorPiercing; //穿甲率
  232. [HideInInspector]
  233. public AttackInfo attackInfo;
  234. [HideInInspector]
  235. public GameObject addAttackEffect;
  236. [HideInInspector]
  237. public SpecialSkills skill;
  238. [HideInInspector]
  239. public GameObject attackEffect;
  240. [HideInInspector]
  241. public Dictionary<string, GameObject> effects;
  242. [HideInInspector]
  243. public GameObject effect;
  244. [HideInInspector]
  245. public float attackDistance;
  246. [Header("攻击范围")]
  247. [HideInInspector]
  248. public AttackTrigger attackTrigger;
  249. [HideInInspector]
  250. public bool isAttackTriggerOn = false; //当前Attack Trigger是否开启
  251. [Header("远程单位")]
  252. [HideInInspector]
  253. public GameObject bulletPrefab; //子弹
  254. [HideInInspector]
  255. public List<Transform> shootPos; //子弹发射位置
  256. [HideInInspector]
  257. public bool shootTrack = false; //是否初始时瞄准目标
  258. [HideInInspector]
  259. public bool shootAlwaysTrack = false; //是否始终追踪
  260. [Header("目标")]
  261. [HideInInspector]
  262. public List<TargetType> targetTypes;
  263. [DisplayOnly]
  264. public List<Character> beTargetCharacter = new List<Character>(); //被哪些锁定
  265. //public float getDistanceOffset = 0f;
  266. [Header("攻击模式")]
  267. public AttackMethod[] attackMethod;
  268. [DisplayOnly]
  269. public AttackMethod curAttackMethod;
  270. public void Init()
  271. {
  272. owner = GetComponent<Character>();
  273. if (attackMethod.Length > 0)
  274. {
  275. attackInfo = attackMethod[0].attackInfo;
  276. curDamage = attackInfo.damage;
  277. }
  278. effects = new Dictionary<string, GameObject>();
  279. for (int i = 0; i < attackMethod.Length; i++)
  280. {
  281. if (attackMethod[i].needToChange)
  282. {
  283. attackMethod[i].attackDistance = UnityEngine.Random.Range(attackMethod[i].minAttackDis,
  284. attackMethod[i].maxAttackDis);
  285. }
  286. }
  287. }
  288. private void OnEnable()
  289. {
  290. if (attackTrigger != null)
  291. {
  292. attackTrigger.gameObject.SetActive(false);
  293. }
  294. }
  295. public void ChooseAttack(int id)
  296. {
  297. //默认起手式只使用一次,id=0为起手式
  298. curAttackMethod = attackMethod[id];
  299. attackType = curAttackMethod.attackType;
  300. canHitFly = curAttackMethod.canHitFly;
  301. armorPiercing = curAttackMethod.armorPiercing;
  302. attackInfo = curAttackMethod.attackInfo;
  303. curDamage = attackInfo.damage;
  304. attackTrigger = curAttackMethod.attackTrigger;
  305. bulletPrefab = curAttackMethod.bulletPrefab;
  306. shootPos = curAttackMethod.shootPos;
  307. shootTrack = curAttackMethod.shootTrack;
  308. shootAlwaysTrack = curAttackMethod.shootAlwaysTrack;
  309. targetTypes = curAttackMethod.targetTypes;
  310. if (attackType == AttackType.Special && skill == null)
  311. {
  312. curAttackMethod.skill= Instantiate(curAttackMethod.skillPrefab, owner.bodyTrans.position,
  313. new Quaternion(0, 0, 0, 0), owner.bodyTrans).GetComponent<SpecialSkills>();
  314. skill = curAttackMethod.skill;
  315. skill.owner = owner;
  316. }
  317. attackEffect = curAttackMethod.attackEffect;
  318. attackDistance = curAttackMethod.attackDistance;
  319. }
  320. public void SetNextKeyTimes()
  321. {
  322. if (curKeyNum < keyTimes.Count)
  323. {
  324. nextStartKeyTime = keyTimes[curKeyNum];
  325. nextEndKeyTime = keyTimes[curKeyNum + 1];
  326. curKeyNum += 2;
  327. }
  328. }
  329. public virtual void Attack_summon()
  330. {
  331. owner.ani.Play("attack_summon", 0, 0);
  332. if (attackType == AttackType.Shoot)
  333. {
  334. attackTrigger.isShoot = true;
  335. attackTrigger.type = AttackTrigger.attackType.summon;
  336. }
  337. attackTime = owner.totalAttack_summonTime;
  338. attackKeyCount = 0;
  339. keyTimes = new List<float>();
  340. foreach (SpineAniKey sak in attackKeys)
  341. {
  342. if (sak.aniName == "attack_summon")
  343. {
  344. foreach (AttackKeyType akt in sak.keys)
  345. {
  346. keyTimes.Add(akt.startKeyTime);
  347. keyTimes.Add(akt.endKeyTime);
  348. }
  349. break;
  350. }
  351. }
  352. curKeyNum = 0;
  353. SetNextKeyTimes();
  354. switch (attackType)
  355. {
  356. case AttackType.Melee:
  357. attackTrigger.attackInfo = attackInfo;
  358. break;
  359. default:
  360. break;
  361. }
  362. owner.ChangeState(CharacterState.Attack);
  363. }
  364. public virtual void Attack_march(int id)
  365. {
  366. if (attackEffect != null)
  367. {
  368. if (effects.ContainsKey(attackEffect.name))
  369. {
  370. effect = effects[attackEffect.name];
  371. effect.SetActive(true);
  372. }
  373. else
  374. {
  375. effects[attackEffect.name] = Instantiate(attackEffect, owner.bodyTrans);
  376. effect = effects[attackEffect.name];
  377. effect.SetActive(true);
  378. }
  379. }
  380. Vector3 leftDir = owner.GetMoveDir();
  381. if (leftDir.x > 0.3f)
  382. {
  383. if (owner.bodyTrans.localScale.x > 0)
  384. {
  385. owner.Turn();
  386. }
  387. }
  388. else if (leftDir.x < -0.3f)
  389. {
  390. if (owner.bodyTrans.localScale.x < 0)
  391. {
  392. owner.Turn();
  393. }
  394. }
  395. ChooseAttack(id);
  396. owner.ani.Play("attack_march", 0, 0);
  397. if (attackType == AttackType.Shoot)
  398. {
  399. attackTrigger.isShoot = true;
  400. attackTrigger.type = AttackTrigger.attackType.march;
  401. }
  402. if (attackType == AttackType.Special)
  403. {
  404. skill.Attack();
  405. }
  406. attackTime = owner.totalAttack_marchTime;
  407. attackKeyCount = 0;
  408. keyTimes = new List<float>();
  409. foreach (SpineAniKey sak in attackKeys)
  410. {
  411. if (sak.aniName == "attack_march")
  412. {
  413. foreach (AttackKeyType akt in sak.keys)
  414. {
  415. keyTimes.Add(akt.startKeyTime);
  416. keyTimes.Add(akt.endKeyTime);
  417. break;
  418. }
  419. }
  420. }
  421. curKeyNum = 0;
  422. SetNextKeyTimes();
  423. attackTrigger.attackInfo = attackInfo;
  424. owner.ChangeState(CharacterState.Attack);
  425. }
  426. public virtual void AttackShootEvent(int attackId, int shootId)
  427. {
  428. GameObject bulletObj = PoolManager.Instantiate(bulletPrefab);
  429. Bullet bullet = bulletObj.GetComponent<Bullet>();
  430. Vector3 attackDir = attackInfo.attackDir.normalized;
  431. if (owner.bodyTrans.localScale.x < 0)
  432. {
  433. attackDir.x = -attackDir.x;
  434. }
  435. if (attackId == 1 && owner.Attack_summonShootCanTransmit)
  436. {
  437. bullet.canTransmit = true;
  438. }
  439. bullet.BeShoot(owner, shootPos[shootId].position, attackDir, shootTrack,
  440. shootAlwaysTrack, owner.attackTarget ? owner.attackTarget : null);
  441. }
  442. public void JudgeTriggerOnOff()
  443. {
  444. attackTime -= Time.deltaTime;
  445. attackKeyCount += Time.deltaTime;
  446. if (!isAttackTriggerOn && attackKeyCount >= nextStartKeyTime && attackKeyCount <= nextEndKeyTime)
  447. {
  448. isAttackTriggerOn = true;
  449. attackTrigger.gameObject.SetActive(true);
  450. }
  451. else if (isAttackTriggerOn && attackKeyCount >= nextEndKeyTime)
  452. {
  453. isAttackTriggerOn = false;
  454. attackTrigger.gameObject.SetActive(false);
  455. SetNextKeyTimes();
  456. }
  457. }
  458. }