Facepunch / sbox-issues

176 stars 12 forks source link

Can't reliably tell when object enters/exits trigger if it has more than one physics shape #4419

Open Gmod4phun opened 9 months ago

Gmod4phun commented 9 months ago

Describe the bug

I suck at explaining things so hopefully I will make sense.

When having a collider with the trigger option enabled, I am unable to use OnTriggerEnter and OnTriggerExit to check when an object enters/exits the trigger if the object has more than one physics shape.

The enter/exit methods gets called multiple times, I presume for each PhysicsShape of the collider. Collider seems to be always the same, as can be seen from the example, so I guess one collider and multiple shapes. Unless I am just misunderstanding on whats going on in the background, it seems like there is no way to accurately tell if an object has really exited the trigger. The trigger's Touching property only returns a single of the object's colliders at all times, but upon exit it's always 0, so trying to check if any other colliders are touching the trigger upon one's exit does not work.

This piece of code can be used to debug the trigger events.

public class TriggerDebug : ModelCollider, Component.ITriggerListener
{
    public List<Collider> UniqueColliders { get; set; } = new();

    TimeSince LastUpdate = 0;
    protected override void OnUpdate()
    {
        base.OnUpdate();

        if ( LastUpdate > 2 )
        {
            LastUpdate = 0;
            Log.Info( $"unique colliders overtime: {UniqueColliders.Count()}" );
        }
    }

    public void OnTriggerEnter( Collider other )
    {
        Log.Info( $"something entered the trigger, we are being touched by {Touching.Count()} colliders" );

        if ( !UniqueColliders.Contains( other ) )
        {
            UniqueColliders.Add( other );
        }
    }

    public void OnTriggerExit( Collider other )
    {
        Log.Info( $"something exited the trigger, we are being touched by {Touching.Count()} colliders" );
    }
}

To Reproduce

  1. Make a GameObject and add the provided debug component to make a trigger and set its model to something (like a crate)
  2. Add another object, with a model and physics that have more than one physics shape (like the toilet model)
  3. Make the model go through the trigger and observe the behaviour

Expected behavior

I am not really sure what would be the expected behaviour, but most likely the trigger could have another property like TouchingShapes that should return the list of all currently touching PhysicsShapes instead of Colliders. At the moment, there is always one Collider per object, but trigger events get called multiple times. Another approach could be to only call the trigger enter/exit events only once, as in call the exit only if a PhysicsShape exited and no other PhysicsShapes are in the trigger anymore.

Media/Files

Showcase of a model with multiple physics shapes passing through a trigger, triggering enter/exit multiple times.

https://github.com/Facepunch/sbox-issues/assets/5991682/c9fcb991-b8b6-413d-8dcc-f3d022d574c2

Additional context

No response

Gmod4phun commented 9 months ago

Here's probably a better video, showing the issue.

https://github.com/Facepunch/sbox-issues/assets/5991682/cffd4c7d-8330-4928-a941-6a720bcf36ee

Also, when the last even was an exit, the Touching list is empty, despite the physics mesh clearly touching the trigger, like this: image

garrynewman commented 9 months ago

That makes sense - will get it fixed

Gmod4phun commented 2 months ago

Still a thing, keeps me from progressing,

Gmod4phun commented 1 month ago

image

Bitching again just in case it gets accidentaly closed. This is still broken :(

Gmod4phun commented 2 weeks ago

Added a simpler demonstration of the issue in the Testbed trigger scene. The chair is still in the trigger, but a part of it that left triggered the exit event.

https://github.com/user-attachments/assets/83616cba-d2c1-4d11-b356-2c12a831f3ab