Перейти к содержимому


Фотография

Передать значение в функцию, вопрос по "spawn"


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 9

#1 OFFLINE   Oubi

Oubi

    Рядовой

  • Пользователи
  • 4 сообщений

Отправлено 17 December 2018 - 20:58

Есть у меня вообщем такой код со всеми пояснениями. Вопрос. Как мне передать значение полученное с помощью param, в inline функцию? А так же... Если в функции используется приостановка (sleep 1;) и функция может вызываться +- одновременно для нескольких игроков, то верно ли использовать spawn ?

 

params [["_EditIdent",0],["_Timer",0]]; // ВХОДЯЩИЕ ПАРАМЕТРЫ ИЗ init.sqf

//CODE HERE


fnc_setTimeout = {
  			hint format ["Value: %1",_this]; // Если передаю _Timer, то _this = any. Если передаю не переменную, а само значение, то всё работает верно.
  			//CODE HERE
			sleep 1;
  			//CODE HERE
		};


//CODE HERE

		"[_Timer] spawn fnc_setTimeout;" // Значение _Timer нужно передать в функцию.

};

Сообщение отредактировал Oubi: 17 December 2018 - 21:07

  • 0

#2 OFFLINE   moroz89

moroz89

    Мл.сержант

  • Пользователи
  • 116 сообщений

Отправлено 18 December 2018 - 09:49

Либо в функции:
hint format ["Value: %1",_this # 0];

Либо передавайте:
_Timer spawn fnc_setTimeout;
  • 0

#3 OFFLINE   vlad333000

vlad333000

    Полковник

  • Пользователи
  • 3224 сообщений
  • Откуда:Кострома

Отправлено 18 December 2018 - 13:07

Oubi, во-первых, в sqf нету inline функций
во-вторых, мне абсолютно не понятно зачем вам это:
"[_Timer] spawn fnc_setTimeout;"
Для вызова функции? Тогда зачем в строке? Вызывайте прямо:
[_Timer] spawn fnc_setTimeout;
Для возврата из функции? А зачем?

Сообщение отредактировал vlad333000: 18 December 2018 - 13:07

  • 0

#4 OFFLINE   Oubi

Oubi

    Рядовой

  • Пользователи
  • 4 сообщений

Отправлено 18 December 2018 - 14:58

vlad333000, вот полный листинг. Думаю так будут более понятны мои цели) Суть скрипта - облегчить работу мишинмейкерам (создаёт ограничивающий триггер вокруг острова с заданными параметрами)
 

params [["_EditIdent",0],["_Timer",0]];

_worldSizeT = if (isNumber (configfile >> "CfgWorlds" >> worldName >> "mapSize")) then {getNumber (configfile >> "CfgWorlds" >> worldName >> "mapSize");} else {8192;};
_worldCenter = [_worldSizeT / 2,_worldSizeT / 2,0];

private ["_widthP","_heightP"];

_widthP = (_worldCenter # 0) + _EditIdent;
_heightP = (_worldCenter # 1) + _EditIdent;

_MarkerWNES=14880; //толщина маркеров по бокам


_markerW = createMarker ["ZmarkerW", [(_MarkerWNES * (-1)),_heightP]];
_markerW setMarkerShape "RECTANGLE";
_markerW setMarkerSize [_MarkerWNES,_heightP];
_markerW setMarkerBrush "DiagGrid";

_markerS = createMarker ["ZmarkerS", [_heightP,(_MarkerWNES * (-1))]];
_markerS setMarkerShape "RECTANGLE";
_markerS setMarkerSize [(_widthP + (_MarkerWNES*2)),_MarkerWNES];
_markerS setMarkerBrush "DiagGrid";

_markerN = createMarker ["ZmarkerN", [_widthP,((_heightP*2)+_MarkerWNES)]];
_markerN setMarkerShape "RECTANGLE";
_markerN setMarkerSize [(_widthP + (_MarkerWNES*2)),_MarkerWNES];
_markerN setMarkerBrush "DiagGrid";

_markerE = createMarker ["ZmarkerE", [((_heightP*2)+_MarkerWNES),_heightP]];
_markerE setMarkerShape "RECTANGLE";
_markerE setMarkerSize [_MarkerWNES,_heightP];
_markerE setMarkerBrush "DiagGrid";


_markerstr = createMarker ["mrk", _worldCenter];
_markerstr setMarkerShape "RECTANGLE";
_markerstr setMarkerSize [_widthP,_heightP];


//Функция выхода за тригер
fnc_setTimeout = {
        hint format ["Value: %1",_this];
        _TimTemp = 33;
        while {!(triggerActivated deadzone) && _TimTemp!=-1} do
            {
                    titleText [format ["<t color='#e50000' size='2'>WARNING</t><br/><t size='1.4'>Вы покидаете игровую зону, вернитесь обратно!<br/>You are leaving the game area, go back!<br/><br/><hr/></t> Time to die: %1",_TimTemp], "BLACK IN", 2, true, true];
                    sleep 1;
                    _TimTemp=(_TimTemp-1);
                if (_TimTemp==-1 && alive player) then {player setDamage 1;};
            };
    
    
};


//ОСНОВНОЙ ТРИГЕР

deadzone = createTrigger ["EmptyDetector", _worldCenter];
deadzone setTriggerArea [_widthP,_heightP, 0, true];
deadzone setTriggerActivation ["ANYPLAYER", "PRESENT", true];
if(_Timer > 0) then {
deadzone setTriggerStatements 
	[
		"this",
		"",
		"[_Timer] spawn fnc_setTimeout;"  //протестить передачу глобальной переменной
	];

} else {};






  • 0

#5 OFFLINE   moroz89

moroz89

    Мл.сержант

  • Пользователи
  • 116 сообщений

Отправлено 18 December 2018 - 16:55

Честно говоря, так и не понял в чем проблема. Вы передаете массив аргументов [_Timer] и в функции в hint тоже передаете этот массив. Хотя в любом случает все будет работать. Ну, по крайней мере, я у себя попробовал, и все работает )

 

"Если передаю _Timer, то _this = any. Если передаю не переменную, а само значение, то всё работает верно."

Проверяйте значение _Timer после этой строчки:

params [["_EditIdent",0],["_Timer",0]];

Возможно вы изначально сюда передаете не то, что нужно.


Сообщение отредактировал moroz89: 18 December 2018 - 17:04

  • 0

#6 OFFLINE   Oubi

Oubi

    Рядовой

  • Пользователи
  • 4 сообщений

Отправлено 18 December 2018 - 17:13

moroz89, проведу несколько различных тестов и результаты добавлю к этому посту, в течении часа)

