Non convex Mesh colliders?

Hi guys
for my “building” project, I need to activate lights for each room by using “OnTriggerEnter” and “OnTriggerExit”. Everything works perfectly fine for box shaped rooms (box collider), the problem is that one of the room is L-shaped (see picture). So for this one, I need L-shaped collider as well. I’ve tried several approaches but none of those works:
1/ Created L-shaped 3D “dummy” object, imported it to Unity, turned off mesh renderer and used it as a source shape for Mesh collider. Unfortunatelly, the “Is trigger” option is greyed out till I select “convex”. And if I select convex, the shape of the trigger changes affecting another room collider. So not a solutin for me.
2/ I’ve tried to add two box colliders, but those are handled separataelly. And since I need to check both OnTriggerEnter and OnTriggerExit, this is causing a mess with scripted behavior. So not a solution as well.

The best way for me would be a possiblity to “group” more collider shapes to act as one but I haven;t found anything like that.

Any tips?
thanks
Milan

Instead of using OnTrigger (if you can’t handle two for the same room, which is possible with a bit of coding) you should directly check if the player’s position is withing some volume, or use the Physics.OverlapBox for both volumes and Store if the player was inside any one of them last frame and use that for TriggerEnter and TriggerExit

OK thanks for providing the ways to go. The problem is that I use OnTriggerEnter/Exit for all other rooms. So chenging it would mean qouite a significant amount of work.
I’m interested on “handle two for the same room”. Any tips?

I’m not 100% sure but can’t you just add a second box collider to the same gameobject? With that you can make up the room from convex pieces

Well, the amount of work still depends on the way you structured the code,
Here is an example:
Use this on the individual colliders:

public class PlayerTrigger : MonoBehaviour
    {
        [SerializeField]
        private Collider col;

        public Collider player;
       
        public RoomTrigger room;

        private void Awake()
        {
            if (!col)
                col = GetComponent<Collider>();
        }

        private void OnTriggerEnter(Collider other)
        {
            if(other == player)
                room.PlayerEntered(col);
        }

        private void OnTriggerExit(Collider other)
        {
            if(other == player)
                room.PlayerExit(col);
        }
    }

Use this for the room as a whole:

public class RoomTrigger: MonoBehaviour
    {
        /// <summary>
        /// Tells if player is inside the Trigger Area
        /// </summary>
        public bool isInside;

        public Dictionary<Collider, bool> triggerEnter;

        private void Awake()
        {
            triggerEnter = new Dictionary<Collider, bool>();
        }

        /// <summary>
        /// Call this function when player enters the area
        /// </summary>
        /// <param name="sender"></param>
        public void PlayerEntered(Collider sender)
        {
            triggerEnter[sender] = true;
            CheckInside();
        }

        /// <summary>
        /// Call this function when player leaves the area
        /// </summary>
        /// <param name="sender"></param>
        public void PlayerExit(Collider sender)
        {
            triggerEnter[sender] = false;
            CheckInside();
        }

        /// <summary>
        /// Checks whether the player is inside and updates isInside
        /// </summary>
        private void CheckInside()
        {
            isInside = false;
            foreach (var key in triggerEnter)
            {
                if (key.Value)
                {
                    isInside = true;
                    break;
                }
            }
        }
    }

Hope this helps

@Ruchir : thanks, this seems doable in my case. Will try.

@tjmaul : not in my case. Since I have to control both OnTriggerEnter and OnTriggerExit, this calls the unwanted actions in the mid of the room when those two colliders interlaps since those are not taken as a simple one but separated.

An alternative would be to not use triggers for the room, but to develop doors with one small trigger each side of their threshold, then depending on which trigger is entered first you know the direction of travel. Give the doors an id / ref for the two spaces they connect and send an event for those space ids (entered/exited) . This gives you more flexibility for room design and and tracking entry points.

I appreciate this is not the quick fix you are looking for, but I think it is worth considering for others with a similar problem.

AlTheSlacker: good point. It seems I made a mistake at the design phase of the project, not knowing that it is not so easy to create non-convex triggers. As you mention, changing all behavior to use door enter points would do the trick, unfortunatelly, it would mean to redo quite a lot of stuff. Definitelly worth of mentioning for the others, though.

Anyways, client (well, this is not game, rather simulation of “smart house” so yes, there is a client) does not want me to use that small (toilet) room on the side so I ended up with squared room anyway. Lucky me :wink:

2 Likes

Well, you are on a flat plane - you can just build a 2D Collider and use Collider2D.OverlapPoint() (of course you have to use the 2D coordinates of the XZ plane and know on which floor your character is) - idk about 2D Triggers, but it should work too - then you would have to transfer your players XZ coords to the XY plane where a dummy object walks around.

You could also build your rooms out of points in space, which form a polygon (must be sorted counterclockwise but thats quite easy) and use the pnpoly algorithm to check if a point is inside a room - thats what I would do.

If your game is grid based, you could just work with the grid.

These are just some alternatives, if you ever want some diagonal walls or something … cause then it will be hard to fill the space with colliders.

Why does the collider have to be L-shaped ? You can use a single box collider for the whole area in blue. Does it matter that some of the box collider would be in an unreachable area outside the room (top right) ?

edited for clarity.

xxxx ooo
xxxx ooo
xxxxxxxx
xxxxxxxx