Войти
UDKСтатьи

UnrealScript. Справочное руководство

Автор:

Введение
  Ссылки
  Назначение этого документа
  Причины разработки языка UnrealScript
  Новое в Unreal Engine 3
  Примерная структура программы
  Виртуальная машина Unreal
  Иерархия объектов
Классы
Переменные
  Типы переменных
    Встроенные типы
    Составные типы данных
    Типы Unreal
    Спецификаторы переменных
    Возможность редактирования
  Массивы
  Структуры
    Спецификаторы структур
  Перечисления
  Константы
  Переменные ссылок на объекты и акторы
  Переменные ссылок на классы
Выражения
  Присваивание
  Преобразование ссылок на объекты и классы
Функции
  Объявление функций
  Спецификаторы параметров функций
  Переопределение функций
Управляющие структуры
  Структуры повторения
    Циклы for
    Циклы do
    Циклы while
    Оператор continue
    Оператор break
  Структуры выбора
    Выражения if-then-else
    Выражения case
    Оператор goto
Функциональность языка
  Встроенные операторы и их приоритет
  Функции общего назначения
    Создание объектов
    Функции для операций над целыми числами
    Функции для операций над числами с плавающей точкой
    Функции для операций над строками
    Функции для операций над векторами
    Функции для работы с таймерами
    Функции для отладки
  Препроцессор UnrealScript
  Инструменты и утилиты UnrealScript
    Профилирование сценариев
    Отладчик сценариев

Введение

Ссылки

Ознакомьтесь со шпаргалкой UnrealScript External Link | UnrealScript. Справочное руководство и книгой Mastering UnrealScript External Link | UnrealScript. Справочное руководство.

Назначение этого документа

Этот технический документ описывает язык UnrealScript. Это не учебник и не он содержит подробных примеров полезного кода UnrealScript. Примеры сценариев UnrealScript вы найдете в исходном коде движка, содержащем десятки тысяч строк рабочего кода UnrealScript, который решает такие задачи, как ИИ, движение, инвентарь и триггеры. Для начала изучите реальзацию сценариев "Actor", "Object", "Controller", "Pawn" и "Weapon".

Этот документ предполагает, что читатель хорошо знает язык C/C++ или Java, знаком с объектно-ориентированным программированием, играл в Unreal и пользовался редактором UnrealEd.

Программистам, новичкам в ООП, я настоятельно рекомендую посетить Amazon.com или книжный магазин и купить книгу по программированию на Java. Java очень похож на UnrealScript, а его изучение позволит понять язык UnrealScript проще и быстрее.

Причины разработки языка UnrealScript

UnrealScript был создан, чтобы обеспечить команду разработчиков Unreal и сторонних разработчиков мощным встроенным языком программирования, охватывающим все задачи и нюансы программирования игр.

Преимущественно язык UnrealScript разработан:

С начала разработки UnrealScript и до его текущей реализации, было изучено и отброшено несколько различных крупных парадигм программирования. Во-первых, мы исследовали возможность использования в качестве основы для языка сценариев Unreal платформы Sun и Microsoft Java VM для Windows. Оказалось, что преимущества Java, по сравнению с применением C/C++, в контексте Unreal добавляют разочаровывающие ограничения, связанные с отсутствием необходимых возможностей языка (например, переопределения операторов), а скорость выполнения программ оказалась довольно медленной из-за накладных расходов VM по переключению между задачами и из-за неэффективности сборщика мусора Java в случае сложной структуры наследования объектов. Во-вторых, мы рассматривали возможность реализации языка UnrealScript на базе Visual Basic, который хорошо работал, но был менее дружественным для программистов, привыкших к C/C++. Окончательное решение заключалось в реализации языка UnrealScript, сочетающего возможности языков C++ и Java, и включающего категории, отражающие объекты, специфичные для разработки игр. Это оказалось правильным решением, значительно упростившим многие аспекты кода Unreal.

Новое в Unreal Engine 3

Для тех, кто уже знаком с UnrealScript, мы представляем краткий обзор основных изменений в UnrealScript, дополняющих версию языка сценариев движка Unreal Engine 2.

Примерная структура программы