UPD. 1

Дополнение 
[_Value] spawn fnc_setTimeout; - передаст как массив
_Timer spawn fnc_setTimeout; - передаст как скалярную величину

Проверки проводил используя 1 и 2 вариант поочередно.

Тест 1
 

 

Проверяйте значение _Timer после этой строчки:

params [["_EditIdent",0],["_Timer",0]];

Возможно вы изначально сюда передаете не то, что нужно.

Проверил. Скалярный тип данных, возвращает то значение, которое и передаётся (всё ок).

Тест 2
Аналогичная проверка _Timer, но уже в функции.

Провёл тесты, а после повторно прочитал документацию. Выходит что локальные переменные работают ток там где их определили, т.э. в данном случае, внутри функции они определятся и не должны.

Тест 3
Передача глобальной переменной в функцию.

Всё работает корректно, значение передается.


Исходя из всех тестов, то как мне кажется, здесь есть 2 варианата
1) Заменять params на что-то другое, поскольку оно возвращает только приватные (локальные) переменные.
2) Городить костыль globalVariable=_privateVariable и проводить действия уже с глобальной переменной (передавать её уже не нужно)

Будут еще теории?) Или рекомендации?

 

Сообщение отредактировал Oubi: 18 December 2018 - 18:17

  • 0

#7 OFFLINE   moroz89

moroz89

    Мл.сержант

  • Пользователи
  • 116 сообщений

Отправлено 18 December 2018 - 17:42

moroz89, проведу несколько различных тестов и результаты добавлю к этому посту, в течении часа)

И да, проверье передачу глобальной переменной. Может у setTriggerStatement свой scope
  • 0

#8 OFFLINE   vlad333000

vlad333000

    Полковник

  • Пользователи
  • 3224 сообщений
  • Откуда:Кострома

Отправлено 18 December 2018 - 18:26

Oubi, тогда смотрите, если значение переменной имеет базовый тип ЧИСЛО, то просто:
format ["[%1] spawn MyFunctuin", _value]
Если значение переменной имеет базовый тип СТРОКА, то:
format ["[""%1""] spawn MyFunctuin", _value]
Если массив из выше перечисленных типов, то так же как и с числом
Если любой другой тип данных, то тут нужен "финт", который предпочтителен в использовании в любой ситуации, даже в ситуация выше:
...
MyFuncition = {
  params ["_trigger", "_list"];

  private _myVariable = _trigger getVariable "MyVariable";
  ...
};
...
trigger setVariable ["MyVariable", <value>];
trigger setTriggerStatements ["this", "[thisTrigger, thisList] spawn MyFunction", ""];
...
PS Функцию лучше определить через

Пожалуйста Войдите или Зарегистрируйтесь чтобы увидеть скрытое содержание


И да, проверье передачу глобальной переменной. Может у setTriggerStatement свой scope

Никакого своего scope у него нету, триггер вызывается из missionNamespace из корня

Сообщение отредактировал vlad333000: 18 December 2018 - 18:30

  • 1

#9 OFFLINE   Oubi

Oubi

    Рядовой

  • Пользователи
  • 4 сообщений

Отправлено 18 December 2018 - 18:52

vlad333000, отдельное спасибо за Functions Library, не обращал должного внимания на это))
И вопрос по поводу setVariable, getVariable.

В чём его преимущество? Если я могу просто объявить одну глобальную переменную (Timer=_Timer) и передать её. Ведь насколько я понял, из того что описано в вики, то setVariable то же самое что и присваивание глобальной переменной.
 

