4

我刚刚开始使用 F# 使用 Unity3D,我注意到协同程序在书籍和教程中被大量使用,作为解决各种问题的巧妙解决方案。我一直在试图弄清楚 F# 是否具有等效的内置结构,或者是否至少可以以某种方式模仿它们,但我在 MSDN 上找不到任何东西。我只找到了几篇关于使用 Continuation monad 实现协程的文章,但作为初学者,这些都超出了我的想象。

这是 Unity 文档中的 C# 示例,当在游戏循环中重复调用时,会导致对象的 alpha 颜色随着时间的推移以小幅增量淡化:

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

}

所以我只需要声明一个返回 IEnumerator 的函数,然后通过“yield”将控制权交给我想要在主体内部的任何位置。我不确定如何在 F# 中执行此操作,因为我不断收到错误消息“此表达式应具有 IEnumerator 类型,但此处具有单元类型”。“yield”关键字在 F# 中的行为似乎也有所不同,因为与 C# 不同,它不能单独使用,并且必须在我从文档中理解的序列表达式中。

所以我错过了什么吗?上述功能如何在 F# 中实现?


更新

古斯塔沃的解释是正确的。这是您可以附加到对象以查看其红色值在 10 秒时间范围内减少 0.1 的确切 Unity 脚本。

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

这篇文章对解释 Unity 中协程的细节很有帮助。

4

1 回答 1

7

等效的 F# 代码如下:

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

请注意,与 C# 不同,您必须产生一些值,因此我们使用单位 ( ())。seq表达式将具有类型,seq<unit>它是 的别名IEnumerable<Unit>。为了使其符合 Unity 所期望的类型,我们只需使用:> IEnumerable

于 2013-11-06T11:27:43.107 回答