Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  4. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

As Unity is very .Net based could it adopt the F# and Visual Basic Languages?

Discussion in 'General Discussion' started by Arowx, Sep 16, 2018.

  1. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    6,462
    Unity is moving towards the latest .Net and C# versions with the adoption of the Roslyn compiler, therefore could Unity also adopt the F# and Visual Basic programming languages?

    F# could possibly be an ideal functional programming language for ECS data-driven programming with its concise syntax that reduced the syntactical bloat of C#. It also has functional programming features that could really make ECS programming easier and faster to write.

    Visual Basic, well BASIC it's a great starting point for any programmer and as Unity have dropped UnityScript and Boo it could allow beginner programmers to quickly get their game ideas up and running.

    In theory these, .Net family languages should be able to work with the Unity API and will be able to take advantage of the IL2CPP build pipeline.

    Would this add to the diversity of Unity programming or just create a brain drain at Unity as they would have to support three language versions?
     
  2. Murgilod

    Murgilod

    Joined:
    Nov 12, 2013
    Posts:
    3,619
  3. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    6,462
    Actually, if you look at F#'s Agent based system...

    https://fsharpforfunandprofit.com/posts/concurrency-actor-model/

    Code (CSharp):
    1. let printerAgent = MailboxProcessor.Start(fun inbox->
    2.  
    3.     // the message processing function
    4.     let rec messageLoop() = async{
    5.        
    6.         // read a message
    7.         let! msg = inbox.Receive()
    8.        
    9.         // process a message
    10.         printfn "message is: %s" msg
    11.  
    12.         // loop to top
    13.         return! messageLoop()
    14.         }
    15.  
    16.     // start the loop
    17.     messageLoop()
    18.     )
    F# you have a MailboxProcessor that responds to Messages.
    ECS you have a System that works on to DataComponents.

    Note F# agent tested and handled about 30 million messages in a second https://theburningmonk.com/2012/03/f-how-many-messages-can-you-post-to-a-f-agent-in-one-second/

    Could F#'s agent-based system be used to build ECS systems in Unity, only with a fraction of the boilerplate code needed?
     
    Deeeds likes this.
  4. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    22,994
    Yes and C# can do it the same. Just because you see a lot of setup now, doesn't mean it will stay that way. Monobehaviour, anyone?
     
    Ryiah likes this.
  5. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    12,177
    Below is the answer from Unity and the link to the blog article. I have trimmed the fat of the article (primarily the examples which you don't need to understand the point) and added text (in brackets) to clarify.

    https://blogs.unity3d.com/2017/08/11/unityscripts-long-ride-off-into-the-sunset/
     
    hippocoder likes this.
  6. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
    The problem with C# is that you are not forced to think in terms of functional programming and novice programmers could use the language wrong.

    It was the same thing with VB6 and older before .NET, you could use OO programming but was not forced to it.
     
  7. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    22,994
    Yeah I'm just saying you don't need a F# to make C# look like it needs less code. If ECS is very regimental for what is and is not allowed, then it's ideal for syntax sugar actually.
     
    AndersMalmgren likes this.
  8. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
    Time will tell, I forsee many funny questions and posted code in the scripting forum :)
     
  9. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    3,130
    I haven't worked with F# so I can't say exactly, but performance is a major problem with most functional code.

    Although I know F# is a hybrid (not pure functional language), I'd imagine it's still difficult to write anything close to high performance code in it.
     
    hippocoder likes this.
  10. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
    What? Functional languages is used when performance is of the outmost importance, more so when scaling out parallel
     
  11. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    3,130
    Local caching and S*** is usually harder to do with functional languages. Something like ECS might be kinda neutral performance wise, but a lot of "state" is often caching related.
     
  12. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    22,994
    Citation?
     
  13. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
  14. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    3,130
    If you are doing something like scaling out across huge amounts of systems - different kinds of performance concerns plop in. Immutability for example is a performance cost at the local scale, but it makes it easier to scale out parallel.

    I doubt you could actually beat well written C# with F# for high performance code, but it's possible that you may find it easier to go parallel w/ something more functional.
     
  15. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
    Funny thing is ECS by default copies things out, or so I read on unity sub Reddit, haven't investigated further

    Edit: hmm maybe it was hybrid, don't remember
     
  16. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    3,415
    Do we still thrust carmack or I'm not uptodate? He said that about functional and performance.
     
  17. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    22,994
    That doesn't make it higher performance at all. It merely means it can be executed in parallel.

    There's nothing in C++ that prevents you cooking up functional programming btw, so it can be tested there with robust compilers but it requires that you also think about the bottlenecks and where they come from. Your entire chain should be designed with functional in mind.

    With Unity and ECS, you have something that can go from classic to hybrid to full ECS without changing the language you know, only the techniques you use to solve problems.

    I would use functional programming in Unity, and learn a new syntax for it, if it had proven benefits that trumped the current approach. Currently I don't see the proven benefits yet. Someone is welcome to convince me though.
     
  18. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    3,130
    In @AndersMalmgren's defense here - "performance" isn't just one thing, like if you're digging into details performance can mean very different things in different context.

    Like, is making a process slower so it's easier to scale it up to parallel a performance increase or decrease?

    Well, it depends kinda on the scale you're looking at. Is google search a high performance system? I think we'd all agree yes, but that kind of performance has zero similarity to 'high performance' in most game development.

    Neither is wrong, you're just talking apples and oranges.
     
    angrypenguin likes this.
  19. FirstTimeCreator

    FirstTimeCreator

    Joined:
    Sep 28, 2016
    Posts:
    629

    I can hardly see a scenario where this would make much difference in a "video game".

    In a high volume webserver sure, but this unity, a game engine. The overhead gain you are talking is minute at best.
     
  20. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    6,462
    As compiler technology from C/C++/C#/Java/.Net and Burst shows it's not the language that is performant it is how the language is compiled to assembly and machine code where performance really happens.

    You could take the least performant scripting abstract language and as long as you have the best native compiler technology chain there is it will be as fast as the fastest language you can compare it to.

    My point is this is not about language performance, it's about programmer performance...

    If the language has a good clean grammar that makes solving the problem at hand easy then that is a 'performant' language and API.

    If however, the language has complex and verbose syntax and messy grammar that makes solving the problem at hand more complex and confusing then that is an 'inefficient' language and API.
     
    neoshaman likes this.
  21. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    3,415
  22. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    3,415
    I support this argument.
    Arowx for president!
     
    Deeeds likes this.
  23. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    3,130
    This is an eternal debate.

    Control vs simplicity.

    High level vs low level.

    Some people like having control and do well with it. More options can mean fewer inefficiencies. Other people prefer having fewer options so they make fewer mistakes. Performance in games is one of the few domains where actual low level performance optimization matters, so you have more people who prefer control than in most software development.
     
  24. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    6,010
    A new language would have to absolutely blow my mind, give me significantly more control and be significantly easier to use than C# in order for me to entertain the idea of adopting it in Unity.
     
  25. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    22,994
  26. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    3,130
    I was really into functional style about ten years ago. It's not a bad approach.

    I'm with @hippocoder though, I really don't see the advantage of functional languages. General purpose with function pointers/first class functions seems to be the winning blend.
     
  27. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    3,130
    I really like this old article.

    http://stevelosh.com/blog/2013/03/list-out-of-lambda/

    He goes over the process of building a purely functional list. Can you build a list without state, using only closures and curry? Yep.

    Absolutely interesting. Kinda mind bending. Makes you feel extremely smart. Totally impractical.
     
    Last edited: Sep 16, 2018
  28. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    1,426
    I agree.

    I would like to see some app examples, where comparing performance C# and F# or whatever other language.
    What most important, and has been pointed out before in other topic (I think also by @hippocoder), with current system, we go official M$ support.

    From ECS point of view, switching language may be worth consideration, if there is prove for significant performance improvement.
    Otherwise, we know for most cases, many don't bother about micro optimization when not needed. And more important than which language is used, is how app code is written. If is none performant written, then which used language is, it don't matter.
     
  29. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
    It's not so much about performance as it is it makes sure you program in a way that works well with paralism. LINQ is a functional language built ontop of C# so you can write immutable and paralell perfomant code in C#, you are just not forced todo it like you are in a pure functional language.

    Edit: also there is a big difference in writing concurrent code and paralell code. Concurent code is much easier to write using locks, semaphores etc
     
  30. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    22,994
    Anyone using LINQ in game development is simply wasting performance. You are aware of the boxing performed behind the scenes?
     
  31. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
    It was just an example of functional programming inside C#.

    Yepp, I know it boxes, it boxes on .NET CLR/compiler too, its even worse on Mono especially Mono 2 (Unity 2017).

    We use it only when performance is not relevant, like when loading a scene or a user action we know can not happen often

    edit: GC problems are alot larger if you target mobile though

    edit2: We use it for stuff like this, things that have no performance impact but simplifies the code alot

    Code (CSharp):
    1.         public void QuickStore(InteractableMagazine magazine)
    2.         {
    3.             var sameOrEmpty = ammoPouches
    4.                 .OrderBy(pouch => pouch.Empty ? 1 : 0)
    5.                 .First(pouch => pouch.Empty || pouch.TopMostItem.Type == magazine.Type);
    6.  
    7.             sameOrEmpty.Store(magazine);
    8.         }
     
    Last edited: Sep 16, 2018
  32. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    1,697
    C# makes it pretty easy to code in a practical functional style. By practical I mean something like you need immutability for a specific reason. Custom value types are really what makes C# an acceptable functional language in a lot of cases. It might not be quite as elegant, but it has the tools you need to get the job done.

    In the context of Unity nobody needs a functional language. And I don't think there is any way you could ever make a good argument for supporting one given the costs involved.
     
    VergilUa, Ryiah and Antypodish like this.
  33. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    15,536
    You could. Technically speaking Unity will work with anything compiled to IL.

    Should you is another question. I see zero reason to use F# in Unity.
     
    VergilUa and Ryiah like this.
  34. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    3,130
    I donno, I wrote a bunch of custom linq versions I use in non critical code.

    Code (csharp):
    1.  
    2.     [System.Diagnostics.DebuggerHidden]
    3.     [System.Diagnostics.DebuggerStepThrough]
    4.     public static PooledList< T > GetWhere< T >( this IList< T > items, Predicate< T > predicate){
    5.       var list = ListPool.Get< T >();
    6.       for( int i = 0 ; i < items.Count ; i++ ){
    7.         var item = items[i];
    8.         if( predicate( item ) )
    9.           list.Add( item );
    10.       }
    11.       return list;
    12.     }
    13.  
    14.     [System.Diagnostics.DebuggerHidden]
    15.     [System.Diagnostics.DebuggerStepThrough]
    16.     public static PooledList<T1> GetMap< T, T1 >( this IList< T > list, Func< T, T1 > converter ){
    17.       var map = ListPool.Get< T1 >();
    18.      
    19.         for( int i = 0 ; i < list.Count ; i++ ) {
    20.             map.Add( converter(list[i]));
    21.         }
    22.         return map;
    23.     }
    24.     [System.Diagnostics.DebuggerHidden]
    25.     [System.Diagnostics.DebuggerStepThrough]
    26.     public static PooledList<T1> GetMap< T, T1 >( this IList< T > list, Func< int, T, T1 > converter ){
    27.       var map = ListPool.Get< T1 >();
    28.         for( int i = 0 ; i < list.Count ; i++ ) {
    29.             map.Add(  converter( i, list[ i ] )  );
    30.         }
    31.         return map;
    32.     }
    33.     [System.Diagnostics.DebuggerHidden]
    34.     [System.Diagnostics.DebuggerStepThrough]
    35.     [CanBeNull]
    36.     public static T1 TryGetFirstOfType< T1, T>(this IList<T> list) where T1 : class, T {
    37.         for (int index = 0; index < list.Count; index++) {
    38.             var i = list[index];
    39.             T1 as_target = i as T1;
    40.             if (as_target != null ) return as_target;
    41.         }
    42.         return default(T1);
    43.     }
    44.  
    Couple little extras - like pooling the lists that get returned to avoid addl allocation, etc. Work's pretty well. You can get reasonably fast performance if you avoid closures in loop.

    I got like a hundred more extension functions I use pretty regularly.
     
    Ryiah likes this.
  35. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    3,415
    Not F# in particular but functional, look at that last part...
     
  36. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    22,994
    He's not saying it's good there. He's saying it's theoretically good. It never ended up becoming good for game development nor faster than ECS is today in the 6 years that have elapsed since then.

    If it was, you can be sure some noise would have been made about it. The silence is telling.
     
  37. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    1,697
    Functional programming has some good ideas that ran headlong into a wall of practical reasons why it doesn't work as well in practice. Performance is just one reason. Another is it just takes a lot of mental effort to get used to things like tail recursion. It's not like just learning another OOP language, it takes a significant amount of time to learn to think in idiomatic functional flows coming from an OOP background. So hiring and training developers to the point where they are actually as productive in a functional language as an OOP one, is a considerable investment.

    The best data we have on how well functional has worked is probably scala. A lot of companies adopted it, and recently a lot are dumping it. Some just saying outright it was a mistake. I do have some friends that still think scala is the best. I know one that works at Amazon and I know they still use it to some extent at least. But you can find basically every language being used at Amazon.
     
    Deeeds, Kiwasi, frosted and 2 others like this.
  38. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
    In none critical code you can even use vanilla Linq, we do it all the time. For example user actions that are local host only. They can only happen 1 time in a reasonable time span
     
  39. FirstTimeCreator

    FirstTimeCreator

    Joined:
    Sep 28, 2016
    Posts:
    629
    That seems pretty bad unless you are running it once lol. Say hello to the garbage collector for me.
     
    VergilUa likes this.
  40. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    22,994
    These LINQ examples still allocate so you will want to do a GC.Collect at some point so that it doesn't hitch mid-gameplay.

    I can well understand the uses there for some people (although I'm not seeing the code shrink because these use cases were adopted). Seems the equivalent C# isn't more work...
     
  41. FirstTimeCreator

    FirstTimeCreator

    Joined:
    Sep 28, 2016
    Posts:
    629
    I am working on a project where I am running 500 RB's that have an AI system I designed. One thing Ive learned is less isn't necessarily better or faster and more isn't either.

    The key to speed in most cases is memory allocation / access which means using the stack/heap correctly as well as not setting types at run-time like using int or especially "var" inside code that executes each frame. These things create garbage and the more you do it the more garbage you will create in your overall project so just don't do it.

    If you want speed use the stack, use structs.

    int somevar = this; <- don't do this in an update loop. = Garbage
    SomeList.Count <- don't do this either esp in update (count your arrays manually when you construct them)

    Of course using structs properly for proper stack/heap use is more work for the programmer than just doing it the lazy way.
     
  42. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
    My example without Linq would be
    Code (CSharp):
    1. public void QuickStore(InteractableMagazine magazine)
    2. {
    3.    AmmoPuch sameOrEmpty = null;
    4.    foreach(var pouch in ammoPouchs)
    5.    {
    6.       if(!pouch.Empty && pouch.TopMostItem.Type == magazine.Type)
    7.       {
    8.          sameOrEmpty = pouch;
    9.          break;
    10.       }
    11.  
    12.       if(pouch.Empty)
    13.           sameOrEmpty = pouch;    
    14.    }
    15.  
    16.    sameOrEmpty.Store(magazine);
    17. }
    While not a complete distaster, still alot harder to read
     
  43. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    12,177
    To be honest they're about the same for me. A single glance was all it took to understand the purpose of the function.
     
    VergilUa likes this.
  44. FirstTimeCreator

    FirstTimeCreator

    Joined:
    Sep 28, 2016
    Posts:
    629
    foreach is slower than for();

    Why use var? esp in a Foreach?

    If you want speed don't use var or foreach.
     
  45. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
    Haha, dude var does nothing for performance, the compiler will replace it with the actual type. Maybe you have mixed the keyword dynamic with var?

    Foreach isn't slower than for. It did allocate in earlier versions of mono though
     
    VergilUa likes this.
  46. FirstTimeCreator

    FirstTimeCreator

    Joined:
    Sep 28, 2016
    Posts:
    629
    https://www.dotnetperls.com/for-foreach

    In the "case" above it is faster. Unless this website incorrect which is where i get my info.

    as far as var, it's just ugly. This isn't javascript it's c#. Anyway my opinion.
     
  47. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
    The biggest difference is calling the Length property in your example, if we cache the length in a local variable they perform very similar

    upload_2018-9-17_15-13-20.png

    var isnt ugly, it removes noise. Javascript is a dynamic language. C# is static, var doesn't change that.
     
  48. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    2,855
    Actually if we build foreach wins

    upload_2018-9-17_15-23-15.png
     
  49. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    12,177
    @AndersMalmgren: Both benchmarks are using .NET though. What's the performance under Mono? I don't know if there would be any differences but it has been known to implement things differently.
     
  50. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    22,994
    Both will need length properties cached.