Jump to content
Leopard20

[Code Performance] Adding Hold Actions to individual units vs adding one to player

Recommended Posts

Hi guys.

 

I want to create a healing script using Hold Actions. I was wondering which method is best performance-wise.
1. Adding the hold actions to all individual units, with a straightforward conditionShow (see the Hold actions description):

"alive _target && _target distance _this < 5 && getDammage _target > 0"

in the above code, _target is the unit the action is attached to and _this is the caller (i.e player).

Also, the action is removed every time it's added, so it might be applied to each unit multiple times during a game session.

This code is simple if added to just one unit. However, there will be too many of these if there are lots of units (I'm aiming for +60!).

 

2. Adding only one action and to the player, but modifying the conditionShow as follows:

"call {_units = applicableUnits select {alive _x && _x distance _target < 5 && ([visiblePosition _target, getDir _target, 60, visiblePosition _x] call BIS_fnc_inAngleSector) && (getDammage _x > 0)}; if (count _units > 0) then {_unit = _units select 0; _target setVariable ['target', _unit]; true} else {false}}"

in the above code, _target is the same as the caller (i.e player), and applicableUnits is an array of applicable units! The reason for adding the "target" variable is here:

This code is obviously more demanding, especially if it's run on each frame (which I'm assuming it is).

 

 

 

Share this post


Link to post
Share on other sites

Unless you're running into performance issues and removing your scripts solves those issues, I wouldn't worry about it.

Usually having one check for the player unit is preferable vs. adding actions to all units.

 

alive _target && _target distance _this < 5 && getDammage _target > 0;//0.0022ms when returning false
  

_target = test;
_return = false;
_units = allUnits select {alive _x && _x distance _target < 5 && ([visiblePosition _target, getDir _target, 60, visiblePosition _x] call BIS_fnc_inAngleSector) && (getDammage _x > 0)};
if (count _units > 0) then {_unit = _units select 0;
	_target setVariable ['target', _unit];
	_return = true
} else {
	_return =false
};
_return
//0.002ms when returning false

 

Cheers

  • Like 2

Share this post


Link to post
Share on other sites

Adding actions to all units is better. As the condition code should only be checked for the unit that you are looking at. Which will either be 1 or 0.
If you add the action to yourself. The condition will always be checked. So on average that would be more checks.

Of course I'm expecting here that BI didn't fuck this up beyond repair and does not check every actions condition every time.

addAction for example only checks the condition of the thing you are looking at. So what I said applies to that. I haven't checked hold actions myself, but if the guy who wrote the code is not an idiot, it will work like that.

 

alive _target && _target distance _this < 5 && getDammage _target

You can optimize that to

alive _target && {_target distance _this < 5} && {getDammage _target}

That way the next conditions aren't actually evaluated once one of them doesn't match.

 

The code from @Grumpy Old Man is very suboptimal. As it filters through ALL Units. Although you only want the first one. So even if you found the first, it will keep iterating through all others and then throw away the results. With hundreds of units on the map that will kill your performance if you do this in unscheduled.

Here is a better variant

private _target = test;
private _units = allUnits;
private _found = _units findIf {alive _x && {getDammage _x > 0} && {_x distance _target < 5} && {[visiblePosition _target, getDir _target, 60, visiblePosition _x] call BIS_fnc_inAngleSector}};
//Notice that I also reordered getDammage to the front. The cheaper, or more likely to be false, check should be placed sooner in the condition if you use lazy-eval.
                
if (_found == -1) exitWith {false};

_target setVariable ["target", _units select _found];
true

 

You can optimize this slightly more by using
condition1 && {cond2 && {cond3 && {cond4}}} instead of cond1 && {cond2} && {cond3} && {cond4}

 

I don't quite get your 2nd method. Why are you checking if the target is facing towards whatever unit?
The code has very different effect compared to your first method.

  • Like 2

Share this post


Link to post
Share on other sites

@Dedmen Right! "Lazy-checking" the condition using { } (at least that's what Larrow called it!)! I totally forgot! Thanks!

 

The reason for checking that the target (player) is facing the wounded unit is to make sure that the action correctly corresponds to the unit you're looking at, not any random unit in your vicinity.

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

×