Этот пример иллюстрирует типичный простой класс UnrealScript и подчеркивает синтаксис и особенности языка UnrealScript. Обратите внимание, что этот пример может отличаться от его реализации в исходном коде Unreal, так как этот документ не синхронизирован с исходным кодом движка.

//=====================================================================
// TriggerLight.
// A lightsource which can be triggered on or off.
//=====================================================================
class TriggerLight extends Light;
 
//---------------------------------------------------------------------
// Variables.
 
var() float ChangeTime; // Time light takes to change from on to off.
var() bool bInitiallyOn; // Whether it's initially on.
var() bool bDelayFullOn; // Delay then go full-on.
 
var ELightType InitialType; // Initial type of light.
var float InitialBrightness; // Initial brightness.
var float Alpha, Direction;
var actor Trigger;
 
//---------------------------------------------------------------------
// Engine functions.
 
// Called at start of gameplay.
function BeginPlay()
{
   // Remember initial light type and set new one.
   Disable( 'Tick' );
   InitialType = LightType;
   InitialBrightness = LightBrightness;
   if( bInitiallyOn )
   {
      Alpha = 1.0;
      Direction = 1.0;
   }
   else
   {
      LightType = LT_None;
      Alpha = 0.0;
      Direction = -1.0;
   }
}
 
// Called whenever time passes.
function Tick( float DeltaTime )
{
   LightType = InitialType;
   Alpha += Direction * DeltaTime / ChangeTime;
   if( Alpha > 1.0 )
   {
      Alpha = 1.0;
      Disable( 'Tick' );
      if( Trigger != None )
         Trigger.ResetTrigger();
   }
   else if( Alpha < 0.0 )
   {
      Alpha = 0.0;
      Disable( 'Tick' );
      LightType = LT_None;
      if( Trigger != None )
         Trigger.ResetTrigger();
   }
   if( !bDelayFullOn )
      LightBrightness = Alpha * InitialBrightness;
   else if( (Direction>0 && Alpha!=1) || Alpha==0 )
      LightBrightness = 0;
   else
      LightBrightness = InitialBrightness;
}
 
//---------------------------------------------------------------------
// Public states.
 
// Trigger turns the light on.
state() TriggerTurnsOn
{
   function Trigger( actor Other, pawn EventInstigator )
   {
      Trigger = None;
      Direction = 1.0;
      Enable( 'Tick' );
   }
}
 
// Trigger turns the light off.
state() TriggerTurnsOff

{
   function Trigger( actor Other, pawn EventInstigator )
   {
      Trigger = None;
      Direction = -1.0;
      Enable( 'Tick' );
   }
}
 
// Trigger toggles the light.
state() TriggerToggle
{
   function Trigger( actor Other, pawn EventInstigator )
   {
      log("Toggle");
      Trigger = Other;
      Direction *= -1;
      Enable( 'Tick' );
   }
}
 
// Trigger controls the light.
state() TriggerControl
{
   function Trigger( actor Other, pawn EventInstigator )
   {
      Trigger = Other;
      if( bInitiallyOn ) Direction = -1.0;
      else Direction = 1.0;
      Enable( 'Tick' );
   }
   function UnTrigger( actor Other, pawn EventInstigator )
   {
      Trigger = Other;
      if( bInitiallyOn ) Direction = 1.0;
      else Direction = -1.0;
      Enable( 'Tick' );
   }
}
Ключевые элементы этого сценария, на которые вам следует обратить внимание:

Виртуальная машина Unreal

Виртуальная машина Unreal состоит из нескольких компонентов: сервер, клиент, движок визуализации и код поддержки движка.

Сервер Unreal контролирует весь геймплей и взаимодействия между персонажами и акторами. В одиночной игре, как клиент Unreal и сервер Unreal работают на одной машине, в интернет-игре, выделенный сервер работает на одной машине, а все игроки подключаются к этой машине как клиенты.

Все игры происходят внутри "уровня" - автономной среды, включающей геометрию и акторов. Хотя UnrealServer может одновременно работать и более, чем с одиним уровнем, все уровни работают независимо и защищены друг от друга: акторы не могут перемещаться между уровнями, а акторы одного уровня не могут связываться с акторами других уровней.

Каждый актор на карте может быть под контролем игрока (в сетевой игре игроков может быть много) или управляться сценарием. В случае, когда актор контролируется сценарием, сценарий полностью определяет поведение и взаимодействует актора с другими акторами.

