Arrow.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using DG.Tweening;
  6. /* 箭对象 */
  7. public class Arrow : MonoBehaviour
  8. {
  9. //飞行时间统计
  10. [NonSerialized] public float flyTime = 0;
  11. //标识—是否击中了什么
  12. [NonSerialized] public bool isHit = false;
  13. //箭的初速度(私用)
  14. [NonSerialized] public float mySpeed = 0;
  15. //箭的初速度(公用)
  16. public static float speed = GameMgr.RealSizeToGameSize(60);
  17. //箭射出时从弓传过来的参数
  18. #region
  19. //手臂弓
  20. [NonSerialized] public ArmBow armBow;
  21. //射出时的起始坐标
  22. [NonSerialized] public Vector3 shootOutPosition;
  23. //绝对射线
  24. [NonSerialized] public RaycastHit absoluteRay;
  25. //制作误差偏移角(强行制造误差,为了增加游戏难度,该偏移角的大小根据难度而定)
  26. [NonSerialized] public float offsetAngle;
  27. //误差偏移后的欧拉角
  28. [NonSerialized] public Vector3 finalAngleAfterOffset;
  29. #endregion
  30. //射线击中的靶子
  31. TargetBody rayHitTargetBody;
  32. //能够完美击中射线点
  33. bool canPerfectHit;
  34. //能否使用侧面镜头
  35. [NonSerialized] public bool canUseSideCamera;
  36. [NonSerialized] public ArrowCamera arrowCameraComp;
  37. public System.Action onDoNextShoot;
  38. public static HashSet<Arrow> arrowSet = new HashSet<Arrow>();
  39. void Awake()
  40. {
  41. arrowSet.Add(this);
  42. GameMgr.ins.gameMode.PauseTimeCounting(this);
  43. //箭模型平时属于ArmBow层,因为ArmBow层在飞行镜头中不被渲染,所以箭出去后要切换layer
  44. this.transform.Find("Head/_hunse_jian").gameObject.layer = 0;
  45. }
  46. void OnDestroy()
  47. {
  48. arrowSet.Remove(this);
  49. if (GameMgr.ins) GameMgr.ins.gameMode.ResumeTimeCounting(this);
  50. }
  51. void Start()
  52. {
  53. mySpeed = speed;
  54. Billboard.ins?.SetArrowSpeed(speed);
  55. if (GameAssistUI.ins && GlobalData.MyDeviceMode == DeviceMode.Archery)
  56. {
  57. int shootScaleValue = 5; //GameAssistUI.ins.shootScaleValue
  58. mySpeed *= shootScaleValue;
  59. Billboard.ins?.SetArrowSpeedScale(shootScaleValue);
  60. }
  61. Debug.Log("射箭基础速度:" + speed + ",射箭加倍后的速度:"+ mySpeed);
  62. Billboard.ins?.ShowSpeed();
  63. if (GlobalData.pkMatchType == PKMatchType.OnlinePK)
  64. {
  65. if (GameMgr.gameType == 9)
  66. {
  67. ((PKGameMode_OnlinePK)GameMgr.ins.gameMode).shootSpeedWillSend = Billboard.ins.GetShootSpeedText();
  68. }
  69. }
  70. if (absoluteRay.transform)
  71. {
  72. //记录射线有没有击中靶子
  73. rayHitTargetBody = absoluteRay.transform.GetComponent<TargetBody>();
  74. //把瞄准点画成红圈,渲染在靶子上
  75. if (rayHitTargetBody)
  76. {
  77. //string typeStr = GlobalData.MyDeviceMode == DeviceMode.Archery? "RedCircle":"BulletCircle";
  78. Transform redCircle = rayHitTargetBody.transform.Find("RedCircle");
  79. redCircle.gameObject.SetActive(true);
  80. redCircle.transform.position = -redCircle.transform.forward * 0.001f + absoluteRay.point;
  81. //渲染弹坑
  82. if (GlobalData.MyDeviceMode == DeviceMode.Gun)
  83. {
  84. Transform crater = transform.Find("Crater");
  85. crater.rotation = redCircle.rotation;
  86. }
  87. }
  88. }
  89. SetUpBeforFly();
  90. if (GlobalData.MyDeviceMode == DeviceMode.Archery)
  91. {
  92. Transform cameraTF = this.transform.Find("Camera");
  93. cameraTF.gameObject.SetActive(true);
  94. arrowCameraComp = cameraTF.gameObject.AddComponent<ArrowCamera>();
  95. arrowCameraComp.arrow = this;
  96. }
  97. this.activeEffectTrail(true);
  98. }
  99. /**在箭飞行前初始化&如果瞄准射线的落点在靶子上时,才调用该函数 */
  100. void SetUpBeforFly()
  101. {
  102. //基础角
  103. float baseAngleX = FormatAngleX(this.transform.eulerAngles.x);
  104. //最大可调整的角度差
  105. float maxDeltaAngleX = 5;
  106. //最终角
  107. float finalAngleX = baseAngleX;
  108. //额外偏移误差角
  109. float offsetAngleX = FormatAngleX(this.finalAngleAfterOffset.x) - baseAngleX;
  110. float offsetAngleY = FormatAngleY(this.finalAngleAfterOffset.y - this.transform.eulerAngles.y);
  111. if (DebugArrowOffsetAngle.ins)
  112. {
  113. offsetAngleX *= DebugArrowOffsetAngle.ins.GetOffsetScaleValue();
  114. offsetAngleY *= DebugArrowOffsetAngle.ins.GetOffsetScaleValue();
  115. }
  116. else
  117. {
  118. offsetAngleX *= this.armBow.shootOffsetAngleScale;
  119. offsetAngleY *= this.armBow.shootOffsetAngleScale;
  120. }
  121. DebugArrowOffsetAngle2.ins?.SetOffsetAngles(offsetAngleX, offsetAngleY);
  122. if (absoluteRay.transform)
  123. {
  124. bool plusOffsetAngleY = false;
  125. //看能否通过调整发射角让箭落在靶子的瞄准点上
  126. CalculateParabolaAngle(absoluteRay.point);
  127. //瞄准的是不是Target层
  128. bool isTargetLayer = IsTargetLayer(absoluteRay.transform.gameObject);
  129. //绝对发射角无解
  130. if (!hasParabolaAngle)
  131. {
  132. if (isTargetLayer) AimLoadChecker.ins?.ShowOutTip();
  133. }
  134. else
  135. {
  136. //来到这里,证明发射角有解,该解姑且叫它绝对角
  137. float absoluteAngleX = parabolaAngleInRadian / Mathf.PI * 180;
  138. //客户要求绝对角跟原本角度相差不能超过 maxDeltaAngleX
  139. float deltaAngleX = absoluteAngleX - baseAngleX;
  140. //如果绝对角跟原本角度相差不超过maxDeltaAngleX
  141. if (Mathf.Abs(deltaAngleX) < maxDeltaAngleX)
  142. {
  143. finalAngleX = Mathf.Clamp(absoluteAngleX + offsetAngleX, -89, 89);
  144. plusOffsetAngleY = true;
  145. if (Math.Abs(offsetAngle) < 0.001)
  146. {
  147. canPerfectHit = true;
  148. }
  149. if (rayHitTargetBody && Mathf.RoundToInt(rayHitTargetBody.GetDistance()) >= 50 && UnityEngine.Random.value < 0.5)
  150. {
  151. canUseSideCamera = true;
  152. }
  153. }
  154. else
  155. {
  156. finalAngleX = Mathf.Clamp(baseAngleX + maxDeltaAngleX, -89, 89);
  157. if (isTargetLayer) AimLoadChecker.ins?.ShowOutTip();
  158. }
  159. }
  160. finalPoint = absoluteRay.point;
  161. if (plusOffsetAngleY)
  162. {
  163. Vector3 myPos = this.transform.position;
  164. Vector3 pointer = finalPoint - myPos;
  165. pointer = Quaternion.AngleAxis(offsetAngleY, Vector3.up) * pointer;
  166. finalPoint = myPos + pointer;
  167. this.transform.LookAt(finalPoint);
  168. }
  169. }
  170. else
  171. {
  172. finalPoint = this.transform.position + this.transform.forward * 100;
  173. }
  174. parabolaAngleInRadian = finalAngleX / 180 * Mathf.PI;
  175. }
  176. /*
  177. 因为Unity引擎的规则,向上时359~270度,向下是0~90度
  178. 为了方便数学运算,换算成 向上时0~90度,向下是0~-90度
  179. */
  180. float FormatAngleX(float value)
  181. {
  182. if (value > 180) value = 360 - value;
  183. else value = -value;
  184. return value;
  185. }
  186. /**UnityY轴旋转只有0°~360°,两个Y轴旋转相减求得的夹角时会出现>180的情况,该函数就是为了解决这问题 */
  187. float FormatAngleY(float value)
  188. {
  189. if (Mathf.Abs(value) > 180)
  190. {
  191. if (value < 0)
  192. {
  193. return 360f + value;
  194. }
  195. if (value > 0)
  196. {
  197. return value - 360f;
  198. }
  199. }
  200. return value;
  201. }
  202. bool IsTargetLayer(GameObject gameObject)
  203. {
  204. return (1 << gameObject.layer) == LayerMask.GetMask("Target");
  205. }
  206. public Transform Head()
  207. {
  208. return this.transform.Find("Head");
  209. }
  210. /**发射角有无解 */
  211. bool hasParabolaAngle = false;
  212. /**发射角弧度解 */
  213. float parabolaAngleInRadian = 0;
  214. /**
  215. 求弓箭发射到指定坐标所需要的角度。
  216. 已知初速度大小V,重力g,起始坐标(a1,a2),目标坐标(b1,b2)。
  217. 解:
  218. 1、列出关系式
  219. Δx = b1 - a1;
  220. Δy = b2 - a2;
  221. Vx = V * cos(angle)
  222. Vy = V * sin(angle)
  223. Vy * t + 1/2 * g * t^2 = Δy
  224. Vx * t = Δx
  225. t = Δx / Vx
  226. 2、推导过程
  227. (V * sin(angle)) * Δx / (V * cos(angle)) + 1/2 * g * Δx^2 / (V^2*cos(angle)^2) = Δy
  228. tan(angle) * Δx + 1/2 * g * Δx^2 / (V^2*cos(angle)^2) = Δy
  229. tan(angle) * Δx + 1/2 * g * (Δx^2 / V^2) * (1 + tan(angle)^2) = Δy
  230. 3、根据求根公式得出结论
  231. a = 1/2 * g * Δx^2 / V^2
  232. b = Δx
  233. c = a - Δy
  234. d = tan(angle) = (-b ± (b^2 - 4*a*c)^0.5) / (2*a)
  235. angle = atan(d)
  236. 有无根的判别式,有根则b^2-4*a*c>=0
  237. */
  238. void CalculateParabolaAngle(Vector3 destination)
  239. {
  240. float deltaX = Vector2.Distance(
  241. new Vector2(destination.x, destination.z),
  242. new Vector2(this.transform.position.x, this.transform.position.z)
  243. );
  244. float deltaY = destination.y - this.transform.position.y;
  245. float a = 0.5f * Physics.gravity.y * Mathf.Pow(deltaX, 2) / Mathf.Pow(this.mySpeed, 2);
  246. float b = deltaX;
  247. float c = a - deltaY;
  248. hasParabolaAngle = Mathf.Pow(b, 2) - 4 * a * c >= 0;
  249. if (hasParabolaAngle)
  250. {
  251. float res1 = (-b + Mathf.Pow(Mathf.Pow(b, 2) - 4 * a * c, 0.5f)) / (2 * a);
  252. float res2 = (-b - Mathf.Pow(Mathf.Pow(b, 2) - 4 * a * c, 0.5f)) / (2 * a);
  253. parabolaAngleInRadian = Mathf.Min(Mathf.Atan(res1), Mathf.Atan(res2));
  254. }
  255. }
  256. void FixedUpdate()
  257. {
  258. if (!isHit && flyTime >= 0)
  259. {
  260. flyTime += Time.deltaTime;
  261. if (flyTime > 14)
  262. {
  263. FlyTimeOut();
  264. }
  265. // this.UpdateRotate();
  266. }
  267. }
  268. public ArrowSync.SyncData outputSyncData;
  269. void Update()
  270. {
  271. UpdateFlyLogic();
  272. if (GlobalData.pkMatchType == PKMatchType.OnlinePK)
  273. {
  274. if (outputSyncData == null) outputSyncData = new ArrowSync.SyncData();
  275. outputSyncData.SetData(this);
  276. }
  277. }
  278. IEnumerator delayFlyTimeOut() {
  279. yield return new WaitForSeconds(0.8f);//gun_shoot 音频长度
  280. FlyTimeOut();
  281. }
  282. void FlyTimeOut()
  283. {
  284. Destroy(gameObject);
  285. GameMgr.ins.gameMode.HitTarget(0);
  286. AudioMgr.ins.PlayCheer(false);
  287. nextShoot();
  288. }
  289. float logicFlyTime = 0;
  290. Vector3 finalPoint;
  291. /**飞行帧逻辑(运动学) */
  292. void UpdateFlyLogic()
  293. {
  294. if (isHit) return;
  295. logicFlyTime += Time.deltaTime;
  296. Vector3 destination = finalPoint;
  297. float vx = Mathf.Cos(parabolaAngleInRadian) * mySpeed;
  298. float t = logicFlyTime;
  299. float vy = Mathf.Sin(parabolaAngleInRadian) * mySpeed + Physics.gravity.y * t;
  300. float dy = Mathf.Sin(parabolaAngleInRadian) * mySpeed * t + 0.5f * Physics.gravity.y * Mathf.Pow(t, 2);
  301. float dx = vx * t;
  302. Vector3 nextPosition = new Vector3(destination.x - shootOutPosition.x, 0, destination.z - shootOutPosition.z);
  303. nextPosition = nextPosition.normalized * dx;
  304. nextPosition.y = dy;
  305. nextPosition = shootOutPosition + nextPosition;
  306. Vector3 oldPosition = this.transform.position;
  307. this.transform.position = nextPosition;
  308. Vector3 eulerAngles = this.transform.eulerAngles;
  309. float angleX = Mathf.Atan(vy / vx) / Mathf.PI * 180;
  310. eulerAngles.x = -angleX;
  311. this.transform.eulerAngles = eulerAngles;
  312. float deltaDistance = Vector3.Distance(oldPosition, nextPosition);
  313. Ray ray = new Ray(oldPosition, nextPosition - oldPosition);
  314. RaycastHit raycastHit;
  315. bool raycastResult = Physics.Raycast(ray, out raycastHit, deltaDistance);
  316. if (raycastResult)
  317. {
  318. this.transform.position = raycastHit.point;
  319. if (ArrowTraceDebug.ins) ArrowTraceDebug.ins.OnArrowUpdate(this);
  320. OnHitAnyInFlyLogic(raycastHit);
  321. }
  322. else
  323. {
  324. if (ArrowTraceDebug.ins) ArrowTraceDebug.ins.OnArrowUpdate(this);
  325. }
  326. }
  327. public class HitType
  328. {
  329. public static int None = 0;
  330. public static int TargetInRing = 1; //击中了靶子,且在得分环内
  331. public static int TargetOutRing = 2; //击中了靶子,但不在得分环内
  332. public static int NotTarget = 4; //击中非目标对象
  333. public static int Animal = 5; //击中动物
  334. }
  335. [NonSerialized] public int hitType = HitType.None;
  336. [NonSerialized] public Transform raycastHitTransform; //射线击中的目标变换
  337. [NonSerialized] public string[] hitTargetAnimalInfo;
  338. //飞行逻辑中检测到碰撞
  339. void OnHitAnyInFlyLogic(RaycastHit raycastHit)
  340. {
  341. this.Head().position = raycastHit.point;
  342. this.transform.SetParent(raycastHit.transform.parent);
  343. string targetName = raycastHit.transform.gameObject.name;
  344. this.raycastHitTransform = raycastHit.transform;
  345. if (targetName == "TargetBody")
  346. {
  347. Vector3 hitPoint = raycastHit.point;
  348. if (rayHitTargetBody && canPerfectHit)
  349. {
  350. hitPoint = absoluteRay.point;
  351. this.Head().position = hitPoint;
  352. }
  353. if (GlobalData.MyDeviceMode == DeviceMode.Archery)
  354. this.arrowCameraComp.arrowCameraTemplate?.beforeHit();
  355. else
  356. nextShootFromType();//子弹直接下一轮
  357. raycastHit.transform.GetComponent<TargetBody>().Hit(this, hitPoint);
  358. }
  359. else if (targetName.StartsWith("TargetAnimalPart"))
  360. {
  361. hitType = HitType.Animal;
  362. Vector3 hitPoint = raycastHit.point;
  363. string partName = targetName.Split(new char[] { '_' })[1];
  364. if (GlobalData.MyDeviceMode == DeviceMode.Archery)
  365. this.arrowCameraComp.arrowCameraTemplate?.beforeHit();
  366. else
  367. nextShootFromType();//子弹直接下一轮
  368. TargetAnimal targetAnimal = raycastHit.transform.GetComponentInParent<TargetAnimal>();
  369. targetAnimal.OnHit(this, hitPoint, partName);
  370. //箭击中的音效
  371. AudioMgr.ins.PlayArrowEnter();
  372. //记录击中的部位和动物ID
  373. hitTargetAnimalInfo = new string[] {
  374. targetAnimal.GetOnlineID().ToString(),
  375. targetAnimal.targetAnimalParts.IndexOf(raycastHitTransform).ToString(),
  376. SyncDataUtil.Vec3ToStr(transform.localPosition),
  377. SyncDataUtil.QuatToStr(transform.localRotation),
  378. SyncDataUtil.Vec3ToStr(transform.position),
  379. SyncDataUtil.QuatToStr(transform.rotation)
  380. };
  381. }
  382. else if (raycastHit.transform.GetComponent<TargetOutBound>())
  383. { //撞到空气墙当作超时处理
  384. if (GlobalData.MyDeviceMode == DeviceMode.Archery)
  385. FlyTimeOut();
  386. else
  387. StartCoroutine(delayFlyTimeOut());
  388. }
  389. else
  390. {
  391. if (GlobalData.MyDeviceMode == DeviceMode.Archery)
  392. this.arrowCameraComp.arrowCameraTemplate?.beforeHit();
  393. else
  394. nextShootFromType();//子弹直接下一轮
  395. Hit();
  396. GameMgr.ins.gameMode.HitTarget(0);
  397. //击中其它东西时的音效
  398. hitType = HitType.NotTarget;
  399. if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name == "Game")
  400. {
  401. AudioMgr.ins.PlayCheer(false);
  402. }
  403. else
  404. {
  405. if (CommonConfig.StandaloneModeOrPlatformB) {
  406. AudioMgr.ins.PlayCheer(false);
  407. } else {
  408. AudioMgr.ins.PlayArrowEnter();
  409. }
  410. }
  411. }
  412. }
  413. public void Hit()
  414. {
  415. isHit = true;
  416. if (GameDebug.ins) GameDebug.ins.ShowRes(absoluteRay.point, this.Head().position);
  417. //控制箭的特效显示
  418. this.activeEffectCyclone(false);
  419. this.activeEffectBomb(true);
  420. this.activeEffectTrail(false);
  421. //最新一箭击中后会发光标记
  422. ArrowLightSick.RecoveryAll();
  423. this.GetComponentInChildren<ArrowLightSick>().Hit();
  424. }
  425. //进入下一轮射击
  426. [NonSerialized] public bool hasDoneNextShoot = false;
  427. public void nextShootFromType() {
  428. // Debug.Log("nextShootFromType:" + GlobalDataTemp.pkMatchType);
  429. if (GlobalDataTemp.pkMatchType == PKMatchType.LocalPK || GlobalDataTemp.pkMatchType == PKMatchType.OnlinePK)
  430. {
  431. StartCoroutine(delayNectShoot());
  432. }
  433. else {
  434. nextShoot();
  435. }
  436. }
  437. IEnumerator delayNectShoot() {
  438. yield return new WaitForSeconds(1.0f);
  439. nextShoot();
  440. }
  441. public void nextShoot()
  442. {
  443. if (hasDoneNextShoot) return;
  444. hasDoneNextShoot = true;
  445. GameMgr.ins.gameMode.ResumeTimeCounting(this);
  446. onDoNextShoot?.Invoke();
  447. try
  448. {
  449. if (AimHandler.ins) AimHandler.ins.Ban9AxisCalculate(false);
  450. //把瞄准点画成红圈,渲染在靶子上(取消)
  451. if (rayHitTargetBody)
  452. {
  453. //string typeStr = GlobalData.MyDeviceMode == DeviceMode.Archery ? "RedCircle" : "BulletCircle";
  454. Transform redCircle = rayHitTargetBody.transform.Find("RedCircle");
  455. redCircle.gameObject.SetActive(false);
  456. }
  457. //最新一箭击中后会发光标记(取消)
  458. ArrowLightSick.RecoveryAll();
  459. }
  460. catch (System.Exception e) { Debug.LogError(e.Message + "\n" + e.StackTrace); }
  461. if (!GameMgr.ins.gameMode.DoNextShoot()) return;
  462. this.armBow.readyShoot();
  463. }
  464. //---------箭矢旋转--------
  465. Vector3 rotateV3 = new Vector3(0, 0, 1400);
  466. void UpdateRotate()
  467. {
  468. this.Head().Rotate(rotateV3 * Time.deltaTime, Space.Self);
  469. }
  470. //---------箭矢特效---------
  471. public void activeEffectCyclone(bool value)
  472. {
  473. this.transform.Find("Head/EF_kuosanquan").gameObject.SetActive(value);
  474. if (!value) return;
  475. ParticleSystemRenderer ps = this.transform.Find("Head/EF_kuosanquan/kuosan").GetComponent<ParticleSystemRenderer>();
  476. ParticleSystemRenderer ps1 = this.transform.Find("Head/EF_kuosanquan/kuosan (1)").GetComponent<ParticleSystemRenderer>();
  477. DOTween.To(() => ps.minParticleSize, value =>
  478. {
  479. ps.minParticleSize = value;
  480. ps.maxParticleSize = value;
  481. }, 0.4f, 0.6f);
  482. DOTween.To(() => ps1.minParticleSize, value =>
  483. {
  484. ps1.minParticleSize = value;
  485. ps1.maxParticleSize = value;
  486. }, 0.8f, 0.6f);
  487. }
  488. void activeEffectBomb(bool value)
  489. {
  490. this.transform.Find("Head/EF_baodian").gameObject.SetActive(value);
  491. }
  492. void activeEffectTrail(bool value)
  493. {
  494. if (GlobalData.MyDeviceMode == DeviceMode.Archery)
  495. {
  496. this.transform.Find("EF_tuowei").gameObject.SetActive(value);
  497. this.transform.Find("EF_tuowei/Trail").GetComponent<TrailRenderer>().time = 1.6f / mySpeed;
  498. }
  499. else {
  500. StartCoroutine(showTrail(value));
  501. }
  502. }
  503. IEnumerator showTrail(bool value) {
  504. this.transform.Find("EF_tuowei_bullet").gameObject.SetActive(value);
  505. //this.transform.Find("EF_tuowei_bullet/Trail").GetComponent<TrailRenderer>().time = 0;
  506. yield return new WaitForEndOfFrame();
  507. this.transform.Find("EF_tuowei_bullet/GB_flame_FX_1").gameObject.SetActive(true);
  508. //this.transform.Find("EF_tuowei_bullet/Trail").GetComponent<TrailRenderer>().time = 0.02f;
  509. //this.transform.Find("EF_tuowei_bullet/Trail").GetComponent<TrailRenderer>().time = 1.6f / mySpeed;
  510. }
  511. }