Best way to Handle Dynamic Events?

Hello fellow developers! As i’m making a custom navigation mesh generator (attempting) for a A* implementation, i would like it to be “dynamic” (somewhat), meaning i need know what the best way of handling events is. in this case by “Handling Dynamic Events” i am talking about handling when objects in the world are inserted, moved or deleted so navigation mesh can be updated accordingly. Determining when something is inserted or removed is trivial and not too expensive or anything (because there is a method for it), however determining when any object in the world (workspace) is moved, while this is also trivial, i haven’t been able to come up with relatively cheap way of doing this. I know i could go and connect events to ever part in the workspace, but i don’t think that really is good solution especially when things start to scale. i have also thought of using a loop and checking for changes in parts that are within a certain area, but i don’t his is really scalable either, but hey maybe i’m wrong.

To sum everything up, i’m am asking what the best way of handling/finding out when any object (part) in the world is inserted, removed but most importantly moved . if i am perhaps not clear enough, don’t be afraid to ask, Thanks!

1 Like

I think you could use that functions :

workspace.Changed:Connect(function(property)
if property == "Part" then

-- function here

end 
   end

Then you could link that to anything

i wish that would work!, but anything changed to descendants/children of the workspace (or a Basepart) don’t fire that event because they aren’t properties.

Some pseudo code and my current understanding

On game.Workspace.DescendantAdded do
Check if its the mesh that your navigating too
On Descendant.Changed do
Check for a parent change. If it is removed then parent will be nil, moved will be different parent, so on and so forth

This way, when a new object is added you are automatically tracking the new object.

1 Like

i like your idea, with your pseudo code i would also ideally connect events to parts when the game starts as well (which isn’t a big deal), but the real problem is the amount of connections, if there were lets say 500+ parts in the workspace and events were connected to all of them, i don’t think that would be good. i would like to prevent so many events being connected especially when alot of of them might not be fired much at all. Maybe i could split the world into chunks and connect and disconnect events when needed? Any other ideas ?


Btw i’m not sure i understand what you mean by:

But, nonetheless Thanks!

I think you should really take a look at this, written by engineers at valve that worked on counter strike Nav Mesh - Valve Developer Community

What is computed during generation

The following steps occur during Navigation Mesh generation:

  • Starting at a player spawn point, walkable space is sampled by “flood-filling” outwards from that spot, searching for adjacent walkable points
  • Rectangular Navigation Areas are constructed from the sampled data
  • Hiding and Sniper spots are computed
  • Encounter Spots and Approach Points are computed (this can take awhile)
  • Initial Encounter areas are computed

Source

Sorry, I meant you should filter the part before connecting it to the event, aka, making sure its at a certain y value so its a floor.

interesting, i do remember seeing this at some point, but unfortunately i don’t think it really addresses how navigation mesh is updated dynamically or how “dynamic events” are handled. Also if it were, i’m sure that what ever engine they would use would handle these “events” better and have a method or something for it.

I think what you could do for the connections issue is to have a “main” model for each “parent” (well like a main model for x amount of parents) so you can cut it down to a couple of connections and then check when descendants change, I am rushing to bed at the moment so I may sound stupid, forgive me!

This is just an idea, you would connect functions to all parts with achored == false, these parts change a lot:

for i, BasePart in pairs(workspace:GetDescendants()) do
    if BasePart:IsA("BasePart") then
        if not BasePart.Anchored then
            BasePart.Changed:Connect(ChangedFunction)
        end
    end
end)

Then you would connect functions to parts via a bindableevent, when a property, let’s say size is changed from a script. This also applies to new instances:

local Bindable = -- the bindable event

Part.Size = Vector3.new(1, 1, 1)
BindableEvent:Fire()
local Bindable = -- the bindable event

Bindable.Event:Connect(ChangedFunction)
1 Like

The main issue you will encounter is that listening to DescendantAdded and DescendantRemoving on workspace is quite costly, not to mention that you will probably have to listen to the movements (:GetPropertyChangedSignal(“Position”) and for orientation). A complex map will be very hard to handle.

Instead, you should create your own custom system, with each significant movement manually updating the mesh. I did it before with my flood fill algorithm and it saved around 6 frames per update. Although note that it was for an RTS like Starcraft, so they were limited to structures being added or removed as well as vehicle movement, while the entire map was divided into sectors.

1 Like