VR模拟枪支打靶,消灭鬼怪,换弹以及上弦等等硬核枪支操作。 使用HTCVive设备,开启SteamVR进行游玩。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

189 lines
6.2 KiB

using HTC.UnityPlugin.PoseTracker;
using HTC.UnityPlugin.Utility;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace HTC.UnityPlugin.Vive
{
public abstract class GrabbableBase<TGrabber> : BasePoseTracker where TGrabber : class, GrabbableBase<TGrabber>.IGrabber
{
public const float MIN_FOLLOWING_DURATION = 0.02f;
public const float DEFAULT_FOLLOWING_DURATION = 0.04f;
public const float MAX_FOLLOWING_DURATION = 0.5f;
public interface IGrabber
{
RigidPose grabberOrigin { get; }
RigidPose grabOffset { get; }
}
private struct PoseSample
{
public float time;
public RigidPose pose;
}
private Queue<PoseSample> m_poseSamples = new Queue<PoseSample>();
private OrderedIndexedSet<TGrabber> m_grabbers = new OrderedIndexedSet<TGrabber>();
private bool m_grabMutex;
private Action m_afterGrabberGrabbed;
private Action m_beforeGrabberReleased;
private Action m_onGrabberDrop;
public virtual float followingDuration { get { return DEFAULT_FOLLOWING_DURATION; } set { } }
public virtual bool overrideMaxAngularVelocity { get { return true; } set { } }
public TGrabber currentGrabber { get; private set; }
public bool isGrabbed { get { return currentGrabber != null; } }
public Rigidbody grabRigidbody { get; set; }
public event Action afterGrabberGrabbed { add { m_afterGrabberGrabbed += value; } remove { m_afterGrabberGrabbed -= value; } }
public event Action beforeGrabberReleased { add { m_beforeGrabberReleased += value; } remove { m_beforeGrabberReleased -= value; } }
public event Action onGrabberDrop { add { m_onGrabberDrop += value; } remove { m_onGrabberDrop -= value; } }
protected virtual void Awake()
{
grabRigidbody = GetComponent<Rigidbody>();
}
protected bool AddGrabber(TGrabber grabber)
{
if (grabber == null || m_grabbers.Contains(grabber)) { return false; }
CheckRecursiveException("AddGrabber");
if (isGrabbed && m_beforeGrabberReleased != null)
{
m_grabMutex = true;
m_beforeGrabberReleased();
m_grabMutex = false;
}
m_grabbers.Add(grabber);
currentGrabber = grabber;
if (m_afterGrabberGrabbed != null)
{
m_afterGrabberGrabbed();
}
return true;
}
protected bool RemoveGrabber(TGrabber grabber)
{
if (grabber == null || !m_grabbers.Contains(grabber)) { return false; }
CheckRecursiveException("RemoveGrabber");
if (m_grabbers.Count == 1)
{
ClearGrabbers(true);
}
else if (grabber == currentGrabber)
{
if (m_beforeGrabberReleased != null)
{
m_grabMutex = true;
m_beforeGrabberReleased();
m_grabMutex = false;
}
m_grabbers.Remove(grabber);
currentGrabber = m_grabbers.GetLast();
if (m_afterGrabberGrabbed != null)
{
m_afterGrabberGrabbed();
}
}
else
{
m_grabbers.Remove(grabber);
}
return true;
}
protected void ClearGrabbers(bool doDrop)
{
if (m_grabbers.Count == 0) { return; }
CheckRecursiveException("ClearGrabbers");
if (m_beforeGrabberReleased != null)
{
m_grabMutex = true;
m_beforeGrabberReleased();
m_grabMutex = false;
}
m_grabbers.Clear();
currentGrabber = null;
if (doDrop)
{
if (grabRigidbody != null && !grabRigidbody.isKinematic && m_poseSamples.Count > 0)
{
var framePose = m_poseSamples.Dequeue();
var deltaTime = Time.time - framePose.time;
RigidPose.SetRigidbodyVelocity(grabRigidbody, framePose.pose.pos, transform.position, deltaTime);
RigidPose.SetRigidbodyAngularVelocity(grabRigidbody, framePose.pose.rot, transform.rotation, deltaTime, overrideMaxAngularVelocity);
m_poseSamples.Clear();
}
if (m_onGrabberDrop != null)
{
m_onGrabberDrop();
}
}
}
protected void OnGrabRigidbody()
{
var targetPose = currentGrabber.grabberOrigin * currentGrabber.grabOffset;
ModifyPose(ref targetPose, null);
RigidPose.SetRigidbodyVelocity(grabRigidbody, grabRigidbody.position, targetPose.pos, followingDuration);
RigidPose.SetRigidbodyAngularVelocity(grabRigidbody, grabRigidbody.rotation, targetPose.rot, followingDuration, overrideMaxAngularVelocity);
}
protected void OnGrabTransform()
{
var targetPose = currentGrabber.grabberOrigin * currentGrabber.grabOffset;
ModifyPose(ref targetPose, null);
if (grabRigidbody != null)
{
grabRigidbody.velocity = Vector3.zero;
grabRigidbody.angularVelocity = Vector3.zero;
}
transform.position = targetPose.pos;
transform.rotation = targetPose.rot;
}
protected void RecordLatestPosesForDrop(float currentTime, float recordLength)
{
while (m_poseSamples.Count > 0 && (currentTime - m_poseSamples.Peek().time) > recordLength)
{
m_poseSamples.Dequeue();
}
m_poseSamples.Enqueue(new PoseSample()
{
time = currentTime,
pose = new RigidPose(transform),
});
}
private void CheckRecursiveException(string func)
{
if (!m_grabMutex) { return; }
throw new Exception("[" + func + "] Cannot Add/Remove Grabber recursivly");
}
}
}