【问题标题】:Trying to use Coroutine to activate and deactivate objects in the scene in VR developmentVR开发中尝试使用Coroutine激活和去激活场景中的物体
【发布时间】:2018-08-15 23:39:23
【问题描述】:

我正在设计一款 VR 游戏,并尝试制作一个附加到左侧控制器的菜单。我有两个按钮,一个用于激活场景中的一些对象,另一个用于将玩家带到不同的场景。

我一直在查看 SteamVR 交互式示例,并试图模仿他们在示例场景中使用的按钮。除了在示例中,他们使用协程在控制器上启动不同的提示,因此他们使用 Hand 类。我只是想用它来激活和停用对象以及更多到不同的场景。

为了说明清楚,这些是我想要实现的目标:

  1. 当用户点击第一个按钮时,激活通过 Unity 中的 Inspector 选项卡指定的对象 (obj1)。
  2. 当用户点击第二个按钮时,停用对象 (obj1) 并移动到不同的场景。

这是示例场景中的 C# 代码。它有三个按钮,它们可以激活“按钮提示”或“文本提示”:

//======= Copyright (c) Valve Corporation, All rights reserved. ===============
//
// Purpose: Demonstrates the use of the controller hint system
//
//=============================================================================

using UnityEngine;
using System.Collections;
using Valve.VR;

namespace Valve.VR.InteractionSystem
{
    //-------------------------------------------------------------------------
    public class ControllerHintsExample : MonoBehaviour
    {
        private Coroutine buttonHintCoroutine;
        private Coroutine textHintCoroutine;

        //-------------------------------------------------
        public void ShowButtonHints( Hand hand )
        {
            if ( buttonHintCoroutine != null )
            {
                StopCoroutine( buttonHintCoroutine );
            }
            buttonHintCoroutine = StartCoroutine( TestButtonHints( hand ) );
        }


        //-------------------------------------------------
        public void ShowTextHints( Hand hand )
        {
            if ( textHintCoroutine != null )
            {
                StopCoroutine( textHintCoroutine );
            }
            textHintCoroutine = StartCoroutine( TestTextHints( hand ) );
        }


        //-------------------------------------------------
        public void DisableHints()
        {
            if ( buttonHintCoroutine != null )
            {
                StopCoroutine( buttonHintCoroutine );
                buttonHintCoroutine = null;
            }

            if ( textHintCoroutine != null )
            {
                StopCoroutine( textHintCoroutine );
                textHintCoroutine = null;
            }

            foreach ( Hand hand in Player.instance.hands )
            {
                ControllerButtonHints.HideAllButtonHints( hand );
                ControllerButtonHints.HideAllTextHints( hand );
            }
        }


        //-------------------------------------------------
        // Cycles through all the button hints on the controller
        //-------------------------------------------------
        private IEnumerator TestButtonHints( Hand hand )
        {
            ControllerButtonHints.HideAllButtonHints( hand );

            while ( true )
            {
                ControllerButtonHints.ShowButtonHint( hand, EVRButtonId.k_EButton_ApplicationMenu );
                yield return new WaitForSeconds( 1.0f );
                ControllerButtonHints.ShowButtonHint( hand, EVRButtonId.k_EButton_System );
                yield return new WaitForSeconds( 1.0f );
                ControllerButtonHints.ShowButtonHint( hand, EVRButtonId.k_EButton_Grip );
                yield return new WaitForSeconds( 1.0f );
                ControllerButtonHints.ShowButtonHint( hand, EVRButtonId.k_EButton_SteamVR_Trigger );
                yield return new WaitForSeconds( 1.0f );
                ControllerButtonHints.ShowButtonHint( hand, EVRButtonId.k_EButton_SteamVR_Touchpad );
                yield return new WaitForSeconds( 1.0f );

                ControllerButtonHints.HideAllButtonHints( hand );
                yield return new WaitForSeconds( 1.0f );
            }
        }


        //-------------------------------------------------
        // Cycles through all the text hints on the controller
        //-------------------------------------------------
        private IEnumerator TestTextHints( Hand hand )
        {
            ControllerButtonHints.HideAllTextHints( hand );

            while ( true )
            {
                ControllerButtonHints.ShowTextHint( hand, EVRButtonId.k_EButton_ApplicationMenu, "Application" );
                yield return new WaitForSeconds( 3.0f );
                ControllerButtonHints.ShowTextHint( hand, EVRButtonId.k_EButton_System, "System" );
                yield return new WaitForSeconds( 3.0f );
                ControllerButtonHints.ShowTextHint( hand, EVRButtonId.k_EButton_Grip, "Grip" );
                yield return new WaitForSeconds( 3.0f );
                ControllerButtonHints.ShowTextHint( hand, EVRButtonId.k_EButton_SteamVR_Trigger, "Trigger" );
                yield return new WaitForSeconds( 3.0f );
                ControllerButtonHints.ShowTextHint( hand, EVRButtonId.k_EButton_SteamVR_Touchpad, "Touchpad" );
                yield return new WaitForSeconds( 3.0f );

                ControllerButtonHints.HideAllTextHints( hand );
                yield return new WaitForSeconds( 3.0f );
            }
        }
    }
}

