Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

event for when a component/node is fully loaded, active and actually in an active graph, similar to other engines "start" function/event #34

Open
Plagiatus opened this issue Oct 15, 2024 · 3 comments
Labels
enhancement New feature or request

Comments

@Plagiatus
Copy link
Collaborator

I'm struggling with this problem pretty much every time I'm writing a ComponentScript that needs to initialize itself somehow.

What Event to use to know that the component is attached to a node that is in an actively loaded graph, with all other components and children deserialized?

I've tried various other events in the past, but they all have side effects or need special extra steps.

My current workaround is waiting for NODE_DESERIALIZED before I can attach to node events (but this also fires when the graph is intially loaded from the resources, not just when it's created/visible/active ingame). Then attaching a GRAPH_INSTANTIATED listener to the node, after which I actually can assume that everything i want is loaded.

Oh and of course I always need to add the "Don't do this in the editor" boilerplate as well.

@Plagiatus Plagiatus added the enhancement New feature or request label Oct 15, 2024
@JirkaDellOro
Copy link
Member

When FUDGE loads a graph, it's fully created and stored in memory, visible or not. So nodes get deserialized and the graph instantiaed. So those events are properly sent.

But what does "created/visible/active ingame" actually mean?

  • when you initialize a viewport with that graph?
  • when you create a graph instance?
  • when you append a graph or a graph instance as child in a scene?
  • when the node gets rendered?

@plojo
Copy link
Collaborator

plojo commented Oct 18, 2024

Unity documentation states:
"Start is called on the frame when a script is enabled, just before any of the Update methods are called for the first time."

I would say it's called before a node gets rendered, but only once and only if the script is active.

Here are my thoughts on the matter:
The current way of updating scripts is by registering a handler on the loop:
ƒ.Loop.addEventListener(ƒ.EVENT.LOOP_FRAME, this.update);
So, what we could do is simply register a start method on the loop that gets executed only once and before update:
ƒ.Loop.addEventListener(ƒ.EVENT.LOOP_FRAME, this.start, { once: true });
But the problem with registering anything on the loop is that we have no way of knowing if our script is actually part of a graph that is being rendered. So basically, our update runs all the time regardless of whether the graph is being drawn by a viewport or not.

Then we have the EVENT.RENDER_PREPARE, which gets dispatched to every node on every call to Render.prepare(), usually once per drawn frame and only to nodes that are about to be drawn by a viewport. Now, the first time we receive this event is almost the ideal point to run a start, except that EVENT.RENDER_PREPARE gets dispatched to every node before the transforms are recalculated.
So ideally, we might need a new (update) event that gets broadcast from a viewport to its attached branch after it runs prepare. Then, on the first time we receive this event and our script is active, we would have our start event.

@Plagiatus
Copy link
Collaborator Author

I understand that these events are sent as they were intended, hence why I'm asking for a new one that fulfills the need i described.

I'm with Jonas on closing in on the actual moment that the event should fire.

  • when the node with the attached component is loaded in a viewport
  • when the node with the attached component is created via script or otherwise
  • when all decendants and components (and preferably the entire graph) of the node is loaded and ready to be accessed
  • before any (render) loops (though we need to add the eventlistener for that ourselves anyways, preferably in a start event)

all of the above combined is what i think I'm looking for.

So out of your suggestions I think the closest one is

when you append a graph or a graph instance as child in a scene

Assuming "in a scene" refers to a graph that's currently loaded in a viewport and "append" means both adding new instance and initializing the scene with the graph.

 

We could call it "START" or "READY" or "NODE_VISIBLE_AND_FULLY_LOADED" or whatever else describes it best.

 


 

When FUDGE loads a graph, it's fully created and stored in memory, visible or not. So nodes get deserialized and the graph instantiaed

This is another confusing matter. What is loaded and/or activated/processed when? I am still trying to grasp at what point what is loaded and activated, so I can only initialize the things I actually need at the moment and not process literally everything.

A graph instance that is only every used to dynamically create objects doesn't need to be loaded and processed all the time. I currently can't think of a situation where I'd want to process a graph or anything related to the graph without that graph being actively rendered and being part of the current game.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants