-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
[Lua] SimulatedBody.GetOnCollisionBeginEvent() issue #17630
Comments
IMO, Things do need their collision to work on frame 1, not frame 2. It sounds like its missing some sort of architecture here to call back when the shapes are ready, or added, or something, so that by the time activate is done, it can immediately collide. Alternatively, a layer of abstraction so that the event is always available to connect to, even if the shapes take a frame. Maybe a call at the bottom of OnEntityActivated for Physics Is Ready or something |
I checked the BaseColliderComponent and to me it doesn't look like that the InitShapes needs to be done in the Activate method. It can be put into Init so the shapes will be ready when the components gets activated and the rigid bodies are created. It looks to me redundant to Init the shapes and clear everytime we activate and deactivate the component. Also I was thinking, why would we want to create and destroy a rigid body ever time we activate/deactivate the component? Is there a reason it is as it is right now? Why not just create once then modify the instance and reset if needed. |
regarding activate/deactivate / Init... The opposite of Activate, is Deactivate. After deactivate, it can be reactivated again. Its possible to add and remove components (including the rigid body component and collider components themselves) while the entity is deactivated, but not while active. This guarantees that when you activate and successfully cache some pointer to something, like a shape, or a callback, or an event, or etc, then, until Deactivate, all pointers to other components cached for performance remain valid and do not need to be re-fetched every frame. Its also by convention when components are supposed to be "listening and active in the world", interacting with other stuff... Actually adding rigid bodies and shapes to the world during that phase (parallel compilation or "dead entities" in the undo stack or component wrappers for game-only entities) would be a super bad idea and would potentially flood the "real" editor world with superflous rigid bodies and shapes that are not supposed to be doing anything yet. This is probably why shapes are destroyed during deactivate and created during activate. Last thing you want is shapes actually being added to a physx world when its loading entities (deserialize + init, but not activate) in the Asset Processor to crunch them into spawnables. There may be some way to cache them so that they do not disappear entirely in deactivate, but do if their component is deleted though ---? That being said, it does sound like there's a sort of sequence of events here, to me it sounds like we are missing a callback of some sort here, so that things that depend on physics can hook into when physics is ready, still part of activate...? Like Activate() -> Add Rigid Bodies/Shapes -> PhysicsReady -> OnPhysicsReady -> do stuff? Its tempting to add a "AfterActivate" callback but that is a treacherous road to travel since usually that results in someone going "but I need to do something After, AFTER, AFTER activate..." |
Fair enough. I digged more into this and it looks like, that RigidBodyNotifications is used to handle initialization in using the events virtual void OnPhysicsEnabled([[maybe_unused]] const AZ::EntityId& entityId)
virtual void OnPhysicsDisabled([[maybe_unused]] const AZ::EntityId& entityId) In short, in Lua it would like this: function MyLuaScript:OnActivate()
self.RigidBodyNotificationBusHandler = RigidBodyNotificationBus.Connect(self, self.entityId)
end
function MyLuaScript:OnDeactivate()
self.RigidBodyNotificationBusHandler:Disconnect()
end So looking into some examples like in ForceRegionComponent.cpp. It does this: Activate: Connect to RigidBodyNotificationBus This however again, causes an issue on the Lua level because when disconnecting at OnDeactivate from the RigidBodyNotificationBus, the OnPhysicsDisabled event is not fired. So using the new bus, RigidBodyNotificationBus I thought would help to "fix" this issue but then again, disconnecting on OnDeactivate seem to cause another unexpected issue. |
I'm not sure I 100% follow, I was expecting something like this ,with scopes not overlapping
I'm guessnig the order of that destruction is switched? I can understand though, why someone might want to invoke the lua OnDeactivate at the beginning, before the entity is actually deactivated, so that all the systems will still in place and lua can "do stuff" using the entity - an actual deactivated entity can't be talked to and all its busses are already gone... but I'm not sure that's idomatic when shutdown should be happening in reverse order to startup... (I took a break here to look at the code). Interesting, it looks like onActivate is invoked when the ScriptComponent (the LUA Script component that you literally add to the entity in the inspector) is Activate()d, and onDeactivate is invoked when that same component is deactivated during entity deactivation. I'm pretty sure components are activated (and deactivated) in the order they appear in the component inspector panel, and in REVERSE when deactivating, so you should definitely see |
Here this is a simple Lua script. I do assume, connecting is done in the correct way, because I would assume, I do connect to RigidBodyNotificationBus in OnActivate, and disconnect in the OnDeactivate: local CollisionHandlingTest =
{
Properties =
{
}
}
function CollisionHandlingTest:OnActivate()
Debug.Log("OnActivate")
-- Connect to the RigidBodyNotificationBus
self.RigidBodyNotificationBusHandler = RigidBodyNotificationBus.Connect(self, self.entityId)
end
function CollisionHandlingTest:OnDeactivate()
Debug.Log("OnDeactivate")
-- Disconnect from the RigidBodyNotificationBus
self.RigidBodyNotificationBusHandler:Disconnect()
end
function CollisionHandlingTest:OnPhysicsEnabled(entityId)
Debug.Log("OnPhysicsEnabled")
end
function CollisionHandlingTest:OnPhysicsDisabled(entityId)
Debug.Log("OnPhysicsDisabled")
end
return CollisionHandlingTest This is a picture of the console: As you can see, the OnPhysicsDisabled event is not triggered because we do disconnect in OnDeactivate. If I move the local CollisionHandlingTest =
{
Properties =
{
}
}
function CollisionHandlingTest:OnActivate()
Debug.Log("OnActivate")
-- Connect to the RigidBodyNotificationBus
self.RigidBodyNotificationBusHandler = RigidBodyNotificationBus.Connect(self, self.entityId)
end
function CollisionHandlingTest:OnDeactivate()
Debug.Log("OnDeactivate")
end
function CollisionHandlingTest:OnPhysicsEnabled(entityId)
Debug.Log("OnPhysicsEnabled")
end
function CollisionHandlingTest:OnPhysicsDisabled(entityId)
Debug.Log("OnPhysicsDisabled")
-- Disconnect from the RigidBodyNotificationBus
self.RigidBodyNotificationBusHandler:Disconnect()
end
return CollisionHandlingTest Here the console: So yes, the order is not good. I am not sure why I am the only one having this issue and If everyone is using Script Canvas, is it handled differently? |
Also moving the component up and down in the inspector does not have any effect, because even though I put the lua script at the most top. when saving everything, restarting the editor, and looking at the order, the lua script is again at the bottom. |
Describe the bug
When using Lua to detect collisions through the SimulatedBody.GetOnCollisionBeginEvent(...) function, it consistently returns nil. The reason for this issue can be found in the RigidBodyComponent.cpp file, where the following line exists:
Upon examination, it appears that the creation of the rigid body is intentionally being deferred, as noted in the accompanying comment. However, this delay leads to a problem when attempting to detect collisions via Lua within the OnActivate() function.
Not sure if this is my wrong doing or this is really a problem.
Steps to reproduce
Steps to reproduce the behavior:
Expected behavior
SimulatedBody.GetOnCollisionBeginEvent(self.entityId) should not return nil.
Actual behavior
A clear and concise description of what actually happened.
Screenshots/Video
If applicable, add screenshots and/or a video to help explain your problem.
Found in Branch
SimulatedBody.GetOnCollisionBeginEvent(self.entityId) returns nil.
Commit ID from o3de/o3de Repository
26baf4a
Desktop/Device (please complete the following information):
The text was updated successfully, but these errors were encountered: