简单交互场景:
传送点,桌子,小球,提示Canvas与文字
SampleInteractable.png
Interactable 脚本:
可以交互得物体上要添加得脚本组件,用于手柄与之交互。
Interactable.png
可设置的属性:
- Activeate Action Set On Attach : 在附着物体时激活的事件集
- Hide Hand On Attach : 在附着物体时,隐藏整个手,包括手柄与手的模型,分离时显示
- Hide Skeleton On Attach :在附着物体时,只隐藏手模型,不包括手柄,分离时显示
- Hide Controller On Attach : 在附着物体时,只隐藏手柄,不包括手模型,分离时显示
- Hand Animation On Pickup : 在捡东西时,播放的手的动画
- Set Range Of Motion On Pickup : 在捡起东西时,在骨骼上设置运动变化
- Use Hand Object Attachment Point : 指定使用手的附着物体的位置点,还是直接使用手的位置作为挂载点
- Hand Follow Transform : 想要手附着在某物上,并跟随其移动,指定该位置
- Hand Follow Transform Position : 手跟随物体的位置移动
- Hand Follow Transform Rotation : 手跟随物体的旋转进行旋转
- Highlight On Hover : 可交互物体,在被手悬停触碰时,是否 外发光 高亮显示
- Hide Highlight : 一些子物体,不高亮显示,例如:透明物体,VFX特效等
可访问的属性或方法:
- attached To Hand : 获取该交互物体附着的手(返回 Hand)
- isDestroying : 只读,获取该交互物体是否销毁中(返回 bool)
- isHovering :只读,获取该交互物体是否被手悬停触碰状态中(返回 bool)
- wasHovering : 只读,获取该交互物体是否被手悬停触碰(返回bool)
Sample Interactable 脚本:
1、该脚本是自定义脚本,可以在内部处理相关交互事件
2、内部这些方法的调用,都是Hand 脚步通过 SendMessage()方式来调用,因此内部的方法名必须与Hand中的名称一致,并且都有Hand类型参数传递,不要求都(声明)有接受者。
例如Hand脚本中:
Hand.png
在可交互的,附着的物体上可以处理的消息有:
- OnHandHoverBegin( Hand hand ) : -----当手开始悬停在可交互物体上,被调用一次
- OnHandHoverEnd( Hand hand ) : -----当手结束悬停在可交互物体上,被调用一次
- HandHoverUpdate( Hand hand ) : -----当手一直悬停在可交互物体上,被每帧调用
- OnAttachedToHand( Hand hand ) : -----当可交互物体刚被手抓取附着时,被调用一次
- OnDetachedFromHand( Hand hand ) : -----当可交互物体刚被手释放分离时,被调用一次
- HandAttachedUpdate( Hand hand ) : -----当可交互物体刚被手一直抓取附着时,被每帧调用
- OnHandFocusAcquired( Hand hand ): -----当附加的GameObject成为主要附加对象时调用调用一次(就是说附加了很多物体到附加物栈中,到该物体成为栈顶时,调用一次)
- OnHandFocusLost( Hand hand ) : ----当这个主要附加GameObject不再是栈顶对象时调用一次
SampleInteractable:
using UnityEngine;
using Valve.VR.InteractionSystem;
/// <summary>
/// 简单的交互
/// </summary>
public class SampleInteractable : MonoBehaviour {
private TextMesh textMesh;//显示文字,输出状态
private Vector3 oldPosition; //记录原来的位置,在分离时回到原来的位置。
private Quaternion oldRotation;//记录原来的旋转,在分离时回到原来的旋转角度
private float attachTime; //被抓取附着的时间
//附着的类型标志
private Hand.AttachmentFlags attachmentFlags = Hand.defaultAttachmentFlags & (~Hand.AttachmentFlags.SnapOnAttach) & (~Hand.AttachmentFlags.DetachOthers) & (~Hand.AttachmentFlags.VelocityMovement);
//可交互对象
private Interactable interactable;
//-------------------------------------------------
void Awake()
{
textMesh = GetComponentInChildren<TextMesh>();
textMesh.text = "无手柄悬停!";
interactable = this.GetComponent<Interactable>();
}
//-------------------------------------------------
// 当手开始悬停在可交互物体上,被调用一次
//-------------------------------------------------
private void OnHandHoverBegin(Hand hand)
{
textMesh.text = "正在悬停的手柄: " + hand.name;
}
//-------------------------------------------------
// 当手结束悬停在可交互物体上,被调用一次
//-------------------------------------------------
private void OnHandHoverEnd(Hand hand)
{
textMesh.text = "无手柄悬停!";
}
//-------------------------------------------------
// 当手一直悬停在可交互物体上,被每帧调用
//-------------------------------------------------
private void HandHoverUpdate(Hand hand)
{
GrabTypes startingGrabType = hand.GetGrabStarting(); //获取手柄进行抓取的方式
bool isGrabEnding = hand.IsGrabEnding(this.gameObject); //获取手柄是否结束抓取
if (interactable.attachedToHand == null && startingGrabType != GrabTypes.None)
{
// 保存位置/旋转,当分离时,以便可以恢复它。
oldPosition = transform.position;
oldRotation = transform.rotation;
//锁定该交互物,避免再悬停到其他物体上,保证一次悬停锁定一个可交互的物体
hand.HoverLock(interactable);
// 附加该物体到手上
hand.AttachObject(gameObject, startingGrabType, attachmentFlags);
}
else if (isGrabEnding)
{
// 从手上分离该物体
hand.DetachObject(gameObject);
// 解除对该物体的悬停锁定
hand.HoverUnlock(interactable);
// 恢复分离的物体到原来的位置
transform.position = oldPosition;
transform.rotation = oldRotation;
}
}
//-------------------------------------------------
// 当可交互物体刚被手抓取附着时,被调用一次
//-------------------------------------------------
private void OnAttachedToHand(Hand hand)
{
textMesh.text = "球体附着在:" + hand.name;
attachTime = Time.time;
}
//-------------------------------------------------
// 当可交互物体刚被手释放分离时,被调用一次
//-------------------------------------------------
private void OnDetachedFromHand(Hand hand)
{
textMesh.text = "球体从 " + hand.name+" 分离!";
}
//-------------------------------------------------
//当可交互物体刚被手一直抓取附着时,被每帧调用
//-------------------------------------------------
private void HandAttachedUpdate(Hand hand)
{
textMesh.text = "球体附着在:" + hand.name + "\n附着时间: " + (Time.time - attachTime).ToString("F2");
}
//-------------------------------------------------
// 当附加的GameObject成为主要附加对象时调用调用一次(就是说附加了很多物体到附加物栈中,到该物体成为栈顶时,调用一次)
//-------------------------------------------------
private void OnHandFocusAcquired(Hand hand)
{
}
//-------------------------------------------------
// 当这个主要附加GameObject不再是栈顶对象时调用一次
//-------------------------------------------------
private void OnHandFocusLost(Hand hand)
{
}
}
注:记住引入命名空间:using Valve.VR.InteractionSystem; 否则无法使用相关的类。