How to program a Trigger Volume?

Started by
4 comments, last by Key_C0de 3 years, 4 months ago

In a 3d game it is often desirable to call events asynchronously when an entity such as the player, or other types of entities overlap with a specific bounding volume. How would I program this in C++ such that the Trigger Volume detects this actor/entity/whatever that overlapped it and can get a handle/pointer to it and execute an event on it. This is what Unreal Engine 4 does for example with its dozens of Volumes for example TriggerBox with OnBeginOverlap UFunction. But this isn't a ue question, this is barebones c++ implementation question.

I've thought about using my global message bus to send an event from the TriggerBox (which I also define as a subclass of Entity) to the overlapped entity.

But something tells me there should be a better more intuitive way to this.

Just to be clear. Say I've put a trigger volume/box in the world with its volume being: {xmin=0,xmax=2,ymin=0,ymax=4,zmin=-10,zmax=10}

Something like that in code:

struct Vol

{

Vec3 m_min;

Vec3 m_max;

Vol( const Vec3& min, const Vec3& max)

: m_min( min ),

m_max( max )

{}

};

class Volume // abstract class

: public Entity

{

bool m_enabled;

Vol m_volume;

RenderableEntity* m_currentActor;

RenderableEntity* m_parent;

public:

Volume( bool enabled, Vol vol )

: m_enabled{enabled},

m_volume(vol)

//…

};

class TriggerVolume

: public Volume

{

public:

TriggerVolume( Vol vol, enabled = true )

: Volume( enabled, vol )

{}

void onEnter( Actor* a );

void onExit( Actor* a );

void onHit( Projectile* a );

};

Actor is a subclass of Entity too (RenderableEntity in my engine), just to give you an idea of how I'm thinking about it.

[ I am not settled in inheriting from Entity is suitable for my non-renderable entities (eg. TriggerVolumes), maybe I'll inherit from an interface instead, but don't worry about these details now. ]

So when an actor enters the volume defined by this TriggerVolume, the latter detects the actor, runs the onEnter event function and does whatever it wants to do..

How would the TriggerVolume detect this actor? Do I run an update each frame on all my world's trigger volumes to test if any actors lie inside them? I have an Octree which can find entities given a bounding box as input. But that's what I want to potentially avoid. I'm thinking that it's kind of overkill and maybe there is a better way to go about it such that the trigger volume itself detects this specific actor that just started overlapping. Again, I'm inspired from UE4, but I've seen the trigger volume concept in every game engine I've tinkered with.

Examples:

  1. When an entity overlaps a volume the onEnter() of that volume calls the actor→damage( 15 /*hit points*/) - this is a "pain volume".
  2. Another trigger volume when the player overlaps it, it checks if this actor is the player actor and if so starts a cutscene.

etc.

Opinions and your input are very appreciated!

Thank you.

None

Advertisement

I'm new on gamedev.net.

My native language isn't English, but I believe I know decently enough to be understandable.

I hope my question makes sense.

Any thoughts and comments appreciated.

By the way code formatting looks kind of bad; can I format code better when posting on the forum?

My guess is no but ok..

None

@fleabay Thank you for confirming that there's probably no better way rather than simply calling update() on all the volumes of the world. I suppose on update then the trigger volume looks up the octree with input its own bounding volume to check if any entities overlap it, right? I can't see any better way..

None

There are a number of different solutions for this but the most common approach usually involves the physics engine and what is generally called phantom or otherwise named invisible volume which gives you a contact event when something enters the area. Basically, this uses computations and optimizations which already exist in the physics systems to do the work in a manner which is scalable. On the other hand, if you are not using a physics engine, things can get complicated depending on your goals. Doing a test against each volume and entity every loop can be expensive depending on the number of entities/volumes you intend to have. If you are talking about a hundred or less total of both entities and volumes, your simple loop is very likely all you need. But, if you scale up it will become a bottleneck in the code relatively quickly. So, if you do intend a lot of entities, you might start looking at a spatial hashing solution to minimize the number of tests you run every frame, even a simple grid is enough to reduce the costs to something manageable for hundreds or even thousands of entities.

@all8up That is right! How did I not think of that. I can just delegate this to the Physics system. That's how UE4 must be doing it! I have recently integrated Bullet Physics into my engine so yeah I think this will work fairly easily now.

None

This topic is closed to new replies.

Advertisement