这就是我所拥有的示例代码的类似副本。我一直在搞清楚对象激活,还没有接触到场景变化:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using Valve.VR;

namespace Valve.VR.InteractionSystem
{
    //................................................
    public class HandMenueActions : MonoBehaviour
    {
        public GameObject AllProducts;

        private Coroutine allProductsCoroutine;
        private Coroutine aboutUsCoroutine;

        //............................................
        public void ShowAllProducts(GameObject AllProducts)
        {
            if (allProductsCoroutine != null)
            {
                StopCoroutine(allProductsCoroutine);
            }
            allProductsCoroutine = StartCoroutine(TestAllProducts);
        }


        //............................................
        //Turns on all products in the scene
        //............................................
        private IEnumerable TestAllProducts()
        {
            AllProducts.SetActive(true);
        }
    }

我没有那么有经验,我尝试编写代码以实现统一,并在旁边打开文档,但我仍然在这里。

【问题讨论】:

    标签: c# unity3d virtual-reality coroutine


    【解决方案1】:

    我不知道你为什么要使用协程而不是简单的方法..

    说实话我不知道具体Valve.VR.InteractionSystem

    但我只会做一些简单的方法,比如:

    public GameObject obj1;
    
    private void Update()
    {
        if(Input.GetButton("Button1") // or however you access your button 1
        {
            obj1.SetActive(true);
        } else if (Input.GetButton("Button2") // or however you access your button2
        {
            obj1.SetActive(false);
        }
    }
    

    我在那里使用 else ,所以同时只执行一个按钮。


    在快速搜索中,我现在还找到了Unity manual for SteamVr controler input

    他们有一个使用事件处理程序/回调的完整示例。这是一个简短的,应该满足您的需要(他们也很好地解释了它是如何工作的)

    using UnityEngine; 
    
    public class ObjectEnabler : MonoBehaviour
    {   
        private SteamVR_TrackedController _controller;  
    
        public GameObject obj1;
    
        private void OnEnable() 
        {       
            // Get the controller this component is attached to
            _controller = GetComponent<SteamVR_TrackedController>();    
    
            // Register callbacks to your buttons
            // I've left this on the ones from the example .. if you need others 
            // You have to look them up
            // In the example there is also a complete list of all button events
            RegisterCallbacks();
        }   
    
        private void OnDisable()    
        {       
            UnregisterCallbacks();
        }
    
        // Register callbacks for controler events
        private void RegisterCallbacks()
        {
            // It is always save to remove callbacks 
            // So just to be sure we only register once so methods are not executed twice
            // I personaly always first unregister callbacks:
            UnregisterCallbacks();
    
            // now I register the callback that means e.g.
            // Everytime the event TriggerClicked is 
            // invoked anywhere in the Scene I want to execute HandleTrickerClicked
            // hint the method can be called as you like .. could also simply be EnableObject e.g.
            _controller.TriggerClicked += HandleTriggerClicked;     
            _controller.PadClicked += HandlePadClicked; 
            // For more information how the callbacks work
            // see the link I provided
        }
    
        // Unregister callbacks for events
        private void UnregisterCallbacks()
        {
            _controller.TriggerClicked -= HandleTriggerClicked;     
            _controller.PadClicked -= HandlePadClicked; 
        }
    
        // Called on TriggerClicked
        // Enables the obj1
        private void HandleTriggerClicked() 
        {
            obj1.SetActive(true);
        }   
    
        // Called on PadClicked
        // Disables the obj1
        private void HandlePadClicked()
        {
            obj1.SetActive(false);
        } 
    }
    

    您现在只需将此脚本附加到控制器(在 SteamVR_TrackedController 组件旁边),它应该会执行您想要的操作。

    (我现在不确定,因为我从未使用过它,而且我在移动设备上,但他们的脚本最终可能会错过一些 using 命名空间,例如从整个 using Valve.VR; 内容开始,但我不知道如何就是这样实现的)

    【讨论】:

    • 所以我对使用什么没有偏好。我尝试编写与您的类似的自己的东西,但我在将其连接到控制器或代码运行时遇到问题。但我认为,在我更仔细地查看您共享的 Unity 代码后,我应该能够弄清楚。非常感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多