当前位置: 首页 > 知识库问答 >
问题:

投射光线时滑块未填充

潘修为
2023-03-14

该脚本引用了slider(滑块)gameobject(游戏对象),并具有一个协同例程(Coroutine),当我们通过按a键将光线投射到画布上时,该脚本将填充滑块。我的代码工作正常,但它不能正确填充滑块。它可以在光线投射时立即改变场景。我想要的是第一个滑块是fill,音频是play,而滑块值等于0。而不是场景更改。我想我在协同程序中做错了什么。

代码:
RayCast脚本:

public class RayCast : MonoBehaviour
{
    private RaycastHit hit;

    [SerializeField]
    private AudioSource source;

    [SerializeField]
    private AudioClip clip;

    //Refrence of Slider Canvas Script
    [SerializeField]
    private SliderSelect sliderCanvasScript;

    private void Update()
    {
        Debug.DrawRay(transform.position, transform.forward, Color.cyan);

        if (Input.GetKeyDown(KeyCode.A) && SliderSelect.check)
        {
            if (Physics.Raycast(transform.position, transform.forward, out hit, 9f))
            {
                if (hit.collider.gameObject.name == "SliderCanvas")
                {
                    Debug.Log("Ray cast to the slider");
                    StartCoroutine(sliderCanvasScript.FillUp());
                    source.PlayOneShot(clip);
                    SceneManager.LoadScene("Scene0", LoadSceneMode.Single);
                }
            }
        }
    }
}

滑块选择脚本:

public class SliderSelect : MonoBehaviour
{
    [SerializeField]
    private Slider mSlider;

    public static bool check;
    private void Start()
    {
        mSlider.minValue = 0;
        mSlider.maxValue = 100;
        mSlider.wholeNumbers = true;
        mSlider.value = 0;
        check = true;
    }

    public IEnumerator FillUp()
    {
        int i = 0;

        while (i <= 100)
        {
            mSlider.value += 2;
            i += 2;
            yield return null;
        }
        mSlider.value = 0 ;
    }
}

共有1个答案

慕云
2023-03-14

我的代码工作正常,但它不能正确填充滑块。当光线投射时,它会立即更改场景。我想要的是第一个滑块被填充,音频被播放,而不是滑块值等于0。比场景更改。我想我在协程中做错了什么

那是因为你在打电话

StartCoroutine(sliderCanvasScript.FillUp());
source.PlayOneShot(clip);
SceneManager.LoadScene("Scene0", LoadSceneMode.Single);

in fromUpdate函数,它实际上不等待FillUp()协程函数完成。

从Update函数启动一个新的协同例程函数,然后在该协同例程函数中执行这三行代码。然后可以替换startcroutine(sliderCanvasScript.FillUp()) 使用返回startcroutine(sliderCanvasScript.FillUp()) 将在调用源代码之前等待它完成。PlayOneShot(剪辑) 后接场景管理器。LoadScene(“场景0”,LoadSceneMode.Single)

此外,要等待音频结束播放,请不要使用静态播放快照功能。

首先,将剪辑分配给AudioSourcesource.clip=剪辑;。现在播放source。播放();。接下来,等待Audio完成播放,同时(source.is播放){返回null;}。就是这样。

该函数应该是这样的:

IEnumerator doInOrder()
{
    //Wait for Fill to finish
    yield return StartCoroutine(sliderCanvasScript.FillUp());
    //Assign Audio Clip
    source.clip = clip;
    //Then Play Sound
    source.Play();

    //Wait for Audio to finish Playing
    while (source.isPlaying)
    {
        yield return null;
    }
    //Load new Scene
    SceneManager.LoadScene("Scene0", LoadSceneMode.Single);
}

这就是整个代码的样子:

public class RayCast : MonoBehaviour
{
    private RaycastHit hit;

    [SerializeField]
    private AudioSource source;

    [SerializeField]
    private AudioClip clip;

    //Refrence of Slider Canvas Script
    [SerializeField]
    private SliderSelect sliderCanvasScript;



    private void Update()
    {
        Debug.DrawRay(transform.position, transform.forward, Color.cyan);
        if (Input.GetKeyDown(KeyCode.A) && SliderSelect.check)
        {
            if (Physics.Raycast(transform.position, transform.forward, out hit, 9f))
            {
                if (hit.collider.gameObject.name == "SliderCanvas")
                {
                    Debug.Log("Ray cast to the slider");
                    StartCoroutine(doInOrder());
                }
            }
        }
    }

    IEnumerator doInOrder()
    {
        //Wait for Fill to finish
        yield return StartCoroutine(sliderCanvasScript.FillUp());
        //Then Play Sound
        source.clip = clip;
        //Then Play Sound
        source.Play();

        //Wait for Audio to finish Playing
        while (source.isPlaying)
        {
            yield return null;
        }
        //Load new Scene
        SceneManager.LoadScene("Scene0", LoadSceneMode.Single);
    }
}

