402 lines
10 KiB
C#
402 lines
10 KiB
C#
using System.Globalization;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using Pico.Platform;
|
||
using UnityEngine;
|
||
using System;
|
||
using DG.Tweening;
|
||
using DragonLi.Core;
|
||
using UnityEngine.XR.Interaction.Toolkit;
|
||
using TrackedPoseDriver = UnityEngine.SpatialTracking.TrackedPoseDriver;
|
||
|
||
/// <summary>
|
||
/// 击打结果
|
||
/// </summary>
|
||
public enum HitResult
|
||
{
|
||
None, // 无效击打
|
||
Hit, // 击中雕像
|
||
TargetBreak, // 击碎目标雕像
|
||
WrongBreak // 击碎错误雕像
|
||
}
|
||
|
||
public class RightHand : MonoBehaviour
|
||
{
|
||
public TrackedPoseDriver tracked;
|
||
|
||
private HandState _cachePlayerState;
|
||
|
||
// 射线
|
||
public LayerMask layerMask;
|
||
public Transform ray;
|
||
|
||
[Tooltip("手模型")] public GameObject hand;
|
||
|
||
public GameObject hit;
|
||
|
||
private int _cacheTargetId = -1;
|
||
|
||
private Vector3 _curPos;
|
||
private bool _isStartTrigger;
|
||
|
||
public bool isTrigger;
|
||
|
||
public float triggerDis;
|
||
|
||
public bool _isOpenLine = false;
|
||
|
||
//拼图Id
|
||
public int puzzleId;
|
||
|
||
private Collider _collider = null;
|
||
|
||
public Collider selfCollider
|
||
{
|
||
get
|
||
{
|
||
if (_collider == null)
|
||
{
|
||
_collider = GetComponentInChildren<Collider>();
|
||
}
|
||
return _collider;
|
||
}
|
||
}
|
||
|
||
public void Start()
|
||
{
|
||
tracked.enabled = true;
|
||
selfCollider.enabled = true;
|
||
GameManager.Ins.playerRightHand=this;
|
||
MRInput.Ins.RegisterClickRrightTrigger(ClickRrightTrigger);
|
||
Init();
|
||
}
|
||
|
||
public void Init()
|
||
{
|
||
hand.SetActive(true);
|
||
statueEventHandObject.SetActive(false);
|
||
_isOpenLine = true;
|
||
}
|
||
|
||
public void Update()
|
||
{
|
||
if (Input.GetKeyDown(KeyCode.Space))
|
||
{
|
||
|
||
}
|
||
|
||
#if UNITY_EDITOR
|
||
Transform camera = GameLocal.Ins.MRCamera.transform;
|
||
transform.position = camera.position + camera.forward * 0.5f + camera.right * 0.2f + camera.up * -0.1f;
|
||
transform.rotation = camera.rotation;
|
||
#endif
|
||
|
||
ray.gameObject.SetActive(_isOpenLine);
|
||
isTrigger = MRInput.Ins.pressRightTrigger;
|
||
if (isTrigger&& !_isStartTrigger)
|
||
{
|
||
_isStartTrigger = true;
|
||
_curPos = transform.position;
|
||
}
|
||
else
|
||
{
|
||
_isStartTrigger = false;
|
||
}
|
||
triggerDis=isTrigger?transform.position.y-_curPos.y:0;
|
||
// 射线检测
|
||
if (_isOpenLine)
|
||
{
|
||
if (Physics.Raycast(transform.position, transform.forward, out RaycastHit handlingHit, 100F, layerMask))
|
||
{
|
||
|
||
}
|
||
else
|
||
{
|
||
hit = null;
|
||
}
|
||
}
|
||
|
||
// 雕像事件击打检测
|
||
if (isInStatueEventMode && enableStatueHitDetection)
|
||
{
|
||
UpdateStatueHitDetection();
|
||
}
|
||
|
||
// 更新手部速度(用于挥拳检测)
|
||
handVelocity = Vector3.Distance(transform.position, lastPosition) / Time.deltaTime;
|
||
lastPosition = transform.position;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新雕像击打检测
|
||
/// </summary>
|
||
private void UpdateStatueHitDetection()
|
||
{
|
||
// 检查击打时间间隔
|
||
if (Time.time - lastHitTime < hitInterval)
|
||
{
|
||
return; // 还在冷却时间内
|
||
}
|
||
|
||
// 方法1:基于手部速度的挥拳检测
|
||
if (handVelocity > swingVelocityThreshold)
|
||
{
|
||
HitResult result = CheckAndHitStatue();
|
||
if (result != HitResult.None)
|
||
{
|
||
lastHitTime = Time.time; // 更新上次击打时间
|
||
Debug.Log($"[RightHand] 挥拳击打雕像结果: {result}");
|
||
}
|
||
}
|
||
|
||
// 方法2:如果当前有碰撞的雕像,按扳机键击打
|
||
if (currentHitStatue != null && isTrigger)
|
||
{
|
||
HitResult result = HitCurrentStatue();
|
||
if (result != HitResult.None)
|
||
{
|
||
lastHitTime = Time.time; // 更新上次击打时间
|
||
Debug.Log($"[RightHand] 扳机击打雕像结果: {result}");
|
||
}
|
||
}
|
||
}
|
||
|
||
public void ClickRrightTrigger()
|
||
{
|
||
if(hit==null)
|
||
return;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 合成宝石钥匙
|
||
/// </summary>
|
||
public void CreateGemKey()
|
||
{
|
||
StartCoroutine(StartGemEnd());
|
||
}
|
||
|
||
IEnumerator StartGemEnd()
|
||
{
|
||
GameManager.Ins.PlaySound2DRPC("1.13");
|
||
|
||
yield return new WaitForSeconds(3f);
|
||
}
|
||
|
||
public void ChangeHand()
|
||
{
|
||
hand.SetActive(true);
|
||
_isOpenLine = true;
|
||
}
|
||
|
||
#region 水晶雕像击打方法
|
||
|
||
[Header("雕像击打配置")]
|
||
public float hitDistance = 1.5f; // 击打检测距离
|
||
public float hitRadius = 0.3f; // 击打检测半径
|
||
public LayerMask statueLayerMask; // 雕像层级
|
||
|
||
/// <summary>
|
||
/// 当前击中的雕像
|
||
/// </summary>
|
||
private CrystalStatue currentHitStatue;
|
||
|
||
/// <summary>
|
||
/// 检测并击打水晶雕像
|
||
/// </summary>
|
||
public HitResult CheckAndHitStatue()
|
||
{
|
||
// 使用球形检测
|
||
Collider[] hits = Physics.OverlapSphere(transform.position, hitRadius, statueLayerMask);
|
||
|
||
if (hits.Length > 0)
|
||
{
|
||
foreach (var collider in hits)
|
||
{
|
||
CrystalStatue statue = collider.transform.parent.GetComponent<CrystalStatue>();
|
||
if (statue != null && !statue.IsBroken())
|
||
{
|
||
return HitStatue(statue);
|
||
}
|
||
}
|
||
}
|
||
|
||
return HitResult.None;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 击打指定水晶雕像
|
||
/// </summary>
|
||
public HitResult HitStatue(CrystalStatue statue)
|
||
{
|
||
if (statue == null || statue.IsBroken())
|
||
{
|
||
return HitResult.None;
|
||
}
|
||
|
||
int healthBefore = statue.GetCurrentHealth();
|
||
statue.OnPlayerHit();
|
||
int healthAfter = statue.GetCurrentHealth();
|
||
|
||
// 判断击打结果
|
||
if (healthAfter <= 0)
|
||
{
|
||
// 雕像碎裂
|
||
if (statue.isTarget)
|
||
{
|
||
return HitResult.TargetBreak;
|
||
}
|
||
else
|
||
{
|
||
return HitResult.WrongBreak;
|
||
}
|
||
}
|
||
else if (healthAfter < healthBefore)
|
||
{
|
||
// 成功击打但未碎裂
|
||
return HitResult.Hit;
|
||
}
|
||
|
||
return HitResult.None;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取视线前方的水晶雕像
|
||
/// </summary>
|
||
public CrystalStatue GetStatueInFront()
|
||
{
|
||
if (Physics.Raycast(transform.position, transform.forward, out RaycastHit hitInfo, hitDistance, statueLayerMask))
|
||
{
|
||
CrystalStatue statue = hitInfo.collider.GetComponent<CrystalStatue>();
|
||
if (statue != null && !statue.IsBroken())
|
||
{
|
||
return statue;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 挥拳检测击打雕像(基于手部速度)
|
||
/// </summary>
|
||
/// <param name="velocityThreshold">速度阈值</param>
|
||
public HitResult CheckSwingHit(float velocityThreshold = 2f)
|
||
{
|
||
// 检测手部速度是否超过阈值
|
||
float handSpeed = tracked ? tracked.transform.GetComponent<Rigidbody>()?.velocity.magnitude ?? 0f : 0f;
|
||
|
||
if (handSpeed < velocityThreshold)
|
||
{
|
||
return HitResult.None;
|
||
}
|
||
|
||
return CheckAndHitStatue();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置当前击中的雕像(用于碰撞检测)
|
||
/// </summary>
|
||
public void SetCurrentHitStatue(CrystalStatue statue)
|
||
{
|
||
currentHitStatue = statue;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 击打当前碰撞的雕像
|
||
/// </summary>
|
||
public HitResult HitCurrentStatue()
|
||
{
|
||
if (currentHitStatue != null)
|
||
{
|
||
return HitStatue(currentHitStatue);
|
||
}
|
||
return HitResult.None;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 雕像事件道具切换
|
||
|
||
[Header("道具配置")]
|
||
public GameObject normalHandObject; // 普通手部道具
|
||
public GameObject statueEventHandObject; // 雕像事件专用道具(如手套)
|
||
|
||
[Header("击打检测配置")]
|
||
public bool enableStatueHitDetection = false; // 是否启用雕像击打检测
|
||
public float swingVelocityThreshold = 2f; // 挥拳速度阈值
|
||
public float hitInterval = 0.5f; // 击打时间间隔(秒)
|
||
|
||
/// <summary>
|
||
/// 是否处于雕像事件模式
|
||
/// </summary>
|
||
private bool isInStatueEventMode = false;
|
||
|
||
/// <summary>
|
||
/// 上次击打时间
|
||
/// </summary>
|
||
private float lastHitTime = 0f;
|
||
|
||
/// <summary>
|
||
/// 上一次的位置(用于计算速度)
|
||
/// </summary>
|
||
private Vector3 lastPosition;
|
||
|
||
/// <summary>
|
||
/// 手部速度
|
||
/// </summary>
|
||
private float handVelocity;
|
||
|
||
/// <summary>
|
||
/// 进入水晶雕像事件模式
|
||
/// </summary>
|
||
public void EnterStatueEventMode()
|
||
{
|
||
isInStatueEventMode = true;
|
||
enableStatueHitDetection = true;
|
||
|
||
// 隐藏射线
|
||
_isOpenLine = false;
|
||
if (ray != null)
|
||
ray.gameObject.SetActive(false);
|
||
|
||
// 切换道具
|
||
if (normalHandObject != null)
|
||
normalHandObject.SetActive(false);
|
||
if (statueEventHandObject != null)
|
||
statueEventHandObject.SetActive(true);
|
||
|
||
// 初始化位置追踪
|
||
lastPosition = transform.position;
|
||
handVelocity = 0f;
|
||
|
||
Debug.Log("[RightHand] 进入雕像事件模式,启用击打检测");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 退出水晶雕像事件模式
|
||
/// </summary>
|
||
public void ExitStatueEventMode()
|
||
{
|
||
isInStatueEventMode = false;
|
||
enableStatueHitDetection = false;
|
||
|
||
// 清空当前碰撞的雕像
|
||
currentHitStatue = null;
|
||
|
||
// 恢复射线
|
||
_isOpenLine = true;
|
||
if (ray != null)
|
||
ray.gameObject.SetActive(true);
|
||
|
||
// 切换道具
|
||
if (statueEventHandObject != null)
|
||
statueEventHandObject.SetActive(false);
|
||
if (normalHandObject != null)
|
||
normalHandObject.SetActive(true);
|
||
|
||
Debug.Log("[RightHand] 退出雕像事件模式,禁用击打检测");
|
||
}
|
||
|
||
#endregion
|
||
}
|