Collision Detection

Revision as of 12:50, 4 December 2015 by LenSe (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Collision Detection is a technique to decide when two objects (in SC2 most propably units) occupy the same space, which can be used for example by physics engines. There are several methods, if you know any other, please add it here.

Simple trigger method

This method simply compares all units to each other and calculates their distances. Works fine for ~200 units (no FPS drop on 4 cores, 2.8 MHz).

lv_unitGroup = (All units); //group of units tested for collision between each other

//we go through all units and compare them to all units with higher ID in group (if we compared each unit to each other, we would calculate each PAIR twice)
for( I from 0 tp (Count units in lv_unitGroup)-1 )
    for (J from I+1 to (Count units in lv_unitGroup) )
        x1, y1 = X and Y of (position of (unit I from lv_unitGroup ))
        x2, y2 = X and Y of (position of (unit J from lv_unitGroup ))
        // r1, r2 are radiuses of the two units
        if( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) < (r1+r2)*(r1+r2) )
                COLLISSION( unit I, unit J)

Other trigger method

Assuming that a unit can collide with another one only when it is moving, you can also check the presence of a unit just in front of each unit. Needs to be tested for performance, but should be a bit more efficient than the previous one.

// Get the group of unit in the region circle of 0.3 radius offset by 1.0 of the position of the unit in direction of that unit
closeUnits = UnitGroup(null, c_playerAny,
    RegionCircle(PointWithOffsetPolar(UnitGetPosition(unit), 1.0, UnitGetFacing(unit)), 0.3),
    UnitFilter(0, 0, 0, 0),
if (closeUnits != null && UnitGroupCount(closeUnits, c_unitCountAll) > 0) {
    // There is one unit (the region is too small to contain more than one unit) in front of the unit you are testing

Data editor method

Other, much faster method is using in-built search effects. They are faster then the trigger method, because the engine already contains some optimalization. Basically what you need to do is create a buff that periodically launches a search effect. The search effect will have a radius of 0, "Extend by unit radius" and launches a dummy damage effect. The dummy effect is then hooked onto a trigger. This will create an universal buff that can be applied to any unit, to include it into collision detection. This method works fine for ~500 units (no FPS drop on 4 cores, 2.8 MHz).

Alternative Data editor method using projectiles

This method utilizes "dumb-fire" projectiles that travel in a straight line, rather than being locked onto a target upon launch. At the same time, a "Create Persistent" effect periodically launches "Search Area" effects at the projectile's location.
When a valid target is found, a "Destroy Persistent" effect is created to remove the previously created "Create Persistent" effect, therefore ending the search.
Optionally, a "Set" effect can be used to also cause a "Damage" type effect on whatever unit was found in the search.

Advanced trigger method

To improve performace of the trigger method, the map can be divided into multiple squares (a 10x10 grid for example). The units will then be assigned to according units groups, and only need to be checked against units from adjacent squares.

Absolutely best method

The fastest method possible would be hooking onto the already present collision detector, that the game engine uses, as that would add zero CPU load.

Needs research: So far there is no way on how to do that.