Jump to content
hansen111

Position Algorithm ArmA3

Recommended Posts

Hello all

So im writing a function (grid system) to avoid overhead on a algorithm that checks if players are in certain areas, the question is:

Do the standard triggers/modules support this already or do they just iterate through all players with something like _unit distance _center on a defined interval?

If its the ladder then using the already supported mapGridPosition function would greatly reduce overhead:

//INIT GRID FOR MONITORING
_gridCenter = [_gridX,_gridY];
_gridID = "mygrid_" + _gridNum + (mapGridPosition _gridCenter);
missionNameSpace setVariable [_gridID, true];

//CHECKING IF PLAYER IS IN GRID
_gridID = "mygrid_" + _gridNum + (mapGridPosition player);
Method 1:
if(isNil _gridID) then {hint "player IS NOT in grid"};
Method 2:
if(missionNameSpace getVariable [_gridID, false]) then {hint "player IS in grid"};

So the question becomes: what is the speed comparison between 

_unit distance _center <= _radius

and

isNil ("mygrid_" + mapGridPosition player) ?  

 

I guess i will run some simulations on this.

 

Thoughts?

 

Thanks in advance.

Share this post


Link to post
Share on other sites
9 minutes ago, stanhope said:

Sure or some other stock function module we already have in the wiki, the important thing is if the grid system can greatly outperform those stock functions/modules.

 

I did some testing and so far it seems the standard distance function is highly optimized, on 7 million iterations on my system there is only 4.5 seconds gained by using:

isNil "somevar"

instead of using

player distance _pos <= _radius

!?

That is super surprising to me. Why would checking if a varibale isNil take almost as long as a full distance check!? I will test further..

Share this post


Link to post
Share on other sites

Incomprehensible...  mapGridPosition is just a way to modify the format of position. So, at what time  if (isNil yourGridposition ) could be useful to detect a "in grid ??" stuff?

 

 

Share this post


Link to post
Share on other sites

Ok, so I will illustrate this better, here is the situation for a case:

https://steamcommunity.com/sharedfiles/filedetails/?id=2301831648

 

We have 7 zones, we want to check 1 time a second what players are in these zones. Now I know of all the modules and functions in the wiki ect. that does this but we can do a lot better performance wise, or at least i think so :-) by using the grid system, I will explain why:

So the normal routine to check if someone (or something) is in a certain  area is by doing a function, module, trigger that uses distance checks in a certain time period in a certain area, like 1 time a second for this example, we have to do this for each zone, so 7 triggers if we use those.  BIS have made a great article explaining the performance of different functions here:

https://community.bistudio.com/wiki/Code_Optimisation

In there we can see:

// with a 30 items array
_someoneIsNear = (allUnits findIf { _x  distance [0,0,0] < 1000 }) != -1;		// 0.0275 ms
_someoneIsNear = { _x distance [0,0,0] < 1000 } count allUnits > 0;				// 0.0645 ms
_someoneIsNear = {
	if (_x distance [0,0,0] < 1000) exitWith { true };
	false
} forEach allUnits;																// 0.0390 ms

that it would take 0.0275 ms to do 30 distance checks (30 soldiers). This is for 1 zone, we have 7, so it would be for each check:  0.0275 * 7 = 0,1925 ms

 

In the grid system we would not need to do 7 distance checks, we need to do 7 isNil checks og 1 call to the mapGridPosition function, but only 1:

_mapgrid = mapGridPosition player;
{
	if(isNil ("mygrid_" + _x + _mapgrid)) then {hint "not in zone"};
} forEach _zones;

Remember we ran a short init code before the mission begins that sets the zone variables, this is done only 1 time in init:

//INIT GRID FOR MONITORING
_gridCenter = [_gridX,_gridY];
_gridID = "mygrid_" + _gridnum + (mapGridPosition _gridCenter);
missionNameSpace setVariable [_gridID, true];

On the BIS optimisation link above you can read the time 1 isNil check takes:

isNil "varName"; // 0.0007 ms

 

So we have reduced a 7 time distance check (0.0275 * 7 = 0,1925 ms) to a 7 time isNil check (0.0007 ms * 7 = 0,0049 ms). The grid system is 275 times faster! - from that we have to deduct the time that 1 call to the mapGridPosition takes so its a bit slower but still a fantastic optimisation! 

 

Share this post


Link to post
Share on other sites

_gridID = mapGridPosition player;

this function always return a string. So, _gridID is a string  , isNil _gridID will be always false in your code.

 

{ if(isNil _gridID) then {hint "not in zone"}; } forEach _zones  // no sense.

 

Triggers with anyPlayer are fine. If the 0.5 sec check seems to be too quick for you just script them with setTriggerInterval   With trigger you know what trigger (so what area) is activated (cherry on the cake imho).