missionNamespace setVariable ["YourString",3];//Same as: YourString = 3;

Повторюсь. Мне важно только быстродействие.


  • 0

#10 OFFLINE   vlad333000

vlad333000

    Полковник

  • Пользователи
  • 3224 сообщений
  • Откуда:Кострома

Отправлено 18 December 2018 - 22:32

Oubi, преимущества:
1. Явное указание пространства имен в котором нужна ваша переменная:
// init.sqf
MyVariable = 1;
// В каком-то скрипте
MyVariable; // 1
// В каком-то другом скрипте
MyVariable; // nil
Разница между скриптами в том, например, что первый был вызван из триггера, а второй из UI, где часто встречается следующая конструкция смены пространства имен:
with uiNamespace do { ... };
А использовав вместо обычного имени переменной следующую конструкцию:
missionNamespace getVariable "MyVariable";
Вы бы всегда получали нужное значение, независимо от контекста выполнения
2. По-умолчанию всегда используется missionNamespace, с помощью команды with-do, упомянутой выше, вы можете сменить пространство имен на uiNamespace, parsingNamespace или profileNamespace. Но с помощью setVariable/getVariable вы можете использовать в качестве пространства имен почти любой объект в Арме! Тем самым реализуя концепцию Объектно-ориентированного программирования:
{ _x setVariable ["MyVariable", _forEachIndex]; } forEach [unit1, unit2, unit3];
unit1 getVariable "MyVariable"; // 0
unit2 getVariable "MyVariable"; // 1
unit3 getVariable "MyVariable"; // 2
MyVariable; // nil
3. in-engine проверка на определение переменной:
MyVariable; // nil
if (isNil "MyVariable") then { 1; } else { MyVariable; }; // 1
Или просто:
missionNamespace getVariable "MyVariable"; // nil
missionNamespace getVariable ["MyVariable", 1]; // 1
4. Т. к. для указания переменной вам нужно ее название в типе STRING, то это позволяет генерировать имя переменной:
{ missionNamespace setVariable [format ["unit%1", _forEachIndex], _x]; } forEach allUnits;
Теперь каждый юнит имеет переменную ссылающуюся на него с именем unit + индекс. Хоть этот код полностью бесполезен, но попробуйте тоже самое провернуть, когда у вас 100 юнитов, без помощи setVariable... у вас банально закончится терпение на 5 или 10 юните!
Так же это позволяет использовать передачу аргументов по "ссылке". Хоть в SQF все переменные и передаются по ссылке, но из-за особенностей реализации команд модифицируются по ссылке только массивы. А иногда нужно модифицировать и другие типы данных:
MyVariable = ""; // ""
[missionNamespace, "MyVariable"] call MyFunction;
MyVariable; // "Hello world!";
// MyFunction
params ["_namespace", "_variable"];

_namespace setVariable [_variable, "Hello world!"];
5. Sharing значения переменной в сетевой игре. Часто можно увидеть следующую конструкцию:
MyVariable = 1;
publicVariable "MyVariable";
Это отправка значения переменной всем другим клиентам в сетевой игре. Но это можно сделать только для переменных в missionNamespace, в то время как с помощью setVariable это можно сделать для переменных практически в любом пространстве:
unit1 setVariable ["MyVariable", 1, true];
И через некоторое время, когда переменная будет синхронизирована, на других машинах в сети можно будет получить:
unit1 getVariable "MyVariable"; // 1
6. Обычная переменная накладывает на свое имя следующие ограничения: только латинские буквы, цифры и нижнее подчеркивание, первый символ не цифра. Имя переменной задаваемой и получаемой с помощью этих команд может быть любым:
missionNamespace setVariable ["This is my variable!", 1];
missionNamespace getVariable "This is my variable!"; // 1
This is my variable! = 1; // Error Missing ;
7. Имя переменной будет проверено на совпадение с зарезервированными именами и выведется понятное сообщение:
missionNamespace setVariable ["player", 1]; // Error Reserved variable in expression
player = 1; // На клиента: Error Generic error in expression На выделенном сервере может вообще ничего не написать
Недостатки: Он всего один - скорость:
Result:
0.0004 ms

Cycles:
10000/10000

Code:
MyVariable
Result:
0.0007 ms

Cycles:
10000/10000

Code:
missionNamespace getVariable "MyVariable"
Result:
0.0016 ms

Cycles:
10000/10000

Code:
missionNamespace getVariable ["MyVariable", 1]
Но тут стоит сказать одну вещь: доступ к локальным переменным значительно быстрее доступа к глобальным переменным:
Result:
0.0003 ms

Cycles:
10000/10000

Code:
_myVariable
Из чего вытекает следующее:
Result:
0.0549 ms

Cycles:
10000/10000

Code:
for "_i" from 0 to 99 do { MyVariable; }
Result:
0.044 ms

Cycles:
10000/10000

Code:
private _MyVariable = missionNamespace getVariable ["MyVariable", 1]; for "_i" from 0 to 99 do { _MyVariable; }

Сообщение отредактировал vlad333000: 18 December 2018 - 22:59

  • 1




Яндекс.Метрика