How do we interact with DOTS systems from monobehaviours, Unity does not explain anything

I cannot find information anywhere on this and am getting conflicting answers when asking around on discord servers.

I am trying to setup the ability to interact with my waypoint graph when a user clicks an edge i want it to split the edge that is clicked into 2 edges and create a node at the position they clicked. Buti t also first needs to check the clicked point overlaps an edge.

It’s not clear what the best practice is to handle this. I get the mouse click from regular monobehaviours using the regular input stuff and raycasting to a plane etc.

The things i’ve been told so far is a monobehaviour should never have a reference to a system so i shouldn’t directly call a public function in a system that does the logic and checks.

So this leaves two options:

Option 1:

The monobehaviour itself should have the logic that creates the two new edge entities and the new node and connects them via an entity command buffer and then play that back by passing in the entitymanager reference, since its a one time operation based on user clicks. But not sure how would i would do the initial check that the mouse is over an edge.

Option 2:

In the monobehaviour similar to option one, create an entity with a custom component like “SplitCommand” which contains the split point.

Create a system that looks for entities with “SplitCommand” and then that system has the logic for splitting and creating the new edges/nodes in an OnUpdate which would run on the next frame. But this still doesn’t help with first checking if the point overlaps an edge by creating such an entity split command. (And i am not even sure if its good practice for monobehaviours to ever create entities).

I’ve been told by different people that both these options are not the correct way to do it…yet no one offering up the actual correct way to do it.

Both of these have issues.

Option 1 means the logic is outside of a system and in a monobehaviour, but option 2 means theres no way to return a true/false if the split was not possible due to no overlaps, so theres no way to inform the user it was not possible. If i do pre-checks that it overlaps an edge i would need a system to do that test but the click is generated in a monobehaviour so how do i do such a test in the click script, the whole this is confusing as heck.

There is absolutely zero explanation by Unity in their docs, all their examples are pretty rudimentary on how we are suppose bridge mono land to ECS land in these situations? What are the best practices for this?

I’m not even sure there is a “correct” way.

One way is to get the World (easier when you have only one), access the EntityManager and just work with that.

What I personally prefer is to move most of the logic to a system, and pretty much only use MonoBehaviours to store data. This is more in line with how the rest of the game is written, and lets you insert the system at a specific point in the game loop, as opposed to MonoBehaviours which run whenever they like. (The challenge really only becomes how to find the GameObjects/MonoBehaviours you need. Use your favorite hack. Me, I’m not above a public static readonly HashSet<SomeMonoBehaviour> Instances…)

That’s a third way, I guess. I’m not a huge fan of spawning entities from mono, but it’s fine for passing simple “fire and froget” commands over to the ECS side.

Maybe MouseClickInputCommand instead? To me it usually feels like moving logic over to the ECS side often disentangles the mess. Maybe read the input and do the raycast in a managed system? YMMV

Thanks for the reply.

The other thing i was wondering if how to involve scriptable objects? I have scriptable objects which holds data about certain stuff.

If i need that data in an entity i need the system when creating an entity to get the data from the scriptable object. I am a bit confused how you link them since they don’t have inspectors like traditional monobehaviours where you can just reference to the scriptable object then grab what you need.

A lot of those conflicting answers comes from the fact that there are various ways to use ECS and the best practices for each approach are often very different. This particular matter happens to be one of those that is drastically affected by such. I wrote up an article on these various approaches at a high level, and perhaps it may help you to identify which approach your project most aligns with. The various ways to use Unity ECS: A Starter Guide

However…

What is stopping you from doing this in a system instead? There are plenty of examples of using both InputManager and Input System in ECS.

1 Like

I didn’t know where to find the examples the entities documentation does not really have much to go on with script examples beyond very basic stuff. Infact none of the documentation even talks about scriptable objects, input system or using any monobehaviour hybrid stuff unless this isn’t the place to actually really understand how to use DOTS in an already established project mostly in monobehaviours: https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/whats-new.html ?

Since i am procedurally generating meshes at runtime for my edges currently using gameobjects, its getting slow as there so many…(the template mesh however is stored in a scriptable object) and unity meshes are classes i don’t see how i’m supposed to be manipulating my waypoint graph and all related meshes in ECS unless there is a new mesh struct type for ECS but i don’t think there is that i can find?

If everything is a system then wouldn’t my system end up doing too many things at once? If i have multiple systems how do you make sure all the systems do what they need to do when the user clicks for that frame? I’m not really getting it at the moment. I think my brain is still very much in OOP mode and am struggling to get how to do it differently.

Input Manager:

Input System:

So I just showed you input. For ScriptableObjects, if you use subscenes, avoid them at runtime until you have a lot more experience. GameObject prefabs are usually the better option. And for integrating ECS into an existing project, it is not a great experience at the moment. If you read my linked post, you would see I talked a fair bit about that, and how that is supposed to improve a lot in Entities 2.0.

The magic pieces here are Mesh.MeshDataArray and UnityObjectRef. The former allows you to jobify modification, and the latter lets you store them in ECS components in an unmanaged form. There is still the gotcha that you have to go managed temporarily for applying the MeshData modifications to the Mesh objects, but just because it is managed doesn’t mean you can’t do it in a system. If you don’t Burst-compile the OnUpdate() of a system, you can do any managed thing in there, potentially even calling into MonoBehaviours or something.

There’s lot of ways to go about it. The important thing to remember here is that input is data. And data is the interface between systems. You reason about input in ECS no differently than how you reason about transforms or health.

1 Like

I see all the examples are in a netcode demo, i never would’ve looked there since i don’t use multiplayer stuff. Don’t know why their actual documentations make so little mention of half of this stuff.

Well a GameObject makes no sense in this case, the scriptable object just contains meshes and materials which i use to procedurally generate at runtime, guess you could think of it as a prefab mesh that i will then clone and edit.

Making a GameObject for that doesn’t really make sense. I would need to load the Mesh/Materials from the Scriptable Object, then the system generates the procedural meshes from the settings in the ScriptableObject. I guess when you say GameObject you mean just create an empty gameobject and bake it to an entity with the references to mesh/materials and use that as the “ScriptableObject” data in the ECS setup?

Yes. This. You can use prefab entities at runtime as resource containers, without ever instantiating them. This is easier to bake with GameObject prefabs. Plus GameObject prefabs support prefab variants, which might be overkill for your use case, but is really nice for more complex resources.