If you want to know if a trigger is activated, no matter which, just waituntil {sleep 1; [trg1,trg2,tr3...] findIf {triggerActivated _x} > -1};

 

You are using markers, not triggers, or even scripted areas?

waitUntil {sleep1; { ["mk1","mk2","mk3"] findIf {!(allPlayers inAreaArray _x isEqualTo [])} > -1 };

 

in Polygons ?

 

 

 

 

Share this post


Link to post
Share on other sites

It was mostly pseudo code to prove the system, I have now edited it so it would actually run, but you have to understand the system here instead of typos.

The facts remain, the grid system on 7 zone case on 30 soldiers is 275 times faster (minus 1 call to  the mapGridPosition function which I cant find a ms time on).

Again the whole difference is that you dont have to do 7 distance checks but 7 isNil checks (+ 1  mapGridPosition call)  

 

Edit:

And oh btw, yes im using grids. If you want to know if someone is in the circle area you have to run distance checks on those that is in the main grid, its still very few distance checks compared to running only triggers.

Edited by hansen111
forgot something

Share this post


Link to post
Share on other sites

Haven't tried your method @hansen111 but if it's 250+ times faster than inArea, that sounds yummy. One thing with triggers though is you can also use thisList with triggers, which returns all objects in the trigger that can trigger it, if any. So if player is in the trigger, thisList will equal [player] if the trigger is set to "ANYPLAYER". That method has been fastest for me, but I'm all about optimization so who knows. Maybe you're onto something. I find a lot of stuff on the wiki to be situationally correct or inaccurate sometimes. Trial and error through experimentation and do what works for you!

Share this post


Link to post
Share on other sites
1 hour ago, hansen111 said:

It was mostly pseudo code to prove the system, I have now edited it so it would actually run, but you have to understand the system here instead of typos.

The facts remain, the grid system on 7 zone case on 30 soldiers is 275 times faster (minus 1 call to  the mapGridPosition function which I cant find a ms time on).

Again the whole difference is that you dont have to do 7 distance checks but 7 isNil checks (+ 1  mapGridPosition call)  

 

Edit:

And oh btw, yes im using grids. If you want to know if someone is in the circle area you have to run distance checks on those that is in the main grid, its still very few distance checks compared to running only triggers.

 

This is not a  "typo" remark. Your "pseudo" code runs fast because, as is, it has no interest at all... the result is immediate: isNil (mapgridPosition whatEverObject) returns false at once.

You should explain your "grid system". At this time, the simple use of mapGridPosition has no sense and most of readers can't understand how to you manage your areas, the distances, the radius... and all geometric things you don't mention here.

Now, if you're attempting to work with the dynamic simulation grid or something like this, you should explain a little bit.

Share this post


Link to post
Share on other sites
2 hours ago, phronk said:

Haven't tried your method @hansen111 but if it's 250+ times faster than inArea, that sounds yummy. One thing with triggers though is you can also use thisList with triggers, which returns all objects in the trigger that can trigger it, if any. So if player is in the trigger, thisList will equal [player] if the trigger is set to "ANYPLAYER". That method has been fastest for me, but I'm all about optimization so who knows. Maybe you're onto something. I find a lot of stuff on the wiki to be situationally correct or inaccurate sometimes. Trial and error through experimentation and do what works for you!

 

Yup, when im actually coding the system im going to have a routine putting players in arrays so its easy to use, it would be something like this (Not tested but you get the idea). 

//INIT
_zoneNumbers = [0,1,2,3,4,5,6];
_gridZonePlayers = [];
{_gridZonePlayers pushBack []} forEach _zoneNumbers;
//ROUTINE
{
	_player = _x;
	_mapgrid = mapGridPosition _player;
	{ 
		_zonenumber = _x;
		if(!isNil ("mygrid_" + str _zonenumber + _mapgrid)) exitWith {
			_playersInZone = _gridZonePlayers select _zonenumber;  
			_playersInZone pushBack _player;
		};
	} forEach _zoneNumbers;
} forEach Allplayers;
//To get the array of players in the zone 1;
_zoneOnePlayers = _gridZonePlayers select 1;

Edit:

And btw if someone is wondering about grid sizes, radius ect then this system is based of the standard arma grid that the mapGridPosition function returns, a grid is 100m X 100m, every position in that grid translates to the same unique grid id which the mapGridPosition function returns when inputting the position. This system does NO distance checks but uses only mapGridPosition hence its much faster.

If you need a circle distance check then you need to do normal distance checks but only for the few players inside the corresponding grid and not all players, again optimizing the method compared to only triggers.

Edited by hansen111

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×