326 lines
9.3 KiB
C#
326 lines
9.3 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// 手类型
|
|
/// </summary>
|
|
public enum HandType
|
|
{
|
|
Left,
|
|
Right
|
|
}
|
|
|
|
/// <summary>
|
|
/// 手状态
|
|
/// </summary>
|
|
public enum HandState
|
|
{
|
|
/// <summary>
|
|
/// 空手
|
|
/// </summary>
|
|
Empty,
|
|
/// <summary>
|
|
/// 有武器
|
|
/// </summary>
|
|
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<Collider>().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<CoroutineTaskManager>.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<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
|
|
GameLocal.Ins.HitUI.SetActive(false), 1f, this);
|
|
}
|
|
return currentHp;
|
|
}
|
|
|
|
public void End()
|
|
{
|
|
Debug.Log("游戏结束");
|
|
IsAlive = false;
|
|
pullHand.bow.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
|