using System.Collections; using System.Collections.Generic; using UnityEngine; public class ArmBow : MonoBehaviour { [SerializeField] AnimationPlayer AP_arm; [SerializeField] AnimationPlayer AP_bow; [SerializeField] GameObject arrow; [SerializeField] BowCamera bowCamera; public HashSet validTargets = new HashSet(); public int shootBackTime = 0; private bool canShoot = false; private bool pulling = false; private bool readying = false; //禁止准备的外部接口 public bool banReady = false; //禁止射击的外部接口 public bool banShoot = false; public static ArmBow ins; public Quaternion[] recordRotations = new Quaternion[100]; public float[] recordRotationVars = new float[99]; public int recordCount = 0; void Start() { ins = this; this.readyShoot(); //initdata int currentShootLevel = LoginMgr.myUserInfo.shootLevel; int[] shootBackTimes = {0, 1, 5}; shootBackTime = shootBackTimes[currentShootLevel]; } void FixedUpdate() { if (this.canShoot) { if (DebugBowPower.ins) DebugBowPower.ins.DoUpdate(); } } void Update() { if (Input.GetKeyDown(KeyCode.Q)) { this.ADS_fire(); } if (this.pulling) { this.bowCamera.updateFollowPullBow(); } else if (!this.canShoot) { this.bowCamera.updateGiveUpPullBow(); } } void onComplete(AnimationPlayerCompleteResult res) { if (res.index == 0) { this.readying = true; this.idle(); this.Invoke("idleToADS", 0.1f); } else if (res.index == 2) { this.ADS_idle(); } } public void ready() { if (banReady) return; GameMgr.ins.gameMode.PauseTimeCounting(this); GameMgr.ins.gameMode.onBowReady(); this.arrow.SetActive(true); AP_arm.play(0, WrapMode.Once); AP_bow.play(0, WrapMode.Once); AP_arm.completeCallback = onComplete; this.pulling = false; this.canShoot = false; } void idle() { AP_arm.play(1, WrapMode.Loop); AP_bow.play(1, WrapMode.Loop); AP_arm.completeCallback = null; this.pulling = false; this.canShoot = false; if (DebugBowPower.ins) DebugBowPower.ins.Init(); } public void idleToADS() { AP_arm.play(2, WrapMode.Once); AP_bow.play(2, WrapMode.Once); AP_arm.completeCallback = onComplete; this.pulling = true; this.canShoot = false; } void ADS_idle() { GameMgr.ins.gameMode.ResumeTimeCounting(this); this.canShoot = true; this.pulling = false; if (DebugBowPower.ins) DebugBowPower.ins.PullFinish(); } public void ADS_fire() { if (!canShoot || banShoot || GameMgr.ins.gamePause) return; GameMgr.ins.gameMode.onBowShoot(); this.pulling = false; this.canShoot = false; this.readying = false; AP_bow.play(0, WrapMode.Once); this.arrow.SetActive(false); shoot(); } public void readyShoot() { this.bowCamera.setFieldOfView(60, false); // this.gameObject.SetActive(true); this.ready(); } void shoot() { RaycastHit raycastHit = CrossHair.ins.GetRaycastHit(); // 筛选出一个稳定的发射角度---start Quaternion best_rotation = this.bowCamera.transform.rotation; if (recordCount >= recordRotations.Length) { int single_check_count = 6; float min_wave = float.MaxValue; for (int i = 0; i < recordRotationVars.Length; i++) { recordRotationVars[i] = Quaternion.Angle(recordRotations[i], recordRotations[i + 1]); if (i >= single_check_count - 1) { float wave = 0; for (int j = i; j > i - single_check_count; j--) { wave += recordRotationVars[j]; } if (wave < min_wave) { min_wave = wave; int best_rotation_index = i - single_check_count + 1 - this.shootBackTime; if (best_rotation_index < 0) best_rotation_index = 0; best_rotation = recordRotations[best_rotation_index]; } } } } // if (recordCount >= recordRotations.Length) { // int single_check_count = 6; // float min_wave = float.MaxValue; // for (int i = 0; i < recordRotationVars.Length; i++) // { // recordRotationVars[i] = Quaternion.Angle(recordRotations[i], recordRotations[i + 1]); // if (i >= single_check_count - 1) // { // float wave = 0; // for (int j = i; j > i - single_check_count; j--) // { // wave += recordRotationVars[j]; // } // if (wave < min_wave) // { // min_wave = wave; // best_rotation = recordRotations[i - single_check_count + 1]; // } // } // } // } // 筛选出一个稳定的发射角度---end Vector3 shootOutPosition = this.bowCamera.transform.position; //如果弓指向太过朝下,在弓口发射可能会射穿地面,因此需要角度适当时,才从弓口射出。 if (BowCamera.ins.transform.localEulerAngles.x < 30) shootOutPosition += this.bowCamera.transform.forward * 1.5f; GameObject arrowCopy = GameObject.Instantiate(this.arrow, shootOutPosition, best_rotation); Vector3 s1 = arrowCopy.transform.localScale; Vector3 s2 = bowCamera.transform.localScale; arrowCopy.transform.localScale = new Vector3(s1.x * s2.x, s1.y * s2.y, s1.z * s2.z); // arrowCopy.transform.LookAt(rayHitPoint); Arrow arrowComp = arrowCopy.AddComponent(); arrowComp.armBow = this; arrowComp.shootOutPosition = shootOutPosition; arrowComp.raycastHit = raycastHit; // Arrow.speed = DebugBowPower.ins.getPowerPercent() * 100f; // Arrow.speed = BaseSpeedSlider.ins.getValue(); // Arrow.speed = Mathf.Pow(ShootCheck.ins.shootSpeed, ShootCheck.ins.shootSpeed < 13 ? 2f: (ShootCheck.ins.shootSpeed < 15 ? 2.5f : 3.0f)); if (ShootCheck.ins && !GameMgr.debugInEditor) { Arrow.speed = GameMgr.RealSizeToGameSize(ShootCheck.ins.shootSpeed); } arrowCopy.SetActive(true); arrow.SetActive(false); AudioMgr.ins.PlayShoot(AudioMgr.GetAudioSource(arrowCopy)); // this.gameObject.SetActive(false); } public void OnEnable() { AudioMgr.GetAudioSource(this.gameObject).clip = null; } public void Hide() { this.transform.localScale = Vector3.zero; } public void Show() { this.transform.localScale = new Vector3(1, 1, 1); } public bool NeedCrossHair() { return canShoot; } //debug public void mouseDown() { if (!this.readying) return; if (this.pulling || this.canShoot) return; this.idleToADS(); } public void mouseUp() { if (!this.readying) return; if (this.pulling) { this.idle(); } else if (this.canShoot) { this.ADS_fire(); } } }