Посмотрев на все эти бегающие акторы, выполняющиеся сценарии и событиями, происходящие в игровом мире, вы, вероятно, задаетесь вопросом, как как это все реализовано в UnrealScript. Ответ на этот вопрос ниже:

Для управления временем Unreal делит каждую секунду геймплея на кванты времени, тики ("Ticks"). Тик - это наименьшая единица времени, за которую обновляются все акторы на уровне. Тик обычно занимает от 1/100 до 1/10 доли секунды. Время тика ограничивается только мощностью процессора; чем быстрее машина, тем ниже продолжительность тика.

В UnrealScript время выполнения некоторых команд занимает ноль тиков (то есть их выполнение происходит без затрат игрового времени), а выполнение других команд занимает много тиков. Функции, выполнение которых занимает игровое время, называюься "латентными функциями" ("latent functions"). Латентными функциями, например, являются Sleep, FinishAnim и MoveTo. Латентные функции в UnrealScript могут вызываться только из "кода состояний" ("state code"), а не из кода функций (включая функции, определенные в состоянии).

Пока актор выполняет латентную функцию, он не может выполнить код состояния до завершения выполнения кода этой латентной функции. Однако при этом функции текущего актора могут вызывать другие акторы или VM. В итоге все функции UnrealScript все же могут вызываться в любой момент, даже во время выполнения латентных функций.

В традиционных терминах программирования, UnrealScript действует так, как будто каждый актор на уровне имеет свой собственный исполняемый "поток". Внутренне, Unreal не использует потоки Windows, потому что это было бы крайне неэффективно (Windows 95 и Windows NT не могут одновременно эффективно обрабатывать тысячи потоков). Вместо этого, UnrealScript эмулирует потоки. Этот факт является прозрачным для кода на UnrealScript, но становится очень очевидным, когда вы пишете код на C++, взаимодействующий со сценариями UnrealScript.

Все сценарии UnrealScript выполняются независимо друг от друга. При наличии 100 монстров на уровне все 100 сценариев этих монстров выполняются одновременно и независимо от "тиков" акторов каждого монстра.

Иерархия объектов

Перед началом работы с UnrealScript важно понять высокоуровневые взаимоотношения между объектами Unreal. Архитектура Unreal серьезно отличается от большинства других игр: движок Unreal является полностью объектно-ориентированным (подобно COM или ActiveX), он имеет четко определенную модель объектов с поддержкой высокоуровневых объектно-ориентированных концепций, таких как графы объектов, сериализация, время жизни объекта и полиморфизм. Исторически, большинство игр разрабатывались монолитно, а их основные функции жестко привязывались на уровне объектов, хотя многие игры, такие как Doom и Quake, оказались расширяемыми на уровне контента. Основное преимущество модели объектно-ориентированного программирования Unreal в том, что новые функциональные возможности и типы объектов могут добавляться к Unreal во время выполнения. Расширение функциональности может осуществляться путем создания подклассов, а не, к примеру, путем модификации кучи существующего кода. Эта модель расширения является чрезвычайно мощной и привлекательной для сообщества Unreal, позволяя вносить в Unreal дополнительные модификации и усовершенствования.

Object - это базовый класс всех объектов Unreal. Все функции в класса Object доступны для всех объектов. Object - это абстрактный базовый класс,  сам по себе он не имеет полезной функциональности. Вся функциональность обеспечивается подклассами, например, классами Texture (текстуры), TextBuffer (кусок текста) и Class (который описывает классы других объектов).

Actor (расширяет класс Object) является базовым классом для всех автономных игровых объектов Unreal. Класс Actor включает всю функциональность, необходимую для перемещения акторов, их взаимодействия между собой, воздействия на игровое окружение, для осуществления других полезных вещей, связанных с игрой.

Pawn (расширяет класс Actor) - это базовый класс всех созданий и персонажей Unreal, которые контролируются высокоуровневым ИИ или управляются непосредственно игроком.

Class (расширяет класс Object) - это особый вид объекта, описывающий класс объектов. На первый взгляд он может показаться запутанным: класс объекта и класс описывает определенные объекты. Но в работе вам встретится множество случаев, когда Вы будете иметь дело с объектами Class. Например, при воплощении нового актора в UnrealScript, вы можете указать класс нового актера, применяя объект Class.

