Спецификаторы параметров функций
Выражения
Присваивание
Чтобы присвоить значение переменной, используйте оператор "=" следующим образом:
function Test()
{
local int i;
local string s;
local vector v, q;
i = 10; // Assign a value to integer variable i.
s = "Hello!"; // Assign a value to string variable s.
v = q; // Copy value of vector q to v.
}
В языке UnrealScript, когда функция или другое выражение, требуют определенный тип данных (например, "float"), а вы указываете другой тип данных (например, "int"), компилятор будет пытаться автоматически привести значение к соответствующему типу. Преобразования между всеми числовыми типами данных (byte, int и float) происходит автоматически, без каких-либо усилий с вашей стороны.
UnrealScript также может конвертировать многие другие встроенные типы данных в другие типы, если вы явно указываете их преобразование преобразовать в коде. Синтаксис для явного преобразования следующий:
function Test()
{
local int i;
local string s;
local vector v, q;
local rotator r;
s = string(i); // Convert integer i to a string, and assign it to s.
s = string(v); // Convert vector v to a string, and assign it to s.
v = q + vector(r); // Convert rotator r to a vector, and add q.
}
Ниже приведен полный набор типов, для которых в языке UnrealScript можно использовать не автоматическое явное преобразование:
- String в Byte, Int, Float: Осуществляется попытка преобразовать строку вида "123" в значение 123. Если строка не является текстовым представлением числа, то результатом будет 0.
- Byte, Int, Float, Vector, Rotator в String: Число преобразуется в текстовое представление.
- String в Vector, Rotator: Осуществляется попытка преобразовать содержимое строки в значения элементов вектора или ротатора, соответственно.
- String в Bool: Преобразует строки "True" и "False" (без учета регистра) в значения True и False, соответственно; преобразует любое ненулевое значение строки в True, а если строка пуста, то в False.
- Bool в String: результатом будет строковое значение "True" или "False".
- Byte, Int, Float, Vector, Rotator в Bool: Преобразует ненулевое значение в True, а нулевое в False.
- Bool в Byte, Int, Float: Преобразует True а 1, а False в 0.
- Name в String: Преобразует имя в соответствующий текстовый эквивалент.
- Rotator в Vector: Возвращает вектор "вперед" в соответствии со значением ротатора.
- Vector в Rotator: Возвращает ротатор с компонентами Pitching и Yaw, указывающими в направление вектора, для Roll присваивается 0.
- Object (или Actor) в Int: Возвращает целое число, гарантированно уникальное для этого объекта.
- Object (или Actor) в Bool: Возвращает False если ссылка на объект равна None или True для ссылки на существующий объект.
- Object (или Actor) в String: Возвращает текстовое представление объекта.
Преобразование ссылок на объекты и классы
Подобно функциям преобразования между различными типами данных, в языке UnrealScript есть возможность преобразования типов ссылок на объекты и акторы. например, у вас есть переменная, названная "Target", являющаяся ссылкой на актор. Скажем, вы пишете сценарий, где вам необходимо проверить, принадлежит ли актор, представленный ссылкой Target, классу "Pawn", а если принадлежит, то осуществить последовательность необходимых вам операций, имеющих смысл только для класса Pawn, например, вызвать определенную функцию. Это можно сделать путем применения операторов преобразования.
var actor Target;
//...
function TestActorConversions()
{
local Pawn P;
// Cast Target to Pawn and assign the result to P. If Target is not a Pawn (or subclass of Pawn), then the value assigned to P will be None.
P = Pawn(Target);
if( P != None )
{
// Target is a pawn, so set its Enemy to Self.
P.Enemy = Self;
}
else
{
// Target is not a pawn.
}
}
Для выполнения преобразования типа актора введите имя класса, в который необходимо преобразовать ссылку,а в скобках укажите имя переменной, ссылающейся на иходный тип актора. Результат преобразования зависит от возможности выполнения преобразования. В приведенном выше примере, если Target ссылается объект Trigger, а не Pawn, выражение Pawn(Target) вернет "None", так как Trigger не может быть преобразован в Pawn. Однако, если ваша цель ссылается объект Brute, преобразование успешно вернет Brute, потому что Brute наследует класс Pawn.
Таким образом, преобразование типов акторов имеет две цели: во-первых, вы можете использовать для проверки объекта на принадлежность определенному классу. Во-вторых, вы можете использовать его для преобразования ссылки на актор из одного класса в другой. Обратите внимание, что это преобразование не влияет на актор и не меняет класс актора, а просто приводить ссылку на актор к конкретному типу, позволяя получить доступ к свойствам и методам, объявленным для типа, к которому осуществляется приведение, например к свойствам и методам производного класса.
Другой пример преобразования находится в сценарий Inventory. Каждый актор сценария Inventory принадлежит к классу Pawn, даже если его переменная Owner ссылается на любой другой актор (Actor.Owner - это переменная типа Actor). Таким образом, общей темой в коде Inventory является приведение типа Owner к типу Pawn, например:
// Called by engine when destroyed.
function Destroyed()
{
// Remove from owner's inventory.
if( Pawn(Owner)!=None )
Pawn(Owner).DeleteInventory( Self );
}
Функции
Объявление функций
В языке UnrealScript вы можете объявлять новые функции и писать новые версии уже существующих (переписывать функции). Функции могут принимать один или несколько параметров (UnrealScript поддерживает переменные любых типов) и, опционально, могут возвращать значение. Хотя большинство функций пишутся непосредственно в UnrealScript, вы также можете объявлять функции, которые могут быть вызваны из UnrealScript, но реализованы на C++ и находятся в DLL. Технология Unreal поддерживает все возможные комбинации вызовов функций: из кода движка на C++ можно вызывать функции сценариев; из сценариев можно вызывать функций, реализованные на C++, и, естественно, из сценариев можно вызывать функции, реализованные в сценариях.
Ниже приведен пример определения простой функции. Эта функция в качестве параметра принимает вектор и возвращает число с плавающей точкой:
// Function to compute the size of a vector.
function float VectorSize( vector V )
{
return sqrt( V.X * V.X + V.Y * V.Y + V.Z * V.Z );
}
Объявление функции всегда начинается с ключевого слова function. За ним следуют тип возвращаемого значения функции (в данном случае float), имя функции, а затем список параметров функции в круглых скобках.
При вызове функции выполняется код, находящийся между фигурными скобками. Внутри функции можно объявлять локальные переменные (с использованием ключевого слова local) и разместить любой код UnrealScript. Необязательное ключевое слово return заставляет функцию немедленно вернуть значение.
В функции вы можете передавать любые типы UnrealScript (в том числе массивы), а функция может возвращать результат любого типа.
По умолчанию, любые локальные переменные, объявляемые в пределах функции, инициализируются нулем.
Вызов функции может быть рекурсивным. Например, следующая функция вычисляет факториал числа:
// Function to compute the factorial of a number.
function int Factorial( int Number )
{
if( Number <= 0 )
return 1;
else
return Number * Factorial( Number - 1 );
}
Некоторые функции UnrealScript вызываются движком при наступлении определенных событий. Например, когда актора коснулся другой актер, двигатель называет функцию Touch, сообщающую акторы, кто с ним соприкасается. При написании собственной функции Touch, вы можете выполнить необходимые действия, выполняемые при вызове Touch:
// Called when something touches this actor.
function Touch( actor Other )
{
Log( "I was touched!")
Other.Message( "You touched me!" );
}
Вышеприведенная функция иллюстрирует несколько моментов. Во-первых, функция записывает сообщение в лог-файл, используя командуLog (которая эквивалентна командам языка Basic "print" и языка C "printf", за исключением некоторых правил форматирования). Во-вторых, она вызывает функцию "Message", находящуюся в другов акторе. Вызов функций, определенных в других объектах, это распространенное действие в языке UnrealScript (как и в других объектно-ориентированных языках, например в Java), поскольку оно обеспечивает простое средство для "общения" акторов между собой.
Переопределение функций
"Переопределение функции" - это изменение реализации функции базового класса для производного класса. Например, вы пишете сценарий для нового вида монстра называемого Demon. Создаваемый вами класс Demon наследует класса Pawn. Когда Pawn видит игрока в первый раз, вызывается функция "SeePlayer" класса Pawn, и Pawn может начать атаковать игрока. Это хорошая концепция, но говорят, что вам хотелсь бы изменить функцию "SeePlayer" для вашего нового класса Demon. Как вы это делаете? Конечно же, с помощью переопределения функции SeePlayer.
Чтобы переопределить функцию, можно просто скопировать определение функции из базового класса и вставить в новый класс. Например, вы можете добавить функцию SeePlayer в ваш класс Demon.
// New Demon class version of the SeePlayer function.
function SeePlayer( actor SeenPlayer )
{
log( "The demon saw a player" );
// Add new custom functionality here...
}
Переопределение функций является ключом к более эффективному созданию новых классов UnrealScript. Вы можете создать новый класс, который расширяет существующий класс. В этом случае все, что вам нужно сделать, это переопределить функции, алгоритм которых должен отличаться от функций базового класса. Это позволяет создавать новые типы объектов без написания множества строк кода.
Некоторые функции в UnrealScript объявляются со спецификатором final. Ключевое слово final (находящееся непосредственно перед словом function) указывает, что данная функция не может быть переопределена для дочернего класса. Этот спецификатор должен быть использован в функциях, для которых переопределение нежелательно, потому что может привести потерям производительности. Например, у вас есть функция VectorSize, которая вычисляет размер вектора. В ней совершенно нечего переопределять, то есть ее целесообразно его объявить какfinal. С другой стороны, конкретная реализация функций, подобных Touch, сильно зависит от контекста и не должна быть окончательной.
===Расширенные спецификаторы функций
Static
Статическая функция языка UnrealScript подобна статической функции языка C++, ее можно вызывать без ссылки на объект класса. Статические функции могут вызывать другие статические функции, может получать доступ к значениям по умолчанию для переменных. Статические функции не могу вызвать не статические функции и получать доступ переменным экземпляра (так как они не выполняются по отношению к экземпляру объекта). В отличие от языка C++, статические функции являются виртуальными и могут быть переопределены в дочерних классах. Это полезно в тех случаях, когда вы хотите вызывать статическую функции для переменной класса, а на момент компиляции класс не известен, но представлен переменной со ссылкой на класс.
Singular
Ключевое слово singular предотвращает возможность рекурсивного вызова функции. Правило в следующем: если ссылка на актор уже в пределах сингулярной функции, то любые последующие вызовы сингулярной функции будут пропущены. В некоторых случаях это позволять бесконечной рекурсии. Например, если вы попытаетесь перемещать актор внутри вашей реализации функции Bump, то есть вероятность, что во время своего движения актор врежется в другой актор, в результате чего произойдет вызов Bump еще раз, и так далее. Для предотвращении подобного поведения Вы должны быть очень осторожны, но если у вас нет полной уверенности в невозможности появления бесконечной рекурсии, то используйте ключевое слово singular.
Native
Вы можете объявить функцию UnrealScript как native, то есть указать, что функция вызывается из UnrealScript, но реализована в коде на C++. Например, класс Actor содержит много определений функций со спецификатором native, например:
native(266) final function bool Move( vector Delta );
Число в скобках, после ключевого слова native соответствует номеру функции, объявленной в коде на C++ (с использованием макроопределения AUTOREGISTER_NATIVE), и необходимо только для оператор-функции. Встроенные функции, как ожидается, находятся в DLL с именем, идентичным имени пакета классов, содержащего определение на языке UnrealScript.
NoExport
Используется только для встроенных функций. Указывает, что объявление функции на C++ для этой встроенной функции не должно быть экспортировано. При компиляции сценария в автоматически генерируемый заголовочный файл будет помещено только объявление этой функции.
Exec
Указывает, что эта функция может быть выполнена путем ввода ее имени в консоли. Применимо только для функций некоторых классов.
Latent
Указывает , что встроенная функция латентная, а это означает, что она может быть вызвана только из кода состояния и может вернуть значение через некоторое количество игрового времени.
Iterator
Указывает, что встроенная функция является итератором, который может быть использован для перебора списка акторов с помощью команды foreach.
Simulated
Указывает, что функция может выполняться на стороне клиента, когда актор эмулируется прокси или автономным прокси. Все встроенные функции как правило эмулируются автоматически. (Примечание: если вы переопределите виртуальную встроенную функцию функцией сценария, функция сценария НЕ будет эмулироваться, если вы укажете это ключевое слово)
Server
Указывает, что функция должна быть отправлена на сервер, а не выполняться на локальном клиенте.
Client
Указывает, что функция должны быть направлена для выполнения на клиенте-владельце, а не запускается на сервере. Этот флаг также неявно устанавливает для функции флаг simulated.
Reliable
Указывает, что реплицируемая функция (отмеченая флагом server или client) должна быть надежно передана, то есть должна гарантированно достичь адресата.
Unreliable
Указывает, что реплицируемая функция (отмеченая флагом server или client) должна быть отправлена ненадежно, что означает, что ее достижение адресата не гарантированно, ее передача может быть выполнена в любой удобный момент не выполняться вообще, если не позволяет пропускная способность сети.
Private, Protected
Эти спецификаторы имеют тот же смысл, что и соответствующие ключевые слова для переменных.
Event
Ключевое слово event в UnrealScript имеет то же значение, что и как функция function. Однако, при экспорте заголовочного файла C++ с использованием =unreal -make -h, UnrealEd автоматически генерирует для "события" заглушку вызова из C++ в UnrealScript, что автоматически синхронизирует код на C++ с функциями UnrealScript и исключает возможность передачи ошибочных параметров в функции UnrealScript. Рассмотрим следующий участок кода UnrealScript.:
event Touch( Actor Other )
{ ... }
Создает код на C++ в EngineClasses.h, подобный следующему:
void eventTouch(class AActor* Other)
{
FName N("Touch",FNAME_Intrinsic);
struct {class AActor* Other; } Parms;
Parms.Other=Other;
ProcessEvent(N, &Parms);
}
Это позволяет вам вызвать функцию UnrealScript из C++ следующим образом:
AActor *SomeActor, *OtherActor;
SomeActor->eventTouch(OtherActor);
Const
Это спецификатор добавляется после объявления функции и может быть использован только в объявлении встроенной функции. Указывает, что функция должна быть экспортирована в заголовочный файл как 'const'. Пример использования: |
native function int doSomething(string myData) const;
Управляющие структуры
Язык UnrealScript поддерживает все стандартные операторы управления выполнением языков C, C++ и Java:
Структуры повторения
Циклы for
Циклы "For" позволяют выполнять цикл до тех пор, пока не будет выполнено определенное условие. Например:
// Example of "for" loop.
function ForExample()
{
local int i;
log( "Demonstrating the for loop" );
for( i=0; i<4; i++ )
{
log( "The value of i is " $ i );
}
log( "Completed with i=" $ i);
}
В результате работы этого цикла мы получим вывод:
Demonstrating the for loop
The value of i is 0
The value of i is 1
The value of i is 2
The value of i is 3
Completed with i=4
В цикле for вы должны указать три выражения, разделенные точкой с запятой. Первое выражение для инициализации переменной в исходное значение. Второе выражение содержит условие, проверяемое перед выполнением каждой итерации цикла, если это выражение истинно, цикл выполняется, а если оно ложно, цикл завершается. Третье условие содержит выражение, увеличивающее счетчик цикла.
Хотя большинство выражений цикла "for" просто обновляют счетчик, вы также можете использовать циклы "for" для более расширенных операций, например, для обхода связанных списков, с помощью соответствующей инициализации исходного значения, условия прекращения и величины прироста.
Во всех управляющих структурах вы можете выполнять одну операцию без расстановки фигурных скобок, например:
for( i=0; i<4; i++ )
log( "The value of i is " $ i );
Или же вы можете выполнить несколько операций, заключив их в фигурные скобки, например:
for( i=0; i<4; i++ )
{
log( "The value of i is" );
log( i );
}
Циклы do
Циклы "do" позволяют вам выполнять цикл пока указанное вами окончательное выражение истинно. Обратите внимание, что Unreal использует синтаксис do-until, который отличается от синтаксиса языков C и Java (использующих do-while).
// Example of "do" loop.
function DoExample()
{
local int i;
log( "Demonstrating the do loop" );
do
{
log( "The value of i is " $ i );
i = i + 1;
} until( i == 4 );
log( "Completed with i=" $ i);
}
В результате работы этого цикла мы получим вывод:
Demonstrating the do loop
The value of i is 0
The value of i is 1
The value of i is 2
The value of i is 3
Completed with i=4
Циклы while
Циклы "while" позволяют вам выполнять цикл пока указанное вами начальное выражение истинно.
// Example of "while" loop.
function WhileExample()
{
local int i;
log( "Demonstrating the while loop" );
while( i < 4 )
{
log( "The value of i is " $ i );
i = i + 1;
}
log( "Completed with i=" $ i);
}
В результате работы этого цикла мы получим вывод:
Demonstrating the do loop
The value of i is 0
The value of i is 1
The value of i is 2
The value of i is 3
Completed with i=4
Оператор continue
Команда "continue" перемещает поток выполнения в начало цикла, а все, что находится после нее, выполнено не будет. В некоторых случаях это может быть использовано для пропуска участка кода цикла.
function ContinueExample()
{
local int i;
log( "Demonstrating continue" );
for( i=0; i<4; i++ )
{
if( i == 2 )
continue;
log( "The value of i is " $ i );
}
log( "Completed with i=" $ i );
}
В результате работы этого цикла мы получим вывод:
Demonstrating continue
The value of i is 0
The value of i is 1
The value of i is 3
Completed with i=4
Оператор break
Команда "break" осуществляетвыходизтекущегоцикла ("For", "Do" или "While").
function BreakExample()
{
local int i;
log( "Demonstrating break" );
for( i=0; i<10; i++ )
{
if( i == 3 )
break;
log( "The value of i is " $ i );
}
log( "Completed with i=" $ i );
}
В результате работы этого цикла мы получим вывод:
Demonstrating break
The value of i is 0
The value of i is 1
The value of i is 2
Completed with i=3
Обратите внимание, что команда "break" также может быть использована для пропуска оставшейся части условного оператора ("switch").
Структуры выбора
Выражения if-then-else
Операторы "if", "else if" и "else" позволяют вам выполнить код при выполнении определенных условий.
// Example of simple "if".
if( LightBrightness < 20 )
log( "My light is dim" );
// Example of "if-else".
if( LightBrightness < 20 )
log( "My light is dim" );
else
log( "My light is bright" );
// Example if "if-else if-else".
if( LightBrightness < 20 )
log( "My light is dim" );
else if( LightBrightness < 40 )
log( "My light is medium" );
else if( LightBrightness < 60 )
log( "My light is kinda bright" );
else
log( "My light is very bright" );
// Example if "if" with brackets.
if( LightType == LT_Steady )
{
log( "Light is steady" );
}
else
{
log( "Light is not steady" );
}
Выражения case
"Switch", "Case", "Default", and "Break" позволяют вам легко обрабатывать списки условий.
// Example of switch-case.
function TestSwitch()
{
// Executed one of the case statements below, based on
// the value in LightType.
switch( LightType )
{
case LT_None:
log( "There is no lighting" );
break;
case LT_Steady:
log( "There is steady lighting" );
break;
case LT_Backdrop:
log( "There is backdrop lighting" );
break;
default:
log( "There is dynamic" );
break;
}
}
Структура "switch" состоит из одного или более операторов "case", а также необязательного оператора "default". Управление передается оператору "case", совпадающему со значением оператора "switch". Оператор "switch" может включать любое количество экземпляров "case", но два оператора "case" не могут иметь одинаковое значение. Выполнение кода после оператора начинается с выбранного оператора и продолжается до тех пор, пока оператор break не передаст управление за пределы структуры case. Если ни одно выражение case не совпадает со значением оператора "switch", управление передается операторам, следующим за необязательным оператором "default". Если оператора "default" нет, то управление передается за пределы управляющей структуры "switch".
Оператор перехода "break", требуется после каждого блока case, включая последний блок, вне зависимости от того, какой из двух операторов ("case" или "default") там использован. Если вы не используете "break", то выполнение будет передано следующему оператору "case" (или "default").
// Example of switch-case.
function TestSwitch2()
{
switch( LightType )
{
case LT_None:
log( "There is no lighting" );
break;
case LT_Steady: // will "fall though" to the LT_Backdrop case
case LT_Backdrop:
log( "There is lighting" );
break;
default:
log( "Something else" );
break;
}
}
Оператор goto
Команда "goto" осуществляет переход потока выполнения к указанной метке.
// Example of "goto".
function GotoExample()
{
log( "Starting GotoExample" );
goto Hither;
Yon:
log( "At Yon" );
goto Elsewhere;
Hither:
log( "At Hither" );
goto Yon;
Elsewhere:
log( "At Elsewhere" );
}
В результате мы получим вывод:
Starting GotoExample
At Hither
At Yon
At Elsewhere
Функциональность языка
Функции общего назначения
Создание объектов
Для того чтобы создать новый экземпляр объекта в UnrealScript, вы будете использовать одну из двух функций в зависимости от того, наследует ли класс объекта класс Actor. Для акторов вы должны использовать функцию Spawn, которая объявлена в файле сценария Actor.uc. Для остальных классов вы должны использовать оператор new. Синтаксис оператора new в отличается от любой другой функции. В дополнение к необязательному списку параметров вы должны указать класс нового объекта и необязательный шаблон объекта. В сценариях UnrealScript нет объявления для оператора new, но если бы было, то выглядело примерно так new:
native final operator function coerce Object new
(
object InOuter,
name InName,
int InFlags,
class InClass,
object InTemplate
);
InOuter
(необязательный) Пакет, который необходимо назначить как "внешний" (Outer) для вновь созданного объекта. Если этот параметр не указан, "внешним" для объекта будет установлен специальный пакет, который существует только во время игры, называемый "переходным пакетом" (transient package).
InName
(необязательный) Имя для нового объекта. Если параметр на указан, объекту будет дано уникальное имя в формате ClassName_##, где ## - уникальный номер, увеличивающийся при создании каждого нового экземпляра этого класса.
InFlags
(необязательный, в настоящее время значение ограничивается 64 битными флагами) Флаги, уточняющие особенности применения объекта после его создания:
· 0x0000000100000000: Редактором поддерживается отмена/повтор операций с данным объектом. (RF_Transactional)
· 0x0000000400000000: Может ссылаться на внешние файлы. (RF_Public)
· 0x0000400000000000: Не может быть сохранен на диск. (RF_Transient)
· 0x0010000000000000: Не загружать объект на игровой клиент. (RF_NotForClient)
· 0x0020000000000000: Не загружать объект на игровой сервер. (RF_NotForServer)
· 0x0040000000000000: Не загружать объект в редактор. (RF_NotForEdit)
· 0x0008000000000000: Держать объект для редактирования, даже если он не на что не ссылается. (RF_Standalone)
InClass
класса, экземпляр которого создается
InTemplate
Объект, используемый для инициализации значений свойств нового объекта
Синтаксис применения оператора new выглядит следующим образом:
ObjectVar = new[(InOuter, InName, InFlags)] <class'InClass'>[(InTemplate)];
Создатьобъекткласса LightFunction:
function CreateALight()
{
local LightFunction NewObj;
NewObj = new class'Engine.LightFunction';
}
Создаем новый объект класса LightFunction с именем "NewLight", указываем этот объект как внешний пакет.
function CreateALight()
{
local LightFunction NewObj;
NewObj = new(Self,'NewLight') class'Engine.LightFunction';
}
Создаем новый объект класса LightFunction с именем "NewLight" в переходный пакет, инициализируем значения свойств нового объекта, используя переменную LightFunctionTemplate:
var LightFunction LightFunctionTemplate; function CreateALight() { local LightFunction NewObj; NewObj = new(None,'NewLight') class'Engine.LightFunction' (LightFunctionTemplate); } defaultproperties { Begin Object Class=LightFunction Name=MyLightFunctionArchetype End Object LightFunctionTemplate=MyLightFunctionArchetype } |
Функции для отладки
Следующие функции могут помочь вам в отладке кода.
- LogEx( ELoggingSeverity Severity, name Category, coerce string Msg ); Выводит сообщение с заданными важностью и категорией. Эта функция обеспечивает больший контроль, чем стандартная функция log(). Она позволяет фильтровать сообщения журнала по важности и по категориям в режиме исполнения.
- LogFatal( name Category, coerce string Msg ); Сокращенныйвариантвызова LogEx(LOG_FATAL, Category, Msg)
- LogError( name Category, coerce string Msg );
- function LogWarn( name Category, coerce string Msg );
- LogInfo( name Category, coerce string Msg );
- LogDebug( name Category, coerce string Msg );
- LogTrace( name Category, coerce string Msg );
Отметим, что по состоянию списка изменений 134102, функции протоколирования, указанные выше, больше не доступны. Они были заменены на соответствующие макроопределения, которые обрабатываются препроцессором UnrealScript.
- ScriptTrace(); Помещает стек вызова текущего сценария в файл журнала
- Name GetFuncName(); Возвращает имя текущей вызываемой функции
- DumpStateStack(); Выводит текущее состояние стека
Препроцессор UnrealScript
Подробнее о препроцессоре читайте на странице Препроцессор Unrealscript .
Профилирование сценариев
The Профайлер геймплея может помочь поиске сценариев, наиболее критичных к времени выполнения.
Отладчик сценариев
Подробнее об инструментах отладки Unreal читайте на странице Debugging Tools .
Продолжение...
Данный документ является переводом оригинального документа UnrealScript Language Reference.
UnrealScript. Справочное руководство. Частьвторая http://www.gamedev.ru/community/udk/articles/UnrealScriptReference2Автор: VincentBarabus Данный документ является переводом оригинального документа UnrealScript Language Reference Расширенные функции языка Таймеры Таймеры используются в качестве механизма для планирования выполнения, повторения или завершения событий. Таким образом, актор может установить таймер, зарегистрировав себя в игровом движке и установив необходимый порядок вызова функции Timer(). Таймеры UnrealScript реализованы как простой массив структур внутри каждого актора (актор может иметь несколько таймеров в стадии согласования). Структура включает в себя количество времени, оставшегося до истечения таймера, функцию для вызова по истечении определенного срока и т.д. Обычно игровой цикл обновляет состояние каждого актора один раз за кадр, а часть функции Tick() каждого актора в включает в себя вызов функции UpdateTimers(), которая проверяет все таймеры на истечение времени и вызывает функции UnrealScript, соответствующие таймерам. Частота таймеров ограничивается временем одного тика и не зависит ни от аппаратных ресурсов, ни от ресурсов операционной системы. Код таймеров реализован на C++, так что вы можете безопасно обновлять сотни таймеров UnrealScript без каких-либо причин для беспокойства. Конечно, вам не следует устанавливать обновление всех таймеров каждый тик, так как таймеры выполняют функции (относительно медленного) кода сценариев. Состояния Обзор состояний Исторически сложилось, что программисты игр используют концепцию состояний. Состояния (также известные как "машины программирования состояний") являются естественным путем управления поведением сложных объектов. Однако, пока поддержка состояний не была реализована на уровне языка UnrealScript, разработчикам для реализации состояний проиходилось создавать конструкции "switch" на языке C или C++. Такой код трудно было писать и обновлять. Теперь UnrealScript поддерживает состояния на уровне языка В UnrealScript каждый актор, расположенный в игровом мире, всегда находится в одном и только одном состоянии. Его состояние отражает действия, которые он должен выполнить. Например, перемещение кисти включает несколько состояний, например, "StandOpenTimed" и "BumpOpenTimed". Для объектов Pawn есть несколько состояний, таких как "Dying", "Attacking" и "Wandering". В языке UnrealScript вы можете писать функции и код, относящиеся к определенным состояниям. Эти функции вызываются только тогда, когда актор пребывает в определенном состоянии. Например, при разработке сценария монстра, вы реализуете функцию "SeePlayer", которая вызывается в тот момент, когда монстр "видит" игрока. "Увидев" игрока монстр перейдет из состояния "Wandering" в состояние "Attacking", начав атаку. Самый простой способ реализовать вышеописанное - это определить некоторые состояния (Wandering и Attacking), и написать различные версии "Touch" в каждом состоянии. Язык UnrealScript поддерживает эту идею. Перед тем, как приступить к изучению состояний, обратите внимание, что существуют два основных преимущества использования состояний и одно осложнение:
Наши рекомендации
|