using System; using System.Collections; using System.Collections.Generic; using DarkTonic.MasterAudio; using DG.Tweening; using DragonLi.Core; using Mirror; using UnityEngine; using UnityEngine.XR; using Random = UnityEngine.Random; /// /// 手类型 /// public enum HandType { Left, Right } /// /// 手状态 /// public enum HandState { /// /// 空手 /// Empty, /// /// 有武器 /// HaveWeapon } public class Player : MonoBehaviour, Damagable { public Transform LeftHand; public Transform RightHand; public InputDevice leftHandDevice; private InputDevice rightHandDevice; public bool isClickSwith = false; public PullHand pullHand; [Header("经验系统")] public int exp; // 当前经验值 private int[] levelThresholds = { 1000, 2000, 3000 }; // 每级经验阈值 private int bowLevel = 0; [Header("弓管理")] public Bow[] bows; // 不同等级的弓 public GameObject levelUpEffect; // 升级特效预制体 public GameObject expEffect; //经验特效 public GameObject expEndEffect; // 升级爆炸特效预制体 //private Bow currentBow; [SoundGroup] public string bgmSound; public bool isDie; public bool IsAlive = true; private float time = 0; [Header("玩家最大血量")] public float maxHp = 1; private float currentHp; public float Health { get => currentHp; set => currentHp = value; } public void Start() { GameLocal.Ins.self = this; maxHp = 100; currentHp = maxHp; // 默认装备第一把弓 EquipBow(0); levelUpEffect.SetActive(false); MasterAudio.PlaySound(bgmSound); #if !UNITY_EDITOR && UNITY_ANDROID && PICO leftHandDevice = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand); rightHandDevice = InputDevices.GetDeviceAtXRNode(XRNode.RightHand); #endif } // 增加经验 public void GetEx(int amount, Vector3 fromPos) { // 生成经验特效飞向弓 StartCoroutine(ShowExpEffect(fromPos)); exp += amount; Debug.Log($"获得经验:{amount},当前经验:{exp}"); // 检查是否升级 CheckLevelUp(); } private IEnumerator ShowExpEffect(Vector3 fromPos) { GameObject expFx = Instantiate(expEffect, fromPos, Quaternion.identity); expFx.transform.localScale = Vector3.one; Transform target = LeftHand != null ? LeftHand : transform; float duration = 1f; float elapsed = 0f; Vector3 startPos = fromPos; // 在 duration 时间内,动态跟踪目标位置 while (elapsed < duration) { elapsed += Time.deltaTime; float t = Mathf.Clamp01(elapsed / duration); // 实时目标位置(弓可能在移动) Vector3 targetPos = target.position; // 使用插值平滑移动 expFx.transform.position = Vector3.Lerp(startPos, targetPos, t); yield return null; } // 抵达弓位置后生成结束特效 if (pullHand.bow != null && expEndEffect != null) { GameObject expEndFx = Instantiate(expEndEffect, pullHand.bow.transform.position, Quaternion.identity); CoroutineTaskManager.Instance.WaitSecondTodo(() => { Destroy(expEndFx); }, 2f); } Destroy(expFx); } private void CheckLevelUp() { if (bowLevel < levelThresholds.Length && exp >= levelThresholds[bowLevel]) { bowLevel++; EquipBow(bowLevel); levelUpEffect.SetActive(true); Debug.Log($"弓升级到 Lv{bowLevel + 1}"); } } private void EquipBow(int index) { for (int i = 0; i < bows.Length; i++) { bows[i].gameObject.SetActive(i == index); } pullHand.bow = bows[index]; } public void UserBow(bool isUser) { pullHand.IsUserBow(isUser); } public void PlaySwitchBowSound() { MasterAudio.PlaySound("获取"); } private void Update() { // 滚轮切换弓 if (Input.mouseScrollDelta.y > 0&&IsAlive) { // 摇杆朝左 isClickSwith = true; int prev = Mathf.Max(0, bowLevel - 1); EquipBow(prev); PlaySwitchBowSound(); } else if (Input.mouseScrollDelta.y < 0&IsAlive) { // 摇杆朝右 isClickSwith = true; int next = Mathf.Min(bows.Length - 1, bowLevel); EquipBow(next); PlaySwitchBowSound(); } #if !UNITY_EDITOR && UNITY_ANDROID && PICO if (rightHandDevice != null) { Vector2 value; rightHandDevice.TryGetFeatureValue(CommonUsages.primary2DAxis, out value); if (value.magnitude > 0) { // 根据轴的值判断摇杆朝向 if (!isClickSwith && value.x < 0 && GameManager.Ins.isGameStart) { // 摇杆朝左 isClickSwith = true; int prev = Mathf.Max(0, bowLevel - 1); EquipBow(prev); PlaySwitchBowSound(); } else if (!isClickSwith && value.x > 0 && GameManager.Ins.isGameStart) { // 摇杆朝右 isClickSwith = true; int next = Mathf.Min(bows.Length - 1, bowLevel); EquipBow(next); PlaySwitchBowSound(); } } else if (value.magnitude == 0) { isClickSwith = false; } if (value.Equals(Vector2.zero)) { isClickSwith = false; } } #endif if (!IsAlive) { time += Time.deltaTime; if (time >= 1f) GameLocal.Ins.dieTxt.text = "4"; if (time >= 2f) GameLocal.Ins.dieTxt.text = "3"; if (time >= 3f) GameLocal.Ins.dieTxt.text = "2"; if (time >= 4f) GameLocal.Ins.dieTxt.text = "1"; return; } Transform mainCamera = GameLocal.Ins.MRCamera.transform; Transform leftControl = GameLocal.Ins.MRLeftControl; Transform rightControl = GameLocal.Ins.MRRightControl; LeftHand.transform.position = leftControl.position; LeftHand.transform.rotation = leftControl.rotation; RightHand.transform.position = rightControl.position; RightHand.transform.rotation = rightControl.rotation; // 同步相机 transform.position = mainCamera.position; transform.rotation = mainCamera.rotation; if (Input.GetKeyDown(KeyCode.Q)) { GameManager.Ins.CloseCurBoss(); } } private void OnTriggerEnter(Collider other) { Debug.LogError("触碰开始:"+other.gameObject.name); // 开始游戏 if (other.tag == "Door") { Debug.Log("触碰开始"); other.gameObject.GetComponent().enabled = false; other.gameObject.SetActive(false); Destroy(other.gameObject); GameManager.Ins.GameStart(); } } public void ApplyDamage(float value, int ownerIndex, Vector3 hitPos, Transform sender) { OnReceiveDamage(value,hitPos,sender); } public void SetBlood(float num) { currentHp += num; EventDispatcher.TriggerEvent("HpChange", currentHp, maxHp); } public float OnReceiveDamage(float damage,Vector3 hitPos,Transform _sender) { float curDamage = damage; SetBlood(-curDamage); #if !UNITY_EDITOR && UNITY_ANDROID && PICO if (_sender != null) { Vector3 forward = transform.forward; Vector3 directionFormHit=(transform.position-hitPos).normalized; float angle = Vector3.Angle(forward, directionFormHit); int index = Random.Range(0, 4); if(TrueGearEffectManager.Ins!=null) TrueGearEffectManager.Ins.OnHit(angle > 90,index,false); } #endif if (currentHp <= 0 && IsAlive) { IsAlive = false; isDie = true; UserBow(false); GameLocal.Ins.DieUI.SetActive(true); GameLocal.Ins.dieTxt.text = ""; GameManager.Ins.PlaySound2DRPC("1.35"); MonoSingleton.Instance.WaitSecondTodo(() => { IsAlive = true; isDie = false; UserBow(true); GameLocal.Ins.DieUI.SetActive(false); currentHp = maxHp; EventDispatcher.TriggerEvent("HpChange", currentHp, maxHp); time = 0f; }, 5f, this); } else if (currentHp > 0) { GameLocal.Ins.HitUI.SetActive(true); MonoSingleton.Instance.WaitSecondTodo(() => GameLocal.Ins.HitUI.SetActive(false), 1f, this); } return currentHp; } public void End() { Debug.Log("游戏结束"); IsAlive = false; pullHand.bow.gameObject.SetActive(false); } }