С помощью UnrealScript вы можете писать код для любого класса, расширяющего класс Object, но 99% времени вы будете писать код для классов, производных от класса Actor. Большинство полезных функций UnrealScript, связанных с игрой, - это действия с акторами.

Классы

Каждый сценарий соответствует одному отдельному классу и начинается с объявления класса, наследуемого класса и другой дополнительной информации, относящейся к классу. Простейшая форма:

class MyClass extends MyParentClass;
Здесь мы объявили новый класс с именем "MyClass", который наследует функциональность класса "MyParentClass". Кроме того, объявленный класс находится в пакете с именем "MyPackage".

Каждый класс наследует все переменные, функции и состояния от своего базового класса. Далее вы можете добавить новые переменные, новые функции (или переопределить существующие функции), новые состояния (или добавить функциональность к существующим).

Типичный подход к разработке класса UnrealScript заключается в создании нового класса (например чудовища минотавра), расширяющего существующий класс, который имеет большинство необходимых функций (например, класс Pawn, базовый класс для всех монстров). При таком подходе вам не нужно заново изобретать колесо - вы можете просто добавить новые необходимые вам функции, сохраняя при этом все существующие функции, не нуждающиеся в модификации. Этот подход особенно эффективен для реализации ИИ: встроенная система ИИ Unreal предоставляет огромное количество базовых функциональных возможностей, применимых в качестве строительных блоков для собственных существ.

Объявление класса может включать несколько дополнительных спецификаторов, которые влияют на класс:

Native(PackageName)
Указывает, что "этот класс использует за-кадром код на C++". Unreal ожидает наличие встроенных (native) классов в коде на C++, реализованных в основном исполняемом модуле (.exe). Объявлять встроенные функций или осуществлять реализацию встроенных интерфейсов могут только встроенные классы. Встроенные классы могут быть производными только от других встроенных классов. Для встроенных классов создается автоматически сгенерированный заголовочный файл C++ с описателями, необходимыми для взаимодействовия переменных и указанных функций сценария к кодом на C++. По умолчанию, PackageName - это имя пакета, в котором находится сценарий класса. Например, если в классе определено имя пакета Engine, то в результате автоматически сгенерированный заголовок будет называться EngineClasses.h.
NativeReplication
Указывает, что репликация значений переменных для данного класса осуществляется в реализации на C++. Допустимо только для встроенных классов.
DependsOn(ClassName[,ClassName,...])
Указывает, что класс ClassName компилируется перед компиляцией текущего класса. ClassName должно указывать на класс в текущем (или предыдущем) пакете. Несколько зависимостей можно определить с помощью DependsOn в одну строку, разделив имена классов запятыми, или же в несколько строк, определив DependsOn для каждого класса.
Abstract
Объявляет класс как "абстрактный базовый класс". Это позволяет пользователю добавлять акторов этого класса в мире с помощью UnrealEd или создвать экземпляры этого класса во время игры, потому что этот класс не имеет смысла сам по себе. Например, базовый класс "Actor" является абстрактным, в то время как подкласс "Ladder" не является абстрактным - Вы можете разместить Ladder в мире, но вы не можете поместить в мире актор. Это ключевое слово распространяется на внутренние дочерние классы, но не распространяется на дочерние классы сценариев.
Deprecated
Все объекты этого класса будут загружены, но не могут быть сохранены. Размещение экземпляра любого устаревшего (deprecated) актора будет выдавать дизайнерам уровней предупреждение при загрузке карты в редакторе. Это ключевое слово применимо к дочерним классам.
Transient
Указывает, что "объекты, принадлежащие к этому классу, никогда не должны сохраняться на диск". Имеет смысл только в сочетании с определенными видами встроенных классов, которые не являются устойчивыми по своей природе, например, как игроки или окна. Это ключевое слово распространяется на дочерние классы; дочерние классы могут переопределить этот флаг путем использования ключевого слова NonTransient.
NonTransient
Отменяет спецификатор Transient, унаследованный от базового класса.
Страницы: 1 2 3 4 5 6 Следующая »

#UDK, #Unreal Development Kit

7 июня 2012 (Обновление: 18 мая 2013)