hamel123 hamel123 - 3 days ago 5
C# Question

Slider not fill when ray is cast

I'm working on

unity3d
and facing a problem. In scene there is a
Main Camera
, which has a child object as
worldspace canvas
, and that canvas also has a child object which is a image.Main Camera I attached the script
MouseLook
for rotating the camera, camera cast a ray by pressing
A
key. Also in the scene there is a
WorldSpace canvas
which has a
box collider
component and a child object
Slider
, and canvas attached with the script
SliderSelect
.Slider

That script taking a reference of slider
gameobject
and has a
Coroutine
which fills the slider when we cast a ray through the camera to the canvas by pressing
A
key. My code is working fine but it doesn't fill the slider correctly. It's change the scene immediately when ray is cast. What i want is first slider is fill and audio is play than slider value equal to 0.Than scene change. I think i'm doing something wrong in
Coroutine
.

Code:

RayCast Script:

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


Slider Select Script:

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

Answer

My code is working fine but it doesn't fill the slider correctly. It's change the scene immediately when ray is cast. What i want is first slider is fill and audio is play than slider value equal to 0.Than scene change. I think i'm doing something wrong in Coroutine

That's because you are calling

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

in from the Update function which really doesn't wait for the FillUp() coroutine function to finish.

Start a new coroutine function from the Update function then execute those three lines of code in that coroutine function. You can then replace StartCoroutine(sliderCanvasScript.FillUp()); with yield return StartCoroutine(sliderCanvasScript.FillUp()); which will wait for it to finish before calling source.PlayOneShot(clip); followed by SceneManager.LoadScene("Scene0", LoadSceneMode.Single);.

Also, to wait for audio to finish playing, don't use the static PlayOneShot function.

First, assign the clip to the AudioSource with source.clip = clip;. Now play with source.Play();. Next, wait for Audio to finish playing with while (source.isPlaying){ yield return null;}. That's it.

This is what that function should look like:

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

This is what the whole code should look like:

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