Difference between revisions of "Collision Detection"
(Added another trigger method) |
|||
Line 13: | Line 13: | ||
if( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) < (r1+r2)*(r1+r2) ) | if( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) < (r1+r2)*(r1+r2) ) | ||
COLLISSION( unit I, unit J) | COLLISSION( unit I, unit J) | ||
+ | </pre> | ||
+ | |||
+ | ==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. | ||
+ | <pre> | ||
+ | // 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), | ||
+ | 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 | ||
+ | } | ||
+ | |||
</pre> | </pre> | ||
Revision as of 00:51, 3 July 2012
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), 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).
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.