I want to start using physics.set_listener, but once I add the code as shown on the example in the manual, all my objects are still getting their regular collision messages, and nothing is printing from the listener function.
I have a game object with a “main.script” on it which is where my game starts, and this line is in my function init(self) function, it’s definitely being run because I put a breakpoint on it and it hit.
physics.set_listener(physics_world_listener)
But breakpoints are not being hit on any of the lines below and nothing is being printed. I would expect trigger_event to be hit and I would also expect all the behaviour in my game to break, since according to the manual, objects don’t receive messages once you activate the listener;
local function physics_world_listener(self, event, data)
if event == hash("contact_point_event") then
-- Handle detailed contact point data
pprint("contact_point_event: "..data)
elseif event == hash("collision_event") then
-- Handle general collision data
pprint("collision_event: "..data)
elseif event == hash("trigger_event") then
-- Handle trigger interaction data
pprint("trigger_event: "..data)
elseif event == hash("ray_cast_response") then
-- Handle raycast hit data
pprint("ray_cast_response: "..data)
elseif event == hash("ray_cast_missed") then
-- Handle raycast miss data
pprint("ray_cast_missed: "..data)
end
end
Yes, it’s the first code snippit I put in my post.
Here’s my full init function
function init(self)
-- Add initialization code here
-- Learn more: https://defold.com/manuals/script/
-- Remove this function if not needed
print("Hello world")
msg.post("/camera#camera", "acquire_camera_focus")
msg.post("@render:", "use_camera_projection")
msg.post(".", "acquire_input_focus")
physics.set_listener(physics_world_listener)
--msg.post(player_join_screen, "load")
msg.post(level_race, "load")
game_state = GameState.GAMEPLAY
end
Ok here’s roughly what I have, and there’s still no effect. This is how I’ve been calling functions in my other scripts;
local physics_world_listener
...
function init(self)
...
physics.set_listener(physics_world_listener)
...
end
physics_world_listener = function(self, event, data)
...
end
Ok well, it works in a blank project, so no idea what’s happening in my project that makes it not work. I even tried just making the function local above the init function exactly as it appears in the example, and it still doesn’t work in my project.
Ok it seems if you load a new collection proxy, that involves re-creating the physics, so you have to do this script after that collection proxy has been loaded.
Every collection has its own physics world.
So, yes, you should set the listener for each physics world separately from inside the physics world itself.
It might be good to make mention of it there. Though to the manual’s credit - like a lot of good manuals, the info is all there, just not in the place you might expect to find it depending on what mindset you’re coming from or what you’re doing. I don’t think it’s anyone’s fault really.
The “Collection proxy” page makes mention of a “new physics world” being created.
To fit the game objects and their components the engine allocates the memory needed for the whole “game world” into which the contents of the bootstrap collection are instantiated. A separate physics world is also created for any collision objects and physics simulation.
The API reference for the function states that the function “sets a physics world event listener”.
And the manual page also mention the physics world:
“This function takes a callback as its argument, which will be called with information about all physics interactions in the world”
We could perhaps add a special mention that the function must be called from within the physics world? We could also add a link to the collection proxy page where the concept of individual physics worlds are mentioned?