Search Unity

  1. The 2022.1 beta is now available for testing. To find out what's new, have a look at our 2022.1 beta blog post.
    Dismiss Notice

Functional programming in ECS ?

Discussion in 'Data Oriented Technology Stack' started by Silenus3, Dec 5, 2019.

  1. Silenus3

    Silenus3

    Joined:
    Jun 5, 2019
    Posts:
    20
    is it possible to use functional C# to write ECS systems ?
     
    Last edited: Dec 6, 2019
  2. pahe4retro

    pahe4retro

    Joined:
    Aug 13, 2019
    Posts:
    33
    If you mean if it's possible to write functional code in C#, the answer is: Yes. Functional programming is a programming paradigm which can be used and applied with several programming languages.

    If you mean if it's possible to use F#, I'm not sure about that, but I doubt it. Just try it out and you'll see if Unity wants to compile your code.
     
    Silenus3 likes this.
  3. dthurn

    dthurn

    Joined:
    Feb 17, 2015
    Posts:
    62
    no -- ECS is fundamentally imperative. The entire paradigm is based on writing systems which modify mutable structs.
     
  4. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    171
    Though the mutation of data in systems is imperative, organizing your data together and querying it is very much declarative. I would say DOD in general is more declarative then it is imperative since the flow of the application is more so determined by your data (declarative) then it is by your code (imperative). And keep in mind that one of the key concepts that makes the Job System so safe and efficient is the ability to "declare" whether ECS data is read only or not.

    To an extend, yes. Unity used a few FP concepts in their implementation of ECS. Such as the use of lambda functions with Entities.ForEach, and also enforcing no side effects when writing burst enabled jobs. Even the use of
    PostUpdateCommands is functional to an extend as it allows you to write systems that produce an array of commands instead of mutating data directly. So just using Unity's ECS as is will have you follow quite a few FP concepts.
     
  5. Silenus3

    Silenus3

    Joined:
    Jun 5, 2019
    Posts:
    20

    how would the concept of Delegates work within ECS ?

    a sequence of systems working in some particular order ?
    how can I change this order dynamically ?
     
  6. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    171
    What exact problem are you trying to solve with the use of delegates within ECS? Or are you more so asking from a place curiosity in how delegates can be utilized within ECS? Also, are you asking whether delegates can be used as a way to declare how systems are ordered?
     
  7. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    9,293
    As @Vacummus said, we need to know, what you try to solve. I got impression, you may be still thinking in OOP when talking about ECS. That requires mind switch, to DOD, which for some may take time.
     
  8. Silenus3

    Silenus3

    Joined:
    Jun 5, 2019
    Posts:
    20
    I'm just wondering what parts of C# are relevant for writing systems ?
    its not clear as of yet , also i'm curious about functional programming with ECS.

    like functions that return functions - which are available in C# to facilitate multi-paradigm programming(as those functions can be stored in variables) rather then just plane OOP.
     
  9. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    9,293
    Check out first page of this thread.
    You may find some answers
    https://forum.unity.com/threads/f-scripting-in-unity.624484/

    Probably most.

    Use classes and structs for that.
    Same result.
     
  10. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    171
    Yeah, this curiosity is great! You might be aware of this, but just to set some context: DOD and FP are on two opposite ends of the same spectrum, where DOD is more about solving problems with smart data layouts and dumb code (systems that unaware of each other), while FP is more about solving problems with dumb data and smart code (functions as first class citizens). Both keep data and behavior separate from each (unlike OOP which couples the two). Which is better is a pointless discussion in my opinion since I see each paradigm more so as a tool to be used to solve a specific problem it's best suited for, hence the point of multi-paradigm programming.

    So one use case where I use FP within ECS is to solve some problems I have had with limitations of Unity's Query API.
    For example, here I am making use of a delegate to declare a base query that can use to branch off multiple sub queries:

    Code (CSharp):
    1. public class DialoguePlayerAddedSystem : ComponentSystem
    2. {
    3.     protected override void OnUpdate()
    4.     {
    5.         Func<EntityQueryBuilder> baseQuery = () => Entities.WithAllReadOnly<DialoguePlayerAdded>();
    6.  
    7.         baseQuery().ForEach((ref Dialogue dialogue, TextMesh textMesh) => {
    8.             textMesh.text = Localization.GetLocalizedString(dialogue.id);
    9.         });
    10.  
    11.         baseQuery().ForEach((ref DialoguePosition position, TextMesh textMesh) => {
    12.             textMesh.transform.position = new Vector3(position.value.x, position.value.y);
    13.         });
    14.  
    15.         baseQuery().ForEach((Entity entity, ref SetFollowTarget followTarget, TextMesh textMesh) => {
    16.            PostUpdateCommands.AddComponentData(entity, new FollowTarget{ target = followTarget.target });
    17.         });
    18.  
    19.         baseQuery().ForEach((Entity entity) => {
    20.             PostUpdateCommands.RemoveComponent<DialoguePlayerAdded>(entity);
    21.         });
    22.     }
    23. }
    I also disagree with Unity's conversion workflow process for building scenes and tend to instead prefer building my game world via code by using a mix of OOP and FP practices. Here is an example:

    Code (CSharp):
    1.  
    2. var player = Build.Character("Player", Sprites.Player)
    3.     .SetSpriteColor(new Color(0.46f, 0.49f, 0.8f))
    4.     .AddComponent<PlayerInput>()
    5.     .AddComponent(new SideScrollingMovement { speed = 500, gravity = 50 })
    6.     .AddComponent(new SideScrollingJump { force = 25, jumpTimeMax = 0.1f });
    7.  
    8. Build.Camera().FollowTarget(player);
    9.  
    10. Build.Environment("Sketch", Sprites.SketchEnv)
    11.     .AddCollider(Points2D.SketchEnv)
    12.     .SetLocalScale(3,3);
    13.  
     
unityunity