using System; using System.Collections; using System.Collections.Generic; using UnityEngine; /* 弓对象 */ public class ArmBow : MonoBehaviour { [SerializeField] AnimationPlayer AP_arm; [SerializeField] AnimationPlayer AP_bow; [SerializeField] GameObject arrow; BowCamera _bowCamera; BowCamera bowCamera { get { if (!_bowCamera) _bowCamera = GetComponentInParent(); return _bowCamera; } } //有效射击目标集合,可以理解为射中集合中的目标才能得分 public HashSet validTargets = new HashSet(); //射箭姿态记录索引倒退数,根据射击难度制造误差 [NonSerialized] public int shootBackTime = 0; [NonSerialized] public float shootOffsetAngleScale = 0; bool canShoot = false; bool pulling = false; bool readying = false; //禁止准备的外部接口 [NonSerialized] public bool banReady = false; //禁止射击的外部接口 [NonSerialized] public bool banShoot = false; //九轴姿态记录 // [NonSerialized] public Quaternion[] recordRotations = new Quaternion[100]; // float[] recordRotationVars = new float[99]; // [NonSerialized] public int recordCount = 0; //过去几帧的镜头值记录 Quaternion[] cameraRotations = new Quaternion[6]; int cameraRotationHasRecordCount = 0; public static ArmBow ins; void Awake() { ins = this; //initdata int currentShootLevel = LoginMgr.myUserInfo.shootLevel; shootBackTime = new int[]{0, 2, 5}[currentShootLevel]; shootOffsetAngleScale = new float[]{0, 7.5f, 10f}[currentShootLevel]; } void Start() { this.readyShoot(); } void FixedUpdate() { if (this.canShoot) { if (DebugBowPower.ins) DebugBowPower.ins.DoUpdate(); } // 记录一些旋转角---start if (this.bowCamera) { for (int i = cameraRotations.Length - 1; i > 0 ; i--) { cameraRotations[i] = cameraRotations[i - 1]; } cameraRotations[0] = this.bowCamera.transform.rotation; cameraRotationHasRecordCount++; } // 记录一些旋转角---end } 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.SetCameraFieldOfViewRecord(60); this.ready(); } void shoot() { // 筛选出一个稳定的发射角度 // #region // bool useAxisData = false;//表示是否使用了九轴原始数据 // Quaternion absolute_rotation = this.bowCamera.transform.rotation; // Quaternion final_rotation = this.bowCamera.transform.rotation; // if (recordCount >= recordRotations.Length) { // for (int i = 0; i < recordRotationVars.Length; i++) { // recordRotationVars[i] = Quaternion.Angle(recordRotations[i], recordRotations[i + 1]); // } // int startCheckIndex = 5; // int checkAfterCount = 5; // float min_wave = float.MaxValue; // for (int i = startCheckIndex; i < recordRotationVars.Length - checkAfterCount; i++) // { // float wave = 0; // for (int j = i; j <= i + checkAfterCount; j++) // { // wave += recordRotationVars[j]; // } // if (wave < min_wave) // { // min_wave = wave; // int best_rotation_index = i; // absolute_rotation = recordRotations[best_rotation_index]; // best_rotation_index -= this.shootBackTime; // if (best_rotation_index < 0) best_rotation_index = 0; // final_rotation = recordRotations[best_rotation_index]; // useAxisData = true; // } // } // if (useAxisData) {//坐标轴换算,原始九轴数据直接用可能会出问题,比如相机的父节点Rotation不为identity时 // Quaternion baseQuat = GameMgr.ins.transform.rotation; // absolute_rotation = baseQuat * absolute_rotation; // final_rotation = baseQuat * final_rotation; // } // } // #endregion #region Quaternion absolute_rotation = this.bowCamera.transform.rotation; Quaternion final_rotation = this.bowCamera.transform.rotation; if (cameraRotationHasRecordCount >= cameraRotations.Length) { absolute_rotation = cameraRotations[5]; final_rotation = cameraRotations[5 - this.shootBackTime]; } #endregion Quaternion oldCameraRotation = Camera.main.transform.rotation; Camera.main.transform.rotation = absolute_rotation; RaycastHit absoluteRay = CrossHair.ins.GetRaycastHit(); Camera.main.transform.rotation = oldCameraRotation; Vector3 shootOutPosition = this.bowCamera.transform.position; Vector3 arrowEuler = absolute_rotation.eulerAngles; arrowEuler.z = 0; //绝对角可能是从原始九轴记录数组里取出来的,它的z可能不是0 GameObject arrowCopy = GameObject.Instantiate(this.arrow, shootOutPosition, Quaternion.Euler(arrowEuler)); 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); Arrow arrowComp = arrowCopy.AddComponent(); arrowComp.armBow = this; arrowComp.shootOutPosition = shootOutPosition; arrowComp.absoluteRay = absoluteRay; arrowComp.offsetAngle = GameDebug.ins ? GameDebug.ins.GetOffsetAngle() : FormatAngle(Quaternion.Angle(absolute_rotation, final_rotation)); arrowComp.finalAngleAfterOffset = final_rotation.eulerAngles; if (ShootCheck.ins && !GameMgr.debugInEditor && !BowCamera.isTouchMode) { Arrow.speed = GameMgr.RealSizeToGameSize(ShootCheck.ins.shootSpeed); } arrowCopy.SetActive(true); arrow.SetActive(false); GameEventCenter.ins.onBowArrowShootOut?.Invoke(this, arrowComp); AudioMgr.ins.PlayShoot(AudioMgr.GetAudioSource(arrowCopy)); // this.gameObject.SetActive(false); if (AimHandler.ins) AimHandler.ins.BanControlObjRotate(true); } //因为Unity引擎的规则,向上时359~270度,向下是0~90度 //为了方便数学运算,换算成 向上时0~90度,向下是0~-90度 float FormatAngle(float value) { if (value > 180) value = 360 - value; else value = -value; return value; } 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 IsCanShoot() { return canShoot; } 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(); } } }