投射光线时滑块不会填充

时间:2016-11-29 19:21:51

标签: c# unity3d

我正在处理conda.exe install mysql-connector-python 并遇到问题。在场景中有一个unity3d,其子对象为Main Camera,该画布还有一个子对象,它是一个图像。Main Camera我附加了脚本worldspace canvas为了旋转相机,相机按MouseLook键投射光线。同样在场景中,A有一个WorldSpace canvas组件和一个子对象box collider,并且画布附有脚本SliderSlider

该脚本引用了滑块SliderSelect并且有一个gameobject,当我们通过按Coroutine键将光线通过相机投射到画布时填充滑块。我的代码工作正常,但它没有正确填充滑块。当光线投射时,它会立即改变场景。我想要的是第一个滑块是填充和音频播放比滑块值等于0.然后场景改变。我想我在A做错了。

代码:
RayCast脚本:

Coroutine

滑块选择脚本:

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);
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:2)

  

我的代码工作正常,但它没有正确填充滑块。它' S   投射光线时立即改变场景。我想要的是第一个   滑块是填充,音频播放比滑块值等于0.Than   场景变化。我认为我在Coroutine中做错了什么

那是因为你正在打电话

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

来自Update函数,该函数实际上并没有等待FillUp()协程函数完成。

从Update函数启动一个新的coroutine函数,然后在该coroutine函数中执行这三行代码。然后,您可以将StartCoroutine(sliderCanvasScript.FillUp());替换为yield return StartCoroutine(sliderCanvasScript.FillUp());,等待它完成后再调用source.PlayOneShot(clip);,然后再调用SceneManager.LoadScene("Scene0", LoadSceneMode.Single);

另外,要等待音频完成播放,请不要使用静态PlayOneShot功能。

首先,使用source.clip = clip;将剪辑指定给AudioSource。现在玩source.Play();。接下来,等待Audio完成while (source.isPlaying){ yield return 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);
    }
}

不要将Collider放在Canvas UI组件上

Colliders只能用于Sprites / SpriteRenderer(2D对象)和MeshRenderer(2D对象)。它永远不应该放在Canvas UI组件上。

即使这对你有用,你应该检测到点击带有OnPointerClick的滑块,然后使用onValueChanged事件检测滑块值的变化。检测这两件事的脚本必须附加到Slider GameObject。然后,您可以实施2个可以注册的事件,并在Slider点击或Slider值更改时接收回调。

将以下脚本附加到滑块:

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;
}