0
votes

So I have a script that when you click a button a movie plays. I have an IEnumerator to see if the movie is over and when it is close it. My code worked fine until I added the IEnumerator and now I can't call the playMovie function.

Image of why I can't call playMovie

Any ideas on why this might be happening? This is what the code looks like:

public void playMovie(Action callback)
    {
        GetComponent<RawImage>().texture = myMovie as MovieTexture;
    audio = GetComponent<AudioSource> ();
        audio.clip = myMovie.audioClip;
        myMovie.Play ();
        audio.Play ();  

        StartCoroutine (FindEnd (callback));
    }


private IEnumerator FindEnd(Action callback)
    {
        while (myMovie.isPlaying) 
        {
            yield return 0;
        }
        callback ();
        yield break;

    }
3
Does the StartCoroutine method actually enumerate the IEnumerator? (i. e. does it use foreach on it?) - Chris Dunaway
"and now I can't call the playMovie function": Why not? What happens when you try? - phoog
@ChrisDunaway In Unity3d you need to think of IEnumerables as how we use async/await today (Unity's stuff came first). Think of StartCoroutine (FindEnd (callback)); as a Task.Factory.StartNew(() => FindEnd(callback), TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()).Unwrap(); and the yield return 0; as a await Task.Yield(); - Scott Chamberlain
@Amanda When you say "I can't call the playMovie function" please explain more what you mean. Are you getting a compiler error? Does the movie just not start? Please include the code where you call playMovie. - Scott Chamberlain

3 Answers

2
votes

The Unity event system doesn't show your method because it takes an Action as an argument. You'll have to make a zero-argument overload for the method.

public void playMovie() 
{
    playMovie(()=>{})
}

public void playMovie(Action callback)
{
    GetComponent<RawImage>().texture = myMovie as MovieTexture;
    audio = GetComponent<AudioSource> ();
    audio.clip = myMovie.audioClip;
    myMovie.Play ();
    audio.Play ();  

    StartCoroutine (FindEnd (callback));
}
1
votes

Any ideas on why this might be happening?

There are restrictions when assigning Unity UI event to a function. These are some of the restrictions I remember:

1.The callback function should only have one parameter.

2.The callback function must be a void function.

3.The callback function parameter type must inherit from Object.

Since Action is a delegate, it does not meet #3 requirement and is not supported in the Editor.

You can remove all the restrictions by performing the Button callback from script instead of the Editor. You can do that by registering to the Button.onClick event.

public Button playButton;

public void playMovie(Action callback)
{
    GetComponent<RawImage>().texture = myMovie as MovieTexture;
    audio = GetComponent<AudioSource>();
    audio.clip = myMovie.audioClip;
    myMovie.Play();
    audio.Play();

    StartCoroutine(FindEnd(callback));
}


private IEnumerator FindEnd(Action callback)
{
    while (myMovie.isPlaying)
    {
        yield return 0;
    }

    callback();
    yield break;
}

void movieDonePlayingCallBack()
{

}

void OnEnable()
{
    //Register Button Event
    playButton.onClick.AddListener(() => buttonClickCallBack(playButton));

}

private void buttonClickCallBack(Button buttonPressed)
{
    if (buttonPressed == playButton)
    {
        //Your code for when Play Button is clicked
        playMovie(movieDonePlayingCallBack);
    }
}

void OnDisable()
{
    //Un-Register Button Event
    playButton.onClick.RemoveAllListeners();
}
0
votes

you cannot reference a method with Action parameter from event system in the unity editor.