3

In Unity3D we are able to make a field accessible inside the editor by marking it as public. This then allows assigning the field's variable in the GUI instead of hard-coding it. This C# code for example will show a "speed" field that can be manually edited during development. It will default to 10 if left unmodified:

public class Example : MonoBehaviour {
    public float speed = 10.0F; 
}

I tried doing this in F# with automatic properties:

type Example() =
    inherit MonoBehaviour()
    member val speed = 10.f with get,set 

but this doesn't work. It does, however, work if I use explicit properties

[<DefaultValue>] val mutable speed : float32

but this has the drawback of not being able to specify a default value in the same expression.

Aren't explicit and automatic properties compiling down to the same thing, with the only difference being that explicit properties are always initialized to zero? And how can I declare the equivalent of the C# code in F#?

  • How does it fail? If you're not using F# 3.0, you don't get automatic properties. Otherwise is your problem that you're inheriting from MonoBehavior and are trying to override a field, which is forbidden? – plinth Nov 07 '13 at 19:46
  • By fails I mean that no field shows up in the Unity editor, although it is still accessible as a public field if I make an instance of the class. Whereas using an explicit property the field is both accessible through an instance and through the editor. No compile errors in either case. And the field "speed" is not overridden, it's one I made up. – user2959993 Nov 07 '13 at 19:56

3 Answers3

4

I think you're confusing two different concepts: explicit fields and auto-properties. Under the hood, a property is more like a method than a field, although access/assignment are syntactically similar. The F# equivalent of your C# would be:

type Example() as this =
  [<DefaultValue>] val mutable public speed: float32;
  do this.speed <- 10.0f
Daniel
  • 47,404
  • 11
  • 101
  • 179
4

I think you are playing a little loosely with the terms "field" and "property".

The Unity editor doesn't bind properties automatically, and the first example you've provided is F#'s auto-properties. For the record, you couldn't bind the following C# in Unity editor pane either:

// does not bind in editor either
class Example : MonoBehavior { 
    public float speed { get; set; }
}

You have to use the code with [DefaultValue] and just initalize it in the constructor or alternatively have a let-bound private field that is tagged [SerializeField] and write your own property wrapper:

type Example () = 
    [<SerializeField>]
    let mutable _speed = 10f
    member this.speed 
        with get () = _speed 
        and set val = _speed <- val
Community
  • 1
  • 1
Jimmy
  • 89,068
  • 17
  • 119
  • 137
  • ah I'm getting the concepts mixed up. Your solution works. Sound like it's time for me to reread the docs though :-) – user2959993 Nov 07 '13 at 20:16
  • I have a question: i'm also building a unity game using F#. How can you debug the Unity F# code in visual studio? Is there a way for UnityVS to work with F#? I have tried and I can't seem to find a way to make this happen... – Tyler Jones Mar 16 '14 at 20:23
1

Another way to implement this, which avoids the [<DefaultValue>] and imperative initialization, would be as follows (note the absence of default constructor on the first line):

type Example =
    val mutable public speed : float32
    new() = { speed = 10.0f }
Tarmil
  • 11,177
  • 30
  • 35
  • Great! That's even more concise, and I can put all my initializations in one place. You can even drop the "public" modifier since vals are public by default. – user2959993 Nov 11 '13 at 03:09