#Best ways to spawn Entities from Visual Element

1 messages · Page 1 of 1 (latest)

ember monolith
#

I heard that the UI toolkit is a good way matching UI with ECS. I want to spawn buildings (prefabs) from a button press. What's the best way to do this?
I have two examples but I assume there are better ones:

var system = World.DefaultGameObjectInjectionWorld.GetExistingSystemManaged<UIButtonSystem>();
system.SpawnEntity();
        
//example2
var query = entityManager.CreateEntityQuery(typeof(BuildingEntitiesComponent));
var buildings = query.GetSingleton<BuildingEntitiesComponent>();
entityManager.Instantiate(buildings.house);```
This code is in the VisualElement class of the game screen.
Thanks for your help!
trim cliff
#

when using ui toolkit with entities, i use it within a system

#

you don't seem to be doing that so what is your setup?

#

the nice advantage of ui toolkit with entities is you don't need gameobjects

ember monolith
#

This is my class for the visual element:

{
    public new class UxmlFactory : UxmlFactory<GameScreenManager, UxmlTraits> { }
    private EntityManager entityManager;
    
    public GameScreenManager()
    {
        RegisterCallback<GeometryChangedEvent>(OnGeometryChange);
        entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
    }

    void OnGeometryChange(GeometryChangedEvent evt)
    {
        this.Q("Button")?.RegisterCallback<ClickEvent>(ev => SpawnEntity());
        UnregisterCallback<GeometryChangedEvent>(OnGeometryChange);
    }

    private void SpawnEntity()
    {
        Debug.Log("Spawning Entity");
        //example 1
        var system = World.DefaultGameObjectInjectionWorld.GetExistingSystemManaged<UIButtonSystem>();
        system.SpawnEntity();
        
        //example2
        var query = entityManager.CreateEntityQuery(typeof(BuildingEntitiesComponent));
        var buildings = query.GetSingleton<BuildingEntitiesComponent>();
        entityManager.Instantiate(buildings.house);

    }
}```
#

What do you mean with within a system?

autumn igloo
#

my approach is via messaging

#

when you click button of UI (doesn't even matter what framework)

#

you send message SpawnEntityMessage to bus

#

then your system either directly creates via callback, or some other handler creates visible to system request so it can do it in OnUpdate

ember monolith
trim cliff
#

well the uidocument has to go on something

autumn igloo
#

UIToolkit requires only 1 game object - UI Document for rendering, but not for UI management

trim cliff
#

but that's about it

ember monolith
ember monolith
autumn igloo
#

you'll just need to send Messenger to your UI, so it can send messages to it

ember monolith
#

Ok thank you I will have a look at this

ember monolith
trim cliff
#

i have 1 system per panel

#

and it creates the UI

autumn igloo
#

just pseudoexample of how simple it is
OnCreate{
var uiRoot =Resources.Load("MyUXMLFile").Instantiate();
}

ember monolith
#

Oh wow this is really good thank you!

autumn igloo
#

(I personally don't like this approach because it requires you to hardcode UI)

ember monolith
#

I can understand this but for my simple ui it's ok

ember monolith
#

Can you also get a reference to the active UI Document / Visual Element inside the SystemBase? So that you can register button callbacks? I tried static referencing but this didn't work

autumn igloo
#

meaning you can just keep it as static reference

#

my suggestion would be a bit different though:
Make everything related to UI in separate UI classes and have a special interface layer so you could affect your UI from within systems

#

also so you could keep your UI objects oriented freely

ember monolith
#

I tried this:

public class GameScreenManager : VisualElement
{
    public new class UxmlFactory : UxmlFactory<GameScreenManager, UxmlTraits> { }
    public static GameScreenManager INSTANCE { get; private set; }

    public GameScreenManager()
    {
        INSTANCE = this;
        RegisterCallback<GeometryChangedEvent>(OnGeometryChange);
    }
}

public partial class UIButtonSystem : SystemBase
{
    
    protected override void OnCreate()
    {
        var element = GameScreenManager.INSTANCE;
        element.Q("Button")?.RegisterCallback<ClickEvent>(ev => SpawnEntity());
    }
}

But it isn't working

ember monolith
autumn igloo
#

besides, this is just empty one

autumn igloo
ember monolith
autumn igloo
#

var element = GameScreenManager.INSTANCE;
Just like that

#

if you're not familiar with UI toolkit, just do UI gui

#

UITOolkit requires way too much time to learn

ember monolith
ember monolith
autumn igloo
#

well sir, because you are doing something absurd in code you shared 😅

#

once again UITK requires quite a lot of time to get into

ember monolith
autumn igloo
#

so if your time is at value

#

I suggest to do UI you know

#

and before trying to connect anything to Systems

ember monolith
autumn igloo
#

just make logs callbacks first

autumn igloo
ember monolith
#

That's right. The problem is that I want something basic like calling a function in a system with a button press. There are a lot of tutorials that explains this but not with ecs. Maybe I will just stick to the custom VisualElement that calls the function like this:

var system = World.DefaultGameObjectInjectionWorld.GetExistingSystemManaged<UIButtonSystem>();
system.SpawnEntity();```
For now
autumn igloo
#

don't do that

#

don't access world from UI

#

access UI from world

#

that's the correct approach

#

just make self sufficient UI with one manager for it

#

manager will contain all methods, properties

#

access this manager from System and that's it

ember monolith
#

Thats not very helping. Can you give me at least a small example on how I access in the OnCreate function of my system the UI and register button callbacks in my system?

autumn igloo
#

in OnStartRunning

#

OnCreate of World runs before Scene is loaded

ember monolith
#

OnStartRunning is also fine

autumn igloo
#

you don't register any callbacks in system

#

you do that in your UI classes

#

in System you only access Manager

#

with all relevant to system logic exposed

#

for example: event

#

for now just make your UI that does not depend on entities in any way

#

that simply makes debug logs on click

#

until then - DOTS is irrelevant

#

and you are subject of help on other channels

ember monolith
#

Okay I have this now:

    public class GameScreenManager : VisualElement
    {
        public new class UxmlFactory : UxmlFactory<GameScreenManager, UxmlTraits> { }
        public GameScreenManager()
        {
            Debug.Log("constructor");
            RegisterCallback<GeometryChangedEvent>(OnGeometryChange);
        }

        void OnGeometryChange(GeometryChangedEvent evt)
        {
            this.Q("Button")?.RegisterCallback<ClickEvent>(ev => SpawnEntity());
            UnregisterCallback<GeometryChangedEvent>(OnGeometryChange);
        }

        public void SpawnEntity()
        {
            Debug.Log("Spawning");
        }
    }