Files
MRSnowWhite/Assets/_SnowWhite/Scripts/Player/RightHand.cs

402 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}