using System; using System.Collections; using System.Collections.Generic; using UnityEngine; /* 弓对象 */ public class ArmBow : MonoBehaviour { [SerializeField] AnimationPlayer AP_arm; [SerializeField] AnimationPlayer AP_bow; [SerializeField] public GameObject arrow; [SerializeField] GameObject bullet; [SerializeField] GameObject armObj; [SerializeField] GameObject bowObj; BowCamera _bowCamera; BowCamera bowCamera { get { if (!_bowCamera) _bowCamera = GetComponentInParent(); return _bowCamera; } } //有效射击目标集合,可以理解为射中集合中的目标才能得分 public HashSet validTargets = new HashSet(); //本地坐标z public const float localPosZ = -0.1f; //射箭姿态记录索引倒退数,根据射击难度制造误差 [NonSerialized] public int shootBackTime = 0; [NonSerialized] public float shootOffsetAngleScale = 0; //禁止准备的外部接口 [NonSerialized] public bool banReady = false; //禁止射击的外部接口 [NonSerialized] public bool banShoot = false; //禁止逻辑,只用于同步状态和渲染,目前用于联机 [NonSerialized] public bool banLogic = false; //过去几帧的镜头值记录 Quaternion[] cameraRotations = new Quaternion[6]; int cameraRotationHasRecordCount = 0; #region logic state [NonSerialized] public int phase = -1; //当前阶段 void UpdatePhase() { if (phase == -1) return; if (phase == 0) { //拉弓前的准备 if (arm_ani_index_cur != 0) { AP_arm.play(arm_ani_index_cur = 0, WrapMode.Once); AP_arm.completeCallback = onComplete; } if (bow_ani_index_cur != 0) { AP_bow.play(bow_ani_index_cur = 0, WrapMode.Once); } } else if (phase == 1) { //拉弓过程 if (arm_ani_index_cur != 2) { AP_arm.play(arm_ani_index_cur = 2, WrapMode.Once); AP_arm.completeCallback = onComplete; } if (bow_ani_index_cur != 2) { AP_bow.play(bow_ani_index_cur = 2, WrapMode.Once); } this.bowCamera.updateFollowPullBow(); } else if (phase == 2) { //拉完完成,等待发射 if (arm_ani_index_cur != 2) { AP_arm.play(arm_ani_index_cur = 2, WrapMode.Once); AP_arm.completeCallback = onComplete; } if (bow_ani_index_cur != 2) { AP_bow.play(bow_ani_index_cur = 2, WrapMode.Once); } } else if (phase == 3) { //射出后 if (arm_ani_index_cur != 3) { AP_arm.play(arm_ani_index_cur = 3, WrapMode.Once); AP_arm.completeCallback = onComplete; } if (bow_ani_index_cur != 3) { AP_bow.play(bow_ani_index_cur = 3, WrapMode.Once); } } if (!IsCanShoot()) { this.bowCamera.updateGiveUpPullBow(); } } void onComplete(AnimationPlayerCompleteResult res) { if (res.index == 0 && !banLogic) { this.phase = 1; } else if (res.index == 2 && !banLogic) { this.phase = 2; GameMgr.ins.gameMode.ResumeTimeCounting(this); } } public bool IsCanShoot() { return phase == 2; } #endregion #region display state int arm_ani_index_cur = -1; int bow_ani_index_cur = -1; #endregion private static ArmBow _ins; public static ArmBow ins { get { if (!_ins) { _ins = GameObject.FindObjectOfType(); } return _ins; } } void Awake() { _ins = this; this.transform.localPosition = new Vector3(0.0865f, -1.692f, -0.1f); //initdata Vector3 localPos = transform.localPosition; localPos.z = localPosZ; transform.localPosition = localPos; int currentShootLevel = UserSettings.ins.shootLevel; shootBackTime = new int[]{0, 2, 5}[currentShootLevel]; shootOffsetAngleScale = new float[]{0, 10f, 10f}[currentShootLevel]; //不同模式下设置速度,用于调整射击间隔 if (GlobalData.MyDeviceMode == DeviceMode.Gun) { AP_arm.speed = 20; AP_bow.speed = 20; } //根据 hideInfraredBowAndArrow 判断是否显示隐藏 if (PlayerPrefs.HasKey("hideInfraredBowAndArrow") && PlayerPrefs.GetInt("hideInfraredBowAndArrow") != 0) { armObj.SetActive(false); bowObj.SetActive(false); //解除默认 hide 状态 PlayerPrefs.SetInt("hideInfraredBowAndArrow", 2); } else { //枪模式下隐藏手臂等 if (GlobalData.MyDeviceMode == DeviceMode.Gun) { armObj.SetActive(false); bowObj.SetActive(false); AP_arm.speed = 10; } else { armObj.SetActive(UserSettings.ins.openBowAndArrow); bowObj.SetActive(UserSettings.ins.openBowAndArrow); } } } void Start() { this.readyShoot(); } void OnDestroy() { if (_ins == this) _ins = null; } void OnEnable() { AudioMgr.GetAudioSource(this.gameObject).clip = null; } void Update() { UpdatePhase(); #if UNITY_EDITOR if (Input.GetKeyDown(KeyCode.Q)) this.ADS_fire(true); #endif } void FixedUpdate() { // 记录一些旋转角---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 } public void readyShoot() { if (banLogic) return; this.bowCamera.SetCameraFieldOfViewRecord(this.bowCamera.defaultCameraFieldOfView); if (banReady) return; GameMgr.ins.gameMode.PauseTimeCounting(this); GameMgr.ins.gameMode.onBowReady(); this.phase = 0; } public void ADS_fire(bool bAddCount = false) { if (!IsCanShoot() || banShoot || GameMgr.ins.gamePause || banLogic || GameMgr.ins.gameOver) return; //枪模式连接的情况下需要判断子弹 if (Billboard.ins && Billboard.ins.isBulletStatus) { if (Billboard.ins.bulletManager.bulletZero()) return; //发射消耗子弹 Billboard.ins.bulletManager.FireBullet(); } GameMgr.ins.gameMode.onBowShoot(); //记录射箭 if(bAddCount)GameMgr.ins.userGameAnalyse.onShootEvent(); this.phase = 3; shoot(); } void shoot() { #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 = BowCamera.ins.transform.rotation; BowCamera.ins.transform.rotation = absolute_rotation; RaycastHit absoluteRay = CrossHair.ins.GetRaycastHit(); BowCamera.ins.transform.rotation = oldCameraRotation; Vector3 shootOutPosition = this.bowCamera.transform.position; Vector3 arrowEuler = absolute_rotation.eulerAngles; arrowEuler.z = 0; //绝对角可能是从原始九轴记录数组里取出来的,它的z可能不是0 GameObject arrowCopy = Instantiate(GlobalData.MyDeviceMode == DeviceMode.Archery? arrow : bullet, shootOutPosition, Quaternion.Euler(arrowEuler)); arrowCopy.SetActive(true); 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() : Quaternion.Angle(absolute_rotation, final_rotation); arrowComp.finalAngleAfterOffset = final_rotation.eulerAngles; if (GlobalData.MyDeviceMode == DeviceMode.Gun) { //枪的速度,设置800 Arrow.speed = 400; AudioMgr.ins.PlayGunShoot(AudioMgr.GetAudioSource(arrowCopy)); } else { if (ShootCheck.ins && !GameMgr.debugInEditor && !BowCamera.isTouchMode) { Arrow.speed = GameMgr.RealSizeToGameSize(ShootCheck.ins.shootSpeed); } AudioMgr.ins.PlayShoot(AudioMgr.GetAudioSource(arrowCopy)); } GameEventCenter.ins.onBowArrowShootOut?.Invoke(this, arrowComp); if (AimHandler.ins) AimHandler.ins.Ban9AxisCalculate(true); } public void Hide() { this.transform.localScale = Vector3.zero; } public void Show() { this.transform.localScale = new Vector3(1, 1, 1); } }