本案例取自邵伟老师所著《Unity VR虚拟现实完全自学教程》一书,场景如图所示:
其中,Box Collider碰撞盒被指定给狙击枪模型WPN_AKM,为Weapon游戏对象添加如下组件:
组件中的Rigidbody,VRTK_Interactable Object(Script),VRTK_Child Of Controller Grab Attach(Script),VRTK_Swap Controller Grab Action(Script),VRTK_Interact Haptics(Script)等,通过菜单命令Window/VRTK/Setup Interactable Object自动加载。持枪的吸附位置定位在空游戏对象Handle上,在组件VRTK_Child Of Controller Grab Attach(Script)中指定,如下图所示:
实现开火射击,是在组件VRTK_Interactable Object_Unity Events(Script)调用脚本组件Weapon中的Shoot方法,如下图所示:
组件VRTK_Interact Controller Appearance(Script)用在游戏运行时隐藏手柄,设置如下图:
VIVE手柄上加载的组件如下图所示,其中VRTK_Object Auto Grab(Script)实现在运行时让Weapon游戏对象替换手柄显示。
Weapon脚本源码如下,邵伟老师已经做了注释:
using UnityEngine;
public class Weapon : MonoBehaviour
{
// 子弹生成位置
public Transform firePoint;
// 枪口火焰特效例子特效
public ParticleSystem muzzleFlash;
// 子弹预制体
public GameObject bulletPrefab;
// 开枪声音
public AudioSource fireSound;
// 射击在金属上的特效
public GameObject metalHitEffect;
// 射击在地面上的特效
public GameObject stoneHitEffect;
// 开枪射击函数,供Use事件调用
public void Shoot()
{
RaycastHit hitInfo;
// 生成子弹实例
GameObject bulletColone = Instantiate(bulletPrefab);
// 设置子弹初始位置
bulletColone.transform.position = firePoint.position;
// 鉴于模型中心点坐标,在子弹生成后,设置其朝向符合显示子弹朝向
// 在实际游戏项目中,需要根据具体模型资源设置子弹朝向
bulletColone.transform.up = -firePoint.forward;
// 发送射线判断是否击中物体
if (Physics.Raycast(firePoint.position, firePoint.forward, out hitInfo))
{
// 分别根据击中碰撞体的Tag生成不同的击中效果
if (hitInfo.collider.tag == "Metal")
{
showHitEffect(metalHitEffect, hitInfo);
}
else if (hitInfo.collider.tag == "Stone")
{
showHitEffect(stoneHitEffect, hitInfo);
}
}
// 播放枪口火焰例子特效
muzzleFlash.Play();
// 播放开枪音效
fireSound.Play();
}
// 生成弹痕及击中效果
void showHitEffect(GameObject effectPrefab, RaycastHit hitInfo)
{
// 弹痕位置为射线击中点,方向为击中点的法线方向
GameObject hitEffectClone = Instantiate(effectPrefab, hitInfo.point, Quaternion.LookRotation(hitInfo.normal));
hitEffectClone.transform.SetParent(hitInfo.transform);
}
}