武器脚本
通常在游戏中可以使用多种武器,那么每类武器就应该有自己独立的脚本,每个实际的武器又应该有其单独的脚本实例。比如,我有一部分武器是单发的枪,那我就应该有一个单发枪的脚本 SingleGunControl ,这个脚本可以指定一些枪支的基本参数(单发伤害,子弹初速度,子弹类型,射速,换弹速度等),在生成不同的单发枪支时给这些参数赋值。
开火事件注册
在定义好 SingleGunControl 脚本后,我们需要给手柄控制器提供开火事件响应器。代码如下:
/// <summary>
/// 单发枪的控制脚本
/// </summary>
public class SingleGunControl : MonoBehaviour
{
private VRTK_ControllerEvents controller;
// 当物体被激活,提供开火事件响应器
private void OnEnable()
{
controller = GetComponentInParent<VRTK_ControllerEvents>();
if (controller == null)
{
this.enabled = false;
return;
}
controller.TriggerPressed += OnTriggerPressed;
}
// 当物体被禁用,注销开火事件响应器
private void OnDisable()
{
if (controller == null)
{
return;
}
controller.TriggerPressed -= OnTriggerPressed;
}
private void OnTriggerPressed(object sender, ControllerInteractionEventArgs e)
{
// 开火事件响应内容
// ...
Debug.LogFormat("{0} -- {1}", sender, e.touchpadAngle);
}
}
此脚本应该挂在枪支对象上,当枪支刚生成时,处于还没有被抓取的状态,我们先将此脚本禁用。既然有禁用,那就应该有启用,这时候就需要另外一个脚本 GrabWeapon,专门用来处理武器抓取事件,在此处可以使用此脚本来改变武器控制脚本的状态。当前枪支的控制脚本为 SingleGunControl ,针对不同的枪支类型,会有不同的控制脚本,但用于转换武器控制脚本状态的 GrabWeapon 则可以重复使用。
/// <summary>
/// 抓取武器的脚本
/// </summary>
public class GrabWeapon : MonoBehaviour
{
private void Start()
{
// 注册抓取事件
GetComponent<VRTK_InteractableObject>().InteractableObjectGrabbed += OnWeaponGrabbed;
}
/// <summary>
/// 抓取事件处理器
/// </summary>
/// <param name="sender">事件触发对象</param>
/// <param name="e">事件变量对象</param>
private void OnWeaponGrabbed(object sender, InteractableObjectEventArgs e)
{
// 由于当前帧无法获取SingleGunControl脚本,所以使用协程在后续时间启用武器控制脚本
StartCoroutine(SetWeaponControlState(sender));
}
/// <summary>
/// 改变武器控制器的状态
/// </summary>
/// <param name="sender">事件触发对象</param>
/// <returns>协程迭代器</returns>
private IEnumerator SetWeaponControlState(object sender)
{
yield return null; // 等待一帧,或者也可以yield return WaitForEndOfFrame();等待当前帧结束
GetComponent<SingleGunControl>().enabled = true;
Debug.LogFormat("{0} 已启用", sender);
}
}
当物体被抓取时,VRTK 会先调用 InteractableObjectGrabbed 事件响应器,然后再将武器挂载到手柄控制器节点下面,这就导致了当 InteractableObjectGrabbed 事件触发时, SingleGunControl 脚本的 OnEnable 方法仍然无法在其父节点上找到手柄控制器,所以 SingleGunControl 中控制器的 TriggerPressed 事件依然无法完成注册,所以这时候使用协程来延迟一帧,等到物体被挂到手柄控制器节点下以后再进行事件注册。
另外,如果要GrabWeapon能够自适应武器类型,可以将 GetComponent().enabled = true; 中的SingleGunControl改为泛型,并限制该泛型必须继承自WeaponControl类。
更多内容请查看总目录【Unity】Unity学习笔记目录整理