Unreal Engine: Тайпкастинг

Основы UnrealScript: Учимся на практике
Раз уж на ХГМе пошла такая пьянка с геймдевом, буду по возможности дописывать подстатьи к этой статье.
С использованием Акторов в качестве переменных связан еще один важный нюанс - кастинг.
Когда мы создаем дочерние классы, мы можем создать в них функции, которых нет в родительском классе. Однако вспомните предыдущую подстатью. Мы узнали, что в классе Pawn есть переменная класса Weapon, в которой хранится актор оружия игрока, которое является подклассом Weapon (например, плазменная пушка). А теперь представьте себе ситуацию, когда нам нужно вызвать функцию, которая есть в плазменной пушке, и которой нет в Weapon. Как решить проблему? Для этого и существует typecasing (или просто casting).

Для примера, создадим подкласс SuperTestActor для нашего TestActor
class SuperTestActor extends TestActor
    placeable;

function SuperFunction()
{
    `log("SuperFunction was called!");
}

defaultproperties
{
}
Мы просто создали дочерний класс и расширили его функцией, которая просто выводит сообщение в лог. Помните, что новый класс наследует все свойства своего родителя, поэтому нам не нужно создавать для него спрайт.
Теперь, если заглянуть в Actor Browser, наш новый класс будет представлен как ответвление от класса TestActor.
Спавнить мы его будем точно так же, как и в предыдущей подстатье - в классе контроллера, в функции StartFire.
exec function StartFire( optional byte FireModeNum )
{
    super.StartFire(FireModeNum);
    MyTestActor = spawn(class'SuperTestActor',,, Pawn.Location);
    `log(MyTestActor @ "<-- MyTestActor");
}
Скомпилировав код и запустив игру, в логе вы можете увидеть, что наша переменная класса TestActor спокойно принимает значение в виде актора класса SuperTestActor.
А теперь попробуем вызывать нашу SuperFunction прямо с StartFire
exec function StartFire( optional byte FireModeNum )
{
    super.StartFire(FireModeNum);
    MyTestActor = spawn(class'SuperTestActor',,, Pawn.Location);
    `log(MyTestActor @ "<-- MyTestActor");

    if(MyTestActor != none)
        MyTestActor.SuperFunction();
}
А вот на этом месте вы получите ошибку:
Error, Unrecognized member 'SuperFunction' in class 'TestActor'
Переменная у нас все таки класса TestActor, и код воспринимает ее исключительно так. Поэтому мы не можем получить доступ к переменным и функциям, созданным в подклассах. Вот тут в игру и вступает кастинг. Стоит всего лишь немного поменять код:
exec function StartFire( optional byte FireModeNum )
{
    super.StartFire(FireModeNum);
    MyTestActor = spawn(class'SuperTestActor',,, Pawn.Location);
    `log(MyTestActor @ "<-- MyTestActor");

    if(SuperTestActor(MyTestActor) != none)
        SuperTestActor(MyTestActor).SuperFunction();
}
Теперь все работает правильно. Однако, что будет, если мы создадим не SuperTestActor, а просто TestActor? Давайте проверим. Поменяйте функцию следующим образом.
exec function StartFire( optional byte FireModeNum )
{
    super.StartFire(FireModeNum);
    MyTestActor = spawn(class'TestActor',,, Pawn.Location);
     `log(MyTestActor@ "<-- MyTestActor");
    if(SuperTestActor(MyTestActor) != none)
        SuperTestActor(MyTestActor).SuperFunction();
    else
        `log("MyTestActor is not a SuperActor.");
}
В логе увидим
[0008.80] ScriptLog: MyTestActor_1<-- MyTestActor
[0008.80] ScriptLog: MyTestActoris not a SuperActor.
Соответственно к заданному нами логическому выражению, это сообщение мы видим, если SuperTestActor(MyTestActor) имеет значение none. Итого, кастинг возвращает нам none, если переменная не является ни представителем класса, к которому мы "тайпкастим", ни его подклассом.
Помимо прочего, очень часто кастинг используют именно для того, чтобы проверить, относится ли переменная к тому или иному классу. Краткий пример:
var Pet MyPet;

function ReactToPet()
{
    if(Cat(MyPet) != none)
        Sneeze();
    else if(Dog(MyPet) != none)
        PetTheDog();
    else
        `log("What are you, pet?");
}
В этом коде, если переменная MyPet содержит класс Cat, вызывается функция Sneeze, если Dog - PetTheDog.

Практическое применение в игре можете придумать сами. В книге оно весьма бесполезное.
А на этом пока все.

Просмотров: 1 126

Комментарии пока отсутcтвуют