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; 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 = 0; shootBackTime = new int[]{0, 2, 5}[currentShootLevel]; shootOffsetAngleScale = new float[]{0, 10f, 10f}[currentShootLevel]; } 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(); #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() { if (!IsCanShoot() || banShoot || GameMgr.ins.gamePause || banLogic || GameMgr.ins.gameOver) return; GameMgr.ins.gameMode.onBowShoot(); this.phase = 3; shoot(); } [NonSerialized] public float shootSpeed = 30; 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 = 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 =Quaternion.Angle(absolute_rotation, final_rotation); arrowComp.finalAngleAfterOffset = final_rotation.eulerAngles; Arrow.speed = GameMgr.RealSizeToGameSize(shootSpeed); AudioMgr.ins.PlayShoot(AudioMgr.GetAudioSource(arrowCopy)); } public void Hide() { this.transform.localScale = Vector3.zero; } public void Show() { this.transform.localScale = new Vector3(1, 1, 1); } }