You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity VRTK VR武器切换技术咨询:实现双武器直接切换替代拾取

补全VR武器切换脚本(VRTK)

嘿,你已经搭好了不错的基础框架!我来帮你补全武器切换的逻辑,让玩家能通过握把按键在两把武器间无缝切换,不用到处跑动拾取。

完整代码实现

using UnityEngine;
using VRTK;

public class WeaponSwitcher : MonoBehaviour
{
    public VRTK_ObjectAutoGrab autoGrab;
    public VRTK_ControllerEvents controllerEvents;
    public VRTK_InteractableObject[] weapons;
    public int selectedWeapon = 0;

    void Start()
    {
        // 自动绑定控制器事件,避免空引用报错
        if (controllerEvents == null)
        {
            controllerEvents = GetComponent<VRTK_ControllerEvents>();
        }
        // 初始化激活默认武器
        SelectWeapon();
    }

    void Update()
    {
        int previousSelectedWeapon = selectedWeapon;

        // 检测握把按键点击,触发武器切换
        if (controllerEvents.gripClicked)
        {
            // 循环切换逻辑:到最后一把后回到第一把
            selectedWeapon = (selectedWeapon + 1) % weapons.Length;
        }

        // 仅当选中武器变化时执行切换操作
        if (previousSelectedWeapon != selectedWeapon)
        {
            SelectWeapon();
        }
    }

    void SelectWeapon()
    {
        // 遍历所有武器,只激活当前选中的那一把
        for (int i = 0; i < weapons.Length; i++)
        {
            weapons[i].gameObject.SetActive(i == selectedWeapon);
        }

        // 绑定自动抓取,让玩家切换后立刻握持武器
        if (autoGrab != null && weapons.Length > 0)
        {
            autoGrab.interactableObject = weapons[selectedWeapon];
            autoGrab.AttemptGrab();
        }
    }
}

关键逻辑说明

  • 初始化容错:在Start()里加了空引用检查,就算你忘了在Inspector拖入controllerEvents,脚本也会自动尝试获取组件,减少报错概率。
  • 循环切换:用取模运算(selectedWeapon + 1) % weapons.Length实现循环切换,以后你想加更多武器,这段代码不用改就能直接适配。
  • 武器状态管理SelectWeapon()会自动隐藏未选中的武器,避免场景里同时出现多把武器造成混乱。
  • 即时握持:切换后自动把autoGrab的目标设为当前武器,调用AttemptGrab()让玩家不用手动去抓,切换体验更流畅。

优化小建议

如果觉得每帧检测按键有点浪费性能,可以改成事件驱动的方式,只在按键点击时触发切换,更符合VR开发的最佳实践:

void Start()
{
    // 自动绑定控制器事件
    if (controllerEvents == null)
    {
        controllerEvents = GetComponent<VRTK_ControllerEvents>();
    }
    // 绑定握把点击事件
    controllerEvents.GripClicked += OnGripClicked;
    SelectWeapon();
}

void OnGripClicked(object sender, ControllerInteractionEventArgs e)
{
    selectedWeapon = (selectedWeapon + 1) % weapons.Length;
    SelectWeapon();
}

void OnDestroy()
{
    // 移除事件监听,防止内存泄漏
    controllerEvents.GripClicked -= OnGripClicked;
}

内容的提问来源于stack exchange,提问作者Danny

火山引擎 最新活动