不要把对撞机放在画布UI组件上

碰撞器应仅用于精灵/精灵渲染器(2D对象)和网格渲染器(2D对象)。它不应该放在画布UI组件上。

即使这对您有效,您也应该使用指针单击来检测滑块上的单击,然后使用值更改事件来检测滑块值的更改。检测这两件事的脚本必须附加到游戏对象上。然后,您可以实现2个事件,当单击或滑块上的值更改时,您可以注册并接收回调。

将下面的脚本附加到您的滑块:

public class SliderDetector : MonoBehaviour, IPointerClickHandler
{
    public Slider slider;

    public delegate void sliderClicked();
    public static event sliderClicked OnClicked;

    public delegate void valueChanged(float value);
    public static event valueChanged onValueChanged;

    // Use this for initialization
    void Awake()
    {
        slider = GetComponent<Slider>();
        //Subscribe To Slider Event
        slider.onValueChanged.AddListener(delegate { sliderCallBack(slider.value); });
    }


    public void OnPointerClick(PointerEventData eventData)
    {
        if (OnClicked != null)
        {
            //Notify All Subscribed function
            OnClicked();
        }
    }

    void sliderCallBack(float value)
    {
        if (onValueChanged != null)
        {
            //Notify All Subscribed function
            onValueChanged(value);
        }
    }

    void OnDisable()
    {
        //Un-Subscribe To Slider Event
        slider.onValueChanged.RemoveListener(delegate { sliderCallBack(slider.value); });
    }
}

然后,要从Raycast脚本中使用它,请添加以下内容:

void OnEnable()
{
    //Subscribe to the Slider Click event
    SliderDetector.OnClicked += OnSliderClicked;
    //Subscribe to the Slider Value Changed event
    SliderDetector.onValueChanged += OnSliderValueChanged;
}

//Will be called when there is a click on that slider
private void OnSliderClicked()
{
    //Slider Clicked Start your coroutine function
    StartCoroutine(doInOrder());
}

//Will be called when the slider value changes
private void OnSliderValueChanged(float value)
{
    //Slider Value Changed, Do Something
}

void OnDisable()
{
    //Un-Subscribe to the Slider Click event
    SliderDetector.OnClicked -= OnSliderClicked;
    //Un-Subscribe to the Slider Value Changed event
    SliderDetector.onValueChanged -= OnSliderValueChanged;
}
 类似资料:
  • 这个类用于进行raycasting(光线投射)。 光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体)。 代码示例 const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); function onMouseMove( event ) { // 将鼠标位置归一化为设备坐标。x 和 y 方向的

  • 概述 该直线运动闭式滑动单元内径为8mm,适用于精密直线运动应用,如印刷机和计算机数控(CNC)设备。 设计用于承载部件的滑动单元具有带有平坦安装面和四个螺纹孔的壳体,每个端部具有圆形夹子以保持球轴套。 球笼在笼环中运行平滑的导轨表面,以确保即使高速运行,噪音低。 参数 内径:8mm 长度:34.06mm 宽度:30mm 高度:22mm

  • 激光发射模块能够发射指向性极其高的光束,配合光线传感器能检测是否有物体经过。可用它实现有趣的案例创意。 净重量:10.8g 体积:24×24×27mm 参数 激光发射功率:1mW 电池容量:85mAh 续航:≥10小时 充电时间:≈100分钟 抗跌落能力:1.5m 工作温度:-10℃~55℃ 工作湿度:<95% 特点 可充电 超长续航 定制化激光模组,不易伤眼"

  • 我们目前使用的光照都来自于空间中的一个点。它能给我们不错的效果,但现实世界中,我们有很多种类的光照,每种的表现都不同。将光投射(Cast)到物体的光源叫做投光物(Light Caster)。在这一节中,我们将会讨论几种不同类型的投光物。学会模拟不同种类的光源是又一个能够进一步丰富场景的工具。 我们首先将会讨论定向光(Directional Light),接下来是点光源(Point Light),它

  • 问题内容: 我的代码如下 “ try”块中的分配会导致警告说明 为什么是这样? 问题答案: 好吧,首先让我们弄清楚问题出在哪里-它在演员表中。这是一个简短的示例: 这仍然有同样的问题。问题在于强制类型转换实际上不会测试任何东西- 因为强制类型转换将有效地转换为原始类型。因为这有点让人惊讶,因为实际上对象 确实 知道所涉及的类,但是考虑类似的情况: 该类型转换将不会检查它是否 确实 是a ,因为该信

  • 本文向大家介绍Swift投射,包括了Swift投射的使用技巧和注意事项,需要的朋友参考一下 示例 将函数应用于集合/流并创建新的集合/流称为投影。