可直接下载使用下载地址
链接:https://pan.baidu.com/s/1RePkv1k9SUjz1IJM7Gcilw
提取码:ae2v
VRTK自带的拾取脚本虽然功能十分强大,但是对于某些开发并不友好,所以在VRTK的基础上,我重新编写了一个拾取功能的脚本
功能:拾取
GrabButton:(可以自行选择按钮,Trigger、Grip、Touchpad)
GrabMode:(可以自行选择拾取后松开方式,HoldButton长按拾取松手掉落、ToggleButton按以下拾取再按下掉落)
GarbTargetPoint:(拾取到之后在手下面的位置:HintPoint、Zero、SetPoint,从碰撞到的位置、从物体的零点、从自己设置position和rotation位置)
功能:抛出
IsAddForce:(勾选后,可以把物体任出去,而且会默认吧物体的物理属性打开)
功能:拾取与放手事件
PickupManager.OnPickUpTarget(GameObject obj)//当拾取到物品时触发,可调用
PickupManager.OnLetGoTarget(GameObject obj)//当放开物品时触发,可调用
这个挂在被拾取物体下
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Collider))]
[RequireComponent(typeof(Rigidbody))]
public class PickUpObject : MonoBehaviour
{
[Header("是否可以被拾取")]
public bool isCanPickUp = true;
[Header("*****——————拾取设置——————*****")]
public string pickUpSeting="拾取设置";
[Header("*****——————松手设置——————*****")]
public string letGoSeting = "松手设置";
/// <summary>
/// 拾取模式
/// </summary>
[Header("拾取模式")]
public TargetPoint garbTargetPoint;
/// <summary>
/// 拾取后位置设置
/// </summary>
[Header("位置设置")]
public Vector3 targetPosition;
/// <summary>
/// 拾取后角度设置
/// </summary>
[Header("位置设置")]
public Vector3 targetRotation;
/// <summary>
/// 松手后是否恢复到原父物体下,false设置为空
/// </summary>
[Header("松手后是否恢复到原父物体下,false设置为空")]
public bool isRestoreParent;
/// <summary>
/// 对象旧的父物体
/// </summary>
/// </summary>
public Transform oldFather;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void ChangeOldFather(Transform father)
{
oldFather = father;
}
}
public enum TargetPoint
{
Zero,
HitPoint,
SetPoint
}
按照自己意愿去设置,具体作用都有注解,就不多赘述了
这个挂在一个空对象下
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRTK;
[RequireComponent(typeof(CapsuleCollider))]
[RequireComponent(typeof(Rigidbody))]
public class PickupManager : MonoBehaviour
{
#region//Open Interface
public delegate void ActivatePickUpManagerEvent(Transform target);
public event ActivatePickUpManagerEvent OnPickUpTarget;
public event ActivatePickUpManagerEvent OnLetGoTarget;
#endregion
[Header("左右手选择")]
public SteamVR_TrackedObject grabHand;
private SteamVR_Controller.Device device;
[Header("拾取按钮")]
public ButtonGrab grabButton;
[Header("拾取模式")]
public GrabMode grabMode;
/// <summary>
/// 判断在ToggleButton模式下,按下时拾取还是放下
/// </summary>
private bool toggleModelIsLetgo;
[Header("松手时是否添加力,选择后默认禁用动力学")]
public bool isAddForce;
private float throwMultiplier;
private Vector3 lastUpdatePosition;
private Vector3 lastUpdateRotation;
private void Start()
{
SetMyCapsuleCollider();
SetMyRigidbody();
transform.SetParent(grabHand.transform);
ResetTransform();
OnPickUpTarget += OnPickUpEventActive;
OnLetGoTarget += OnLetGoEventActive;
}
private void OnDestroy()
{
OnPickUpTarget -= OnPickUpEventActive;
OnLetGoTarget -= OnLetGoEventActive;
}
private void OnPickUpEventActive(Transform target)
{
//Debug.Log("拾取" + target.name);
}
private void OnLetGoEventActive(Transform target)
{
//Debug.Log("放下" + target.name);
}
private void OnTriggerStay(Collider other)
{
if (grabHand.index != SteamVR_TrackedObject.EIndex.None)
{
device = SteamVR_Controller.Input((int)grabHand.index);
if (other.transform.GetComponent<PickUpObject>())
{
if (other.transform.GetComponent<PickUpObject>().isCanPickUp)
{
PickUpTarget(other.transform);
}
}
}
}
private void Update()
{
if (targetTransform)
{
if (transform.childCount == 0)
{
targetTransform = null;
toggleModelIsLetgo = false;
}
}
if (grabHand.index != SteamVR_TrackedObject.EIndex.None)
{
device = SteamVR_Controller.Input((int)grabHand.index);
switch (grabMode)
{
case GrabMode.HoldButton:
GrabModeHoldButton();
break;
case GrabMode.ToggleButton:
GrabModeToggleButton();
break;
default:
break;
}
}
if (isAddForce)
{
if (targetTransform)
{
if (lastUpdatePosition != Vector3.zero)
{
throwMultiplier = (transform.position - lastUpdatePosition).magnitude;
lastUpdateRotation = (transform.position - lastUpdatePosition).normalized;
}
lastUpdatePosition = transform.position;
}
}
}
/// <summary>
/// 拾取目标对象
/// </summary>
/// <param name="target"></param>
private void PickUpTarget(Transform target)
{
if (targetTransform == null)
{
bool canPickup = false;
//通过检测后canPickup=true;
//开始检测
switch (grabButton)
{
case ButtonGrab.TriggerPress:
if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger))//按下扳机
{
//Debug.Log(grabButton);
canPickup = true;
}
break;
case ButtonGrab.GripPress:
if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Grip))//按下侧边键
{
//Debug.Log(grabButton);
canPickup = true;
}
break;
case ButtonGrab.TouchpadPress:
if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Touchpad))//按下圆盘
{
//Debug.Log(grabButton);
canPickup = true;
}
break;
default:
break;
}
if (canPickup)
{
//目标对象赋值给targetTransform,用于后续传输参数
targetTransform = target;
//记录目标对象的刚体设置松手时还原
m_targetRigdbodyInspector = new TargetRigdbodyInspector(target.GetComponent<Rigidbody>().useGravity, target.GetComponent<Rigidbody>().isKinematic);
PickUpTargetInspector(target);
}
}
}
/// <summary>
/// 松开所拾取的对象
/// </summary>
private void LetGoTarget()
{
//手柄下方有物体且记录值不为空
if (transform.childCount > 0 && targetTransform != null)
{
//判断设置
if (targetTransform.GetComponent<PickUpObject>().isRestoreParent)
{
if (targetTransform.GetComponent<PickUpObject>().oldFather)
{
targetTransform.SetParent(targetTransform.GetComponent<PickUpObject>().oldFather);
}
else
{
targetTransform.SetParent(null);
}
}
else
{
targetTransform.SetParent(null);
}
toggleModelIsLetgo = false;
LetGoTargetInspector();
}
}
/// <summary>
/// 拾取后物体设置
/// </summary>
/// <param name="target"></param>
private void PickUpTargetInspector(Transform target)
{
target.SetParent(transform);
switch (target.GetComponent<PickUpObject>().garbTargetPoint)
{
case TargetPoint.Zero:
target.localPosition = Vector3.zero;
target.localEulerAngles = Vector3.zero;
break;
case TargetPoint.HitPoint:
break;
case TargetPoint.SetPoint:
target.localPosition = target.GetComponent<PickUpObject>().targetPosition;
target.localEulerAngles = target.GetComponent<PickUpObject>().targetRotation;
break;
default:
break;
}
target.GetComponent<Rigidbody>().isKinematic = true;
if (OnPickUpTarget != null)
{
OnPickUpTarget(targetTransform);
}
else
{
Debug.Log(111);
}
}
/// <summary>
/// 松手后物体设置
/// </summary>
private void LetGoTargetInspector()
{
//恢复刚体设置
targetTransform.GetComponent<Rigidbody>().isKinematic = m_targetRigdbodyInspector.isKinematic;
targetTransform.GetComponent<Rigidbody>().useGravity = m_targetRigdbodyInspector.useGravity;
//是否使用手柄偏移量添加物理效果写在这下面
if (isAddForce)
{
TargetAddForce(targetTransform.GetComponent<Rigidbody>());
}
//触发松手接口
OnLetGoTarget(targetTransform);
targetTransform = null;
}
/// <summary>
/// 将物体扔出
/// </summary>
/// <param name="objectRigidbody"></param>
private void TargetAddForce(Rigidbody objectRigidbody)
{
objectRigidbody.isKinematic = false;
objectRigidbody.velocity = lastUpdateRotation * throwMultiplier * 100;
objectRigidbody.angularVelocity = lastUpdateRotation * throwMultiplier;
}
#region//LetGo Judge
/// <summary>
/// Hold模式下松手判断
/// </summary>
private void GrabModeHoldButton()
{
if (targetTransform)
{
bool canLetgo = false;
switch (grabButton)
{
case ButtonGrab.TriggerPress:
if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Trigger))
{
//Debug.Log("松手" + grabButton);
canLetgo = true;
}
break;
case ButtonGrab.GripPress:
if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Grip))
{
Debug.Log("松手" + grabButton);
canLetgo = true;
}
break;
case ButtonGrab.TouchpadPress:
if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Touchpad))
{
Debug.Log("松手" + grabButton);
canLetgo = true;
}
break;
default:
break;
}
if (canLetgo)
{
LetGoTarget();
}
}
}
/// <summary>
/// Toggle模式下松手判断
/// </summary>
private void GrabModeToggleButton()
{
if (targetTransform)
{
bool canLetgo = false;
switch (grabButton)
{
case ButtonGrab.TriggerPress:
if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Trigger))
{
toggleModelIsLetgo = true;
}
if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger))
{
if (toggleModelIsLetgo)
{
//Debug.Log("松手" + grabButton);
canLetgo = true;
}
}
break;
case ButtonGrab.GripPress:
if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Grip))
{
toggleModelIsLetgo = true;
}
if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Grip))
{
if (toggleModelIsLetgo)
{
Debug.Log("松手" + grabButton);
canLetgo = true;
}
}
break;
case ButtonGrab.TouchpadPress:
if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Touchpad))
{
toggleModelIsLetgo = true;
}
if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Touchpad))
{
if (toggleModelIsLetgo)
{
Debug.Log("松手" + grabButton);
canLetgo = true;
}
}
break;
default:
break;
}
if (canLetgo)
{
LetGoTarget();
}
}
}
#endregion
#region//Target Parameter Record
/// <summary>
/// 被抓取物体刚体设置
/// </summary>
public TargetRigdbodyInspector m_targetRigdbodyInspector;
/// <summary>
/// 目标刚体设置
/// </summary>
public class TargetRigdbodyInspector
{
public bool useGravity;
public bool isKinematic;
public TargetRigdbodyInspector(bool gravity, bool kinematic)
{
useGravity = gravity;
isKinematic = kinematic;
}
}
#endregion
#region//System Default Settings
/// <summary>
/// 记录目标Transform
/// </summary>
private Transform targetTransform;
private CapsuleCollider myCollider;
private Rigidbody myRigidbody;
/// <summary>
/// 设置碰撞器
/// </summary>
private void SetMyCapsuleCollider()
{
myCollider = GetComponent<CapsuleCollider>();
myCollider.isTrigger = true;
myCollider.center = new Vector3(0, -0.03f, -0.06f);
myCollider.radius = 0.05f;
myCollider.direction = 2;
}
/// <summary>
/// 设置刚体
/// </summary>
private void SetMyRigidbody()
{
myRigidbody = GetComponent<Rigidbody>();
myRigidbody.isKinematic = true;
myRigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
}
/// <summary>
/// 设置位置
/// </summary>
private void ResetTransform()
{
transform.localPosition = Vector3.zero;
transform.localEulerAngles = Vector3.zero;
}
#endregion
}
public enum ButtonGrab
{
/// <summary>
/// 扳机
/// </summary>
TriggerPress,
/// <summary>
/// 侧边
/// </summary>
GripPress,
/// <summary>
/// 圆盘
/// </summary>
TouchpadPress
}
public enum GrabMode
{
/// <summary>
/// 持续按下拾取,抬起时松开
/// </summary>
HoldButton,
/// <summary>
/// 按下拾取,再按松开
/// </summary>
ToggleButton
}
添加后自动生成刚体和碰撞器,不用设置刚体和碰撞器的属性,代码中会赋值
GrabHand 使用哪只手拾取,就将他的Controller拖拽进来
这个脚本放在Editor文件夹下
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(PickUpObject))]
public class PickUpObjectSeting : Editor
{
private SerializedObject pickUpObject;//序列化
private SerializedProperty m_pickUpTag, m_letGoTag;
private SerializedProperty m_isCanPickUp;
/// <summary>
/// 设置拾取模式下的参数
/// </summary>
private SerializedProperty m_targetPointtype, m_targetPosition, m_targetrotation;
/// <summary>
/// 设置松手后是否恢复至原父物体下
/// </summary>
private SerializedProperty m_isRestoreParent, m_oldFather;
private void OnEnable()
{
pickUpObject = new SerializedObject(target);
m_isCanPickUp= pickUpObject.FindProperty("isCanPickUp");
m_pickUpTag= pickUpObject.FindProperty("pickUpSeting");
m_letGoTag = pickUpObject.FindProperty("letGoSeting");
m_targetPointtype = pickUpObject.FindProperty("garbTargetPoint");
m_targetPosition = pickUpObject.FindProperty("targetPosition");
m_targetrotation = pickUpObject.FindProperty("targetRotation");
m_isRestoreParent = pickUpObject.FindProperty("isRestoreParent");
m_oldFather = pickUpObject.FindProperty("oldFather");
}
public override void OnInspectorGUI()
{
pickUpObject.Update();
EditorGUILayout.PropertyField(m_isCanPickUp);
EditorGUILayout.PropertyField(m_pickUpTag);
EditorGUILayout.PropertyField(m_targetPointtype);
if (m_targetPointtype.enumValueIndex == 2)
{
EditorGUILayout.PropertyField(m_targetPosition);
EditorGUILayout.PropertyField(m_targetrotation);
}
EditorGUILayout.PropertyField(m_letGoTag);
EditorGUILayout.PropertyField(m_isRestoreParent);
if (m_isRestoreParent.boolValue)
{
EditorGUILayout.PropertyField(m_oldFather);
}
pickUpObject.ApplyModifiedProperties();
}
}