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

queryChanged does not work for multiple worlds #155

Open
TheyCallMeRyan opened this issue Jan 11, 2025 · 2 comments
Open

queryChanged does not work for multiple worlds #155

TheyCallMeRyan opened this issue Jan 11, 2025 · 2 comments
Labels
bug Something isn't working

Comments

@TheyCallMeRyan
Copy link

Description

Loop starts topoRuntime for all worlds.
queryChanged calls useHookState expecting a pristine result for each world.
Instead, all worlds receive the same result from topoRuntime, and since the first world to call queryChanged there sets hookState.storage, all future worlds will both:

  1. Fail to iterate over any pre-existing entities
  2. Fail to mark _changedStorage[componentToTrack] for that specific world
    With the result being that no other world will receive the associated data

Steps to reproduce

Minimum Reproduction:

--!strict

-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Libraries
local Matter = require(ReplicatedStorage.Matter)

local World1 = Matter.World.new()
local World2 = Matter.World.new()
local World3 = Matter.World.new()

local Worlds = {
	World1 = World1,
	World2 = World2,
}

local Component = Matter.component("TestComponent")

local Loop = Matter.Loop.new(Worlds)
Loop:setWorlds(Worlds)

Loop:scheduleSystem(function(worlds: {[string]: Matter.World})
	for worldId, world in worlds do
		print("queryChanged: ", worldId)
		for id, record in world:queryChanged(Component) do
			print("Component Changed: ", worldId, id, record.new.text)
		end
	end
end)

local Bindable = Instance.new("BindableEvent")

Loop:begin({
	default = Bindable.Event
})

World1:spawn(Component({text = "Test 1"}))
World2:spawn(Component({text = "Test 2"}))
World3:spawn(Component({text = "Test 3"}))

Bindable:Fire()

Worlds.World3 = World3

Loop:setWorlds(Worlds)

Bindable:Fire()

Output:

  18:56:13.548  queryChanged:  World2  -  Server - TestSingleLoopMultipleWorlds:25
  18:56:13.548  Component Changed:  World2 1 Test 2  -  Server - TestSingleLoopMultipleWorlds:27
  18:56:13.548  queryChanged:  World1  -  Server - TestSingleLoopMultipleWorlds:25
  18:56:13.549  queryChanged:  World1  -  Server - TestSingleLoopMultipleWorlds:25
  18:56:13.549  queryChanged:  World2  -  Server - TestSingleLoopMultipleWorlds:25
  18:56:13.549  queryChanged:  World3  -  Server - TestSingleLoopMultipleWorlds:25

queryChanged failed to receive either the Component in World1, or the one in World3 because it processed the one in World2

Expected behavior

I expect queryChanged to work for each world assigned to the Loop and not just the first one called.

@TheyCallMeRyan TheyCallMeRyan added the bug Something isn't working label Jan 11, 2025
@TheyCallMeRyan
Copy link
Author

It might be possible to do something related to setting unique topoRuntimes for each world in Loop; however, I think a better solution might be to have each world store the storage table as:
world._queryChangedHooks[hookState] = storage
instead of hookState.storage = storage
This would also allow for easy cleanup in queryChangedCleanup.

@TheyCallMeRyan
Copy link
Author

The potentially larger issue going on here is that using systems within Loop with topoRuntime.start called for all the worlds will make it so any calls to topoRuntime within that system will get the same result for all worlds.

So if you wanted unique values for useEvent/useThrottle/useDeltaTime/other hooks, they'll be the same.
I think in general, other hooks getting the same result in a system with multiple worlds is fine, but I think specifically world:queryChanged is world specific and needs world-specific hook results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant