I'm just getting started with Unity3D using F# and I'm noticing that coroutines are used heavily in books and tutorials as a neat solution for solving a variety of problems. I've been trying to figure out whether or not F# has the equivalent built-in constructs, or if it's at least possible to somehow mimic them, but I can't find anything on MSDN. I only found a few articles with implementations of coroutines using a Continuation monad, but these are way over my head as a beginner.
Here's the C# example from the Unity docs, which when called repeatedly inside the game loop results in fading the object's alpha color in small increments over time:
IEnumerator Fade() {
for (float f = 1f; f >= 0; f -= 0.1f) {
Color c = renderer.material.color;
c.a = f;
renderer.material.color = c;
yield return;
}
}
So I simply have to declare a function that returns an IEnumerator, then cede control wherever I want to inside the body with a "yield." I'm not sure how to do this in F# as I keep getting the error "This expression was expected to have type IEnumerator but here has type unit". The "yield" keyword also seems to behave differently in F# since unlike C# it cannot be used on its own and has to be inside a sequence expression as I understood from the docs.
So am I missing anything? How would the functionality above be implemented in F#?
Gustavo's explanation is correct. Here is the exact Unity script which you can attach to an object to see it's Red color value decrease by 0.1 over a 10 second time frame.
namespace CoroutinesExample
open UnityEngine
type CoroutinesExample() =
inherit MonoBehaviour()
member this.Start() =
// Either of the these two calls will work
// this.StartCoroutine("Fade") |> ignore
this.Fade()
member this.Fade() =
seq {
for f in 1.f .. -0.1f .. 0.f do
let mutable c = this.renderer.material.color
c.r <- f
this.renderer.material.color <- c
yield WaitForSeconds(1.f)
} :?> IEnumerator
This article was very helpful in explaining the details of coroutines in Unity.
The equivalent F# code is the following:
member this.Fade() =
seq {
for f in 1.0 .. -0.1 .. 0.0 do
let c = renderer.material.color
c.alpha <- f
renderer.material.color <- c
yield ()
} :> IEnumerable
Note that unlike in C#, you have to yield some value, so we're using unit (()
). The seq
expression will have the type seq<unit>
, which is an alias for IEnumerable<Unit>
. To make it conform to the type Unity is expecting, we just need to upcast it by using :> IEnumerable
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With