cklymowsky 1 Posted March 30, 2018 With additional units on the field the FPS starts to drop. I would like to have the script only calculate the _distance every second instead of on every frame to see how much it improves FBS. Any ideas? I have tried the following with no luck private ["_randomSectorDestination","_revealTime","_enemyArray","_addNew"]; _enemyArray = []; _distance = 0; _displayName = ""; _picture = ""; _icon = ""; _revealTime = 30; _run = missionNamespace setVariable ["Intel",0]; _timer = missionNamespace setVariable ["Timer",time]; fn_Draw3DNEW = { _enemyArray = []; _distance = 0; _displayName = ""; _picture = ""; _icon = ""; _run = missionNamespace getVariable ["Intel",0]; _timer = missionNamespace getVariable ["Timer",0]; {if (((side _x) == AIside) && (isFormationLeader _x)) then {_enemyArray pushBack _x}} forEach allUnits+vehicles+allUnitsUAV; { _text = ""; if ( floor(time-_timer) == _run ) then { _run = missionNamespace setVariable ["Intel",_run + 5]; private ["_private", "_displayName", "_picture", "_icon", "_text", "_distance", "_leaderDestination","_enemyArray"]; if (vehicle _x != _x) then {_x = vehicle _x}; _distance = round (_x distance player); _displayName = getText (configfile >> "CfgVehicles" >> typeOf _x >> "displayName"); }; _text = str(parseText format["%1 men %2m",count units group _x, (str _distance)]); _icon = ""; if ( (_x isKindOf "LandVehicle") or (_x isKindOf "Air") or (_x isKindOf "Ship") ) then { _picture = getText (configfile >> "CfgVehicles" >> typeOf _x >> "picture"); } else { _icon = getText (configFile >> "CfgVehicles" >> typeOf _x >> "Icon"); _picture = getText (configFile >> "CfgVehicleIcons" >> _icon); }; drawIcon3D [ _picture, [1,0,0,1], [(visiblePosition _x) select 0,(visiblePosition _x) select 1,((visiblePosition _x) select 2) + 10], 0.8, 0.5, 0, _text, 0, 0.03, "PuristaMedium" ]; player reveal [_x, 4]; {[_x, 1] showWaypoint "ALWAYS" } forEach allGroups; } forEach _enemyArray; hint format ["_run: %1 \n floor(time-_timer): %2 \n floor(time-_timer) == _run: %3", _run, floor(time-_timer), floor(time-_timer) == _run]; }; _addNew = ["BIS_idNEW", "onEachFrame", "fn_Draw3DNEW"] call BIS_fnc_addStackedEventHandler; sleep (_revealTime); ["BIS_idNEW", "onEachFrame", "fn_Draw3DNEW"] call BIS_fnc_removeStackedEventHandler; _run = missionNamespace setVariable ["Intel",nil]; _timer = missionNamespace setVariable ["Intel",nil]; thanks in advance... Share this post Link to post Share on other sites
whiztler 137 Posted March 30, 2018 Well if you did not copy this from somewhere else then you know how to script and should be able to turn this into a per second cycle easily. Few notes though: Script could do with some optimizing. Note that 'reveal' on each frame and even every second is quite expensive. No sure why you are declaring variables at the beginning of the script as they are not used elsewhere What is 'AIside'? Not declared anywhere unless it is a new BIS function I am un aware off Share this post Link to post Share on other sites
mrcurry 496 Posted March 30, 2018 My practice when working with onEachFrame and similar is to move the data crunching into a separate scripted loop (like a while do for instance) and I let the onEachFrame code read from a common data set all required parameters. It sacrifices a bit of memory but doesn't clog up the unscheduled code with expensive operations. It also gives easy control over the update rate through sleep and waitUntil etc. 1 Share this post Link to post Share on other sites
gc8 977 Posted March 30, 2018 (edited) Since you are calling drawIcon3D the code should go to "Draw3D" event handler instead. _drawEvent = addMissionEventHandler ["Draw3D", { // drawIcon3D code here } ]; sleep (_revealTime); removeMissionEventHandler ["Draw3D", _drawEvent]; But I'm not sure can you use BIS_fnc_addStackedEventHandler to make new Draw3D events. The above code should however be all you need. As for performance you should create separate loop that handles the units. putting it all in eachframe loop will indeed take a lot from the CPU . Edited March 30, 2018 by gc8 Added some more code Share this post Link to post Share on other sites
cklymowsky 1 Posted March 30, 2018 Hi All, I went with the following changes and it does improve FPS. Let me know if you see any other improvements. Thanks in advance. Quote private ["_revealTime","_addNew","_enemyArray","_displayName", "_picture", "_icon", "_text", "_distance"]; _revealTime = 60; _enemyArray = []; _distance = 0; _displayName = ""; _picture = ""; _icon = ""; _timer = time; _text = ""; enemyArray = []; while {floor(time -_timer) <= _revealTime} do { _enemyArray = []; {if ((((side _x) == AIside) && (isFormationLeader _x)) or (((side _x) == AIside) && (vehicle _x != _x))) then {_enemyArray pushBackUnique (vehicle _x)}} forEach allUnits; enemyArray = []; { //if (vehicle _x != _x) then {_x = vehicle _x}; _distance = round (_x distance player); _displayName = getText (configfile >> "CfgVehicles" >> typeOf _x >> "displayName"); _text = str(parseText format["%1 men %2m",count units group _x, (str _distance)]); if ( (_x isKindOf "LandVehicle") or (_x isKindOf "Air") or (_x isKindOf "Ship") ) then { _picture = getText (configfile >> "CfgVehicles" >> typeOf _x >> "picture"); _text = str(parseText format["%1m",(str _distance)]); } else { _icon = getText (configFile >> "CfgVehicles" >> typeOf _x >> "Icon"); _picture = getText (configFile >> "CfgVehicleIcons" >> _icon); }; player reveal [_x, 4]; enemyArray pushBack [_x,_picture,_text]; sleep 0.05; } forEach _enemyArray; sleep 0.5; _addNew = ["BIS_idNEW", "onEachFrame", { _unit = objNull; _picture = ""; _text = ""; _enemyArray = _this select 0; { _unit = _x select 0; _picture = _x select 1; _text = _x select 2; drawIcon3D [ _picture, [1,0,0,1], [(visiblePosition _unit) select 0,(visiblePosition _unit) select 1,((visiblePosition _unit) select 2) + 10], 0.8, 0.5, 0, _text, 0, 0.03, "PuristaMedium" ]; } forEach (_enemyArray); }, [enemyArray]] call BIS_fnc_addStackedEventHandler; }; ["BIS_idNEW", "onEachFrame"] call BIS_fnc_removeStackedEventHandler; Share this post Link to post Share on other sites
HallyG 239 Posted March 30, 2018 Try changing: [(visiblePosition _unit) select 0,(visiblePosition _unit) select 1,((visiblePosition _unit) select 2) + 10] to (visiblePosition _unit) vectorAdd [0,0,10] Then, _enemyArray = []; {if ((((side _x) == AIside) && (isFormationLeader _x)) or (((side _x) == AIside) && (vehicle _x != _x))) then {_enemyArray pushBackUnique (vehicle _x)}} forEach allUnits; to (using the select command) _enemyArray = allUnits select {((side _x isEqualTo AIside) && (isFormationLeader _x)) or ((side _x isEqualTo AIside) && (vehicle _x != _x))} apply {vehicle _x}; Additionally you are using str when format already returns a string. parseText parses structured text which the strings used do not contain (therefore it's not required): _text = str(parseText format["%1m",(str _distance)]); to _text = format ["%1m", _distance]; Additionally, you are using pushBack when you could use the apply command: Spoiler From: enemyArray = []; { //if (vehicle _x != _x) then {_x = vehicle _x}; _distance = round (_x distance player); _displayName = getText (configfile >> "CfgVehicles" >> typeOf _x >> "displayName"); _text = str(parseText format["%1 men %2m",count units group _x, (str _distance)]); if ( (_x isKindOf "LandVehicle") or (_x isKindOf "Air") or (_x isKindOf "Ship") ) then { _picture = getText (configfile >> "CfgVehicles" >> typeOf _x >> "picture"); _text = str(parseText format["%1m",(str _distance)]); } else { _icon = getText (configFile >> "CfgVehicles" >> typeOf _x >> "Icon"); _picture = getText (configFile >> "CfgVehicleIcons" >> _icon); }; player reveal [_x, 4]; enemyArray pushBack [_x,_picture,_text]; sleep 0.05; } forEach _enemyArray; to: enemyArray = _enemyArray apply { _distance = round (_x distance player); _displayName = getText (configFile >> "CfgVehicles" >> typeOf _x >> "displayName"); _text = format ["%1 men %2m", count units group _x, _distance]; if ((_x isKindOf "LandVehicle") or (_x isKindOf "Air") or (_x isKindOf "Ship")) then { _picture = getText (configFile >> "CfgVehicles" >> typeOf _x >> "picture"); _text = format ["%1m", _distance]; } else { _icon = getText (configFile >> "CfgVehicles" >> typeOf _x >> "Icon"); _picture = getText (configFile >> "CfgVehicleIcons" >> _icon); }; player reveal [_x, 4]; sleep 0.05; [_x,_picture,_text] }; 1 Share this post Link to post Share on other sites
Dedmen 2703 Posted April 11, 2018 https://community.bistudio.com/wiki/Code_Optimisation Here is a wiki page with lots of common optimizations. But remember to always think about what you are doing. shortening your variable names from _veryDescriptiveVariableName to _v1 might give you a 0.0001ms performance improvement. But readability is more important if you ever wanna touch your code again. Share this post Link to post Share on other sites
Grumpy Old Man 3545 Posted April 11, 2018 On 3/30/2018 at 8:32 AM, whiztler said: Well if you did not copy this from somewhere else then you know how to script and should be able to turn this into a per second cycle easily. Few notes though: Script could do with some optimizing. Note that 'reveal' on each frame and even every second is quite expensive. No sure why you are declaring variables at the beginning of the script as they are not used elsewhere What is 'AIside'? Not declared anywhere unless it is a new BIS function I am un aware off Any numbers on your reveal assumption? Revealing 100 units to the player takes around 0.0823ms, since one frame takes 16.6667ms to run at 60fps there's plenty of overhead. Same goes for "player distance [0,0,0]" which only takes 0.0008ms. @cklymowsky: Optimization is only needed if you notice an fps drop. Try running the mission without the script, if the fps still drops it's most likely not the script. To get more performance out of your script it's good practice to look at each single command used and find possible faster alternatives. You are already using sleep 0.05 in the forEach loop, which equals 50ms my guess is that the draw event is slowing things down. From the looks of it you always add a stacked eventhandler every 0.5s for every unit inside the enemyArray, since both _enemyArray and enemyArray reset to [] at beginning of the while loop. You need to check if the units are already being handled by the onEachFrame either with making sure the enemyArray doesn't reset every iteration or by using setVariable/getVariable. Cheers Share this post Link to post Share on other sites