【用Unity开发Oculus Quest用的APP】用Hand tracking功能抓住物体
◆ 写在开头
上一回、写了关于Oculus Quest 中Hand tracking功能的使用的内容。
所以这次的内容上,关于如何使用Hand tracking实现抓住物体的方法。
关于手的动作、手指状态的取得等,这里就不详细写了。
具体方法等,请自行查询。
如果制作中用什么问题或不明点,
有需要的话可以参考下面两条内容。
用Unity开发Oculus Quest用的APP 导入APP、进行运行状态确认
抓住物体吧(物体的设置与制作)
Hand tracking功能的使用
关于这次的内容,抓住物体的实行方法
完全属于自己想当然的做法,参考性比较低……请谅解。
◆ 开发环境
macOS Mojave 版本 10.14.6
Unity 2018.4.12f1
Android SDK
为了能够使用Hand tracking的功能,
Oculus的版本必须得是(Ver12)或以上。(需要更新的请即时更新)
◆ 制作顺序
- 准备阶段的说明
- 实现【抓住】功能
- 手指动作的判断
- 理论关系和代码
- 动作确认
准备阶段的说明
首先准备必要的Object,
在这里我们意见实装了Hand tracking功能、准备好了自带物理的几个测试用方块。
方块的尺寸颜色等请自由设置(方便看清就行)。
为了更直观的显示代码部分是否有正确实行等、
这里制作了观测用Canvas,当然这个只是起到了方便看的作用并不是必须要制作的东西,
只是单纯的有了会更直观而已。
当然桌子也不是必须品。
实现【抓住】功能
以前在抓住物体吧(物体的设置与制作)中,只要成功的在画面中表示手,便可以直接实行抓取,
但Hand tracking好像没有办法直接抓取的样子。
所以,
这次要做的事情就是,
当手触碰到物体且作出了抓住物体的动作时,把被触碰物体放入手的Object中,
也就是说,成为手的子级。
当然,除了成为子级以外,
当发生抓住判定时,被抓物体跟随手一起移动也是实现的方法之一。
手指动作的判断
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ovrHand : MonoBehaviour
{
private OVRHand _ovrHand;
// 抓住状态的取得
public bool _catching;
// Start is called before the first frame update
void Start()
{
_catching = false;
_ovrHand = this.gameObject.GetComponent<OVRHand>();
}
// Update is called once per frame
void Update()
{
if (_ovrHand.GetFingerIsPinching(OVRHand.HandFinger.Index))
{
_catching = true;
}
else
{
_catching = false;
}
}
}
将上述内容直接拖入「OVRHandPrefab」中。
关于手动作的取得、变数「_ catching」的制作与「_ catching」的说明,之后再说。
GetFingerIsPinching可以判断手指尖是否接触
OVRHand.HandFinger可以判断某手指是否与大拇指接触,这次接触手指的设置是食指。
当食指尖与大拇指触碰时,「_catching」变为true。
将「_catching」的状态在Canvas上表示
(和上面讲到的一样Canvas并不是必需品,下面的内容里讲省略全部关于Canvas的内容)
理论关系和代码
private ovrHand _ovrHand;
private bool _touchIN; //触碰
private bool _catch; //抓住动作
private bool _hold; //是否能抓住
// Start is called before the first frame update
void Start()
{
_ovrHand = FindObjectOfType<ovrHand>();
}
void Update()
{
// 取得手的动作 判断是否抓住
_catch = _ovrHand._catching;
touchCube();
CatchCube();
}
void touchCube()
{
if (_touchIN == true && _catch == false)
{
_hold = true;
}
}
void CatchCube()
{
if (_hold == true && _catch == true)
{
_touchIN = false;
}
else if (_touchIN = false && _touchIN == false)
{
_hold = false;
}
}
首先,需要分析关于抓住物体这一动作。
当手是抓住动作状态的时候触碰物体,是不能抓住物体的。
而在手触碰物体后,实行抓住动作便可抓住物体。
将上述内容用代码表示。
void OnCollisionStay(Collision other)
{
if (other.gameObject.name == "Hand_Index3_CapsuleRigidBody" ||
other.gameObject.name == "Hand_Index2_CapsuleRigidBody" ||
other.gameObject.name == "Hand_Thumb3_CapsuleRigidBody" ||
other.gameObject.name == "Hand_Thumb2_CapsuleRigidBody"
)
{
_touchIN = true;
// 固定位置且消除物理す
gameObject.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
gameObject.GetComponent<Rigidbody>().isKinematic = true;
}
}
参考上述内容,
想要实行抓住动作,首先需要从触碰物体开始。
关于手指各个部位的名字请参考最上面的连接。
发生触碰时,「 _touchIN」的状态变为true。
void CatchCube()
{
if (_hold == true && _catch == true)
{
// 变为右手子级
gameObject.transform.SetParent(_rightHandAnchor.gameObject.transform);
// 消除重力与触碰判定
gameObject.GetComponent<Rigidbody>().useGravity = false;
gameObject.GetComponent<BoxCollider>().isTrigger = true;
_touchIN = false;
}
else if (_touchIN = false && _touchIN == false)
{
// 解除父级关系
gameObject.transform.parent = null;
// 恢复重力 触碰
gameObject.GetComponent<Rigidbody>().useGravity = true;
gameObject.GetComponent<BoxCollider>().isTrigger = false;
// 恢复位置移动与物理
gameObject.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.None;
gameObject.GetComponent<Rigidbody>().isKinematic = false;
_hold = false;
}
}
这次准备的方块中因为加入了物理效果,所以当发生抓住判定时,需要将其去掉。
(没放入物理的情况下就没有写的必要了)
请根据自己的状况判断后,将必要的内容写入「CatchCube()」中。
(代码的意思,在上面有写请参考)
最后,把「cubeTouch.cs」拖入到方块中,完成必要的设置就算完成了。
动作确认
最后导入Oculus,确认是否能够正常运行吧。
Author And Source
この問題について(【用Unity开发Oculus Quest用的APP】用Hand tracking功能抓住物体), 我々は、より多くの情報をここで見つけました https://qiita.com/Kujirai_sakananosuke/items/fd027181ea7a196149cf著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .