CollisionProperty

From Valve Developer Community
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Underlinked - Logo.png
This article needs more Wikipedia icon links to other articles to help Wikipedia icon integrate it into the encyclopedia. Please help improve this article by adding links Wikipedia icon that are relevant to the context within the existing text.
January 2024

All entities that are collideable have a CollisionProperty. There's an accessor in CBaseEntity called CollisionProp() that lets you access/interact with collision functionality. Here is an overview of some of the functionality contained in the collision property:

Entities that use VPhysics also have a IPhysicsObject which provides additional collision properties related to vphysics simulation.

For the entity's motion, the collision property's solid type (CollisionProp()->SetSolid()) determines what type of collision primitive to use for tests.

There is also unsigned int CBaseEntity::PhysicsSolidMaskForEntity( void ) const which determines what types of contents are solid for the entity. Most things are CONTENTS_SOLID, but there are a set of flags (mostly used by the BSP compiler) that can specialize contents to be filtered by certain traces or movement types. An example of this is CONTENTS_GRATE which is applied to brushes textured with textures that should be solid for movement, but not for bullets or line of sight tests.

Otherwise CBaseEntity::m_CollisionGroup determines which other entities will collide with this one. The rules for which collision groups collide are in CGameRules::ShouldCollide() and can be customized to suit the needs of a particular mod.

Surrounding bounds

Surrounding bounds are used as a coarse test for many queries like collision and visibility.

For example, ray/box traces are first checked against the collision property's surrounding bounds to determine whether to then check for intersections with hitboxes on players. So a player's surrounding bounds need to be configured so that they always enclose any hitboxes that should be checked.

By default the surrounding bounds are computed as a box that surrounds the collision hull. If the collision hull is smaller than the hitboxes, the surrounding bounds must be enlarged to guarantee a proper hitbox test. It can be customized by calling:

CollisionProp()->SetSurroundingBoundsType( USE_GAME_CODE );

The parameter can be any of these:

enum SurroundingBoundsType_t
{
	USE_OBB_COLLISION_BOUNDS = 0,
	USE_BEST_COLLISION_BOUNDS,		// Always use the best bounds (most expensive)
	USE_HITBOXES,
	USE_SPECIFIED_BOUNDS,
	USE_GAME_CODE,
	USE_ROTATION_EXPANDED_BOUNDS,
	USE_COLLISION_BOUNDS_NEVER_VPHYSICS,

	SURROUNDING_TYPE_BIT_COUNT = 3
};

USE_HITBOXES will simply transform all hitboxes and build a surrounding box around those. This can be expensive to do every frame (players generally move every frame), but may be the simplest way to solve any hitbox problems.

USE_GAME_CODE lets a programmer customize the bounds as needed by calling a virtual defined in the entity's class:

virtual void			ComputeWorldSpaceSurroundingBox( Vector *pWorldMins, Vector *pWorldMaxs );

USE_SPECIFIED_BOUNDS could also be used to solve this problem by specifying a constant box that is always larger than the space occupied by hitboxes in any animation. As a trade off, this will be cheaper than USE_HITBOXES as the player animates and moves, but more a conservative boundary resulting in more hitbox queries happening against ray tests that miss. The highest performance method will depend on the mod's number of players moving vs. number of ray/box traces computed against players (and how many of those queries actually miss).