Sunday, April 7, 2013

Меняем персонажа в процессе игры в UDK

    По упомянутой просьбе на сайте решил немного поизучать вопрос переключения у игрока стандартного меша.
    В играх, где есть несколько персонажей и необходимо переключаться между ними, или же на каждый уровень приходится свой персонаж, придется озаботится этим вопросом.
    К делу. В итоге скопилось целых три способа(и скорее всего еще столько же можно придумать(найти)) и все как обычно: легкий,легкий и ... легкий. Начнем для разминки с легкого...
    Здесь представлены только собственные классы SM_PlayerController, потому как основные добавления происходят в этих классах. Полные версии скриптов, готовые для компиляции находятся в архиве, который можно скачать по ссылке в конце статьи.





Простая замена меша игрока во время игры.

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

    При этом не меняется сам класс Pawn, что пожалуй не есть гуд. Конечно можно напихать различных функций также переключающихся между собой, если какие-то свойства координально отличаются от старого персонажа...
    Для примера создал спец блок для кисмета, при срабатывании которого и будет происходить, столь вожделенные события. Напомню, что все на достаточно примитивном уровне, без изысков и  спецэффектов - быстрая спартанская смена меша. При достаточной сноровке переходный процесс можно или спрятать или скрасить. Конечно же можно назначить смену pawn на какую нибудь кнопку, действие и т.д. алгоритм в целом не поменяется.


класс SM_PlayerController:
class SM_PlayerController extends GamePlayerController;

var SkeletalMesh Changemesh;
var MaterialInterface ChangeMaterial0;
var AnimTree ChangeAnimTree;
var array<animset> ChangeAnimSet;
var AnimNodeSequence ChangeAnimSeq;
var PhysicsAsset ChangePhysicsAsset;
var bool SwitchMesh;


simulated event PostBeginPlay()

{
    super.PostBeginPlay();
    //`log("SM_PlayerController");
}

// вызывается из кисмета и  поменяет перса.
function SwitchPerson(bool Allowed)
{
    SwitchMesh = Allowed;
    if(SwitchMesh)   
    {
        SwitchMesh = FALSE        // Сначала  прописываем на какой именно меш будем менять, для примера взять      
     // стандартный  меш IronGuard
        ChangeMesh=SkeletalMesh'CH_IronGuard_Male.Mes h.SK_CH_IronGuard_MaleA'
        ChangeAnimTree=AnimTree'CH_AnimHuman_Tree.AT_ CH_Human';
        ChangeAnimSet[0]=AnimSet'CH_AnimHuman.Anims.K_AnimHuman_AimOffset';
        ChangeAnimSet[1]=AnimSet'CH_AnimHuman.Anims.K_AnimHuman_BaseMale';
        ChangePhysicsAsset=PhysicsAsset'CH_AnimCorrup t.Mesh.SK_CH_Corrupt_Male_Physics';
        // Затем поочередно применяем 
        self.Pawn.Mesh.SetSkeletalMesh(ChangeMesh);
        self.Pawn.Mesh.SetMaterial(0,MaterialInstanceConstant'CH_IronGuard_Male.Materials.MI_CH_IronG_MHead01_V01');
        self.Pawn.Mesh.SetMaterial(1,MaterialInstanceConstant'CH_IronGuard_Male.Materials.MI_CH_IronG_Mbody01_V01');
        /* !! Понадобится если будете менять на перса у которого другая анимация  и физика */
        //self.Pawn.Mesh.SetPhysicsAsset(ChangePhysicsAsset);
        //self.Pawn.Mesh.AnimSets=ChangeAnimSet;
        //self.Pawn.Mesh.SetAnimTreeTemplate(ChangeAnimTree);
    }
}

defaultproperties 
{
    SwitchMesh = FALSE
}



Полная замена pawn на другой, только что вызванный.

    Принцип в этот раз несколько другой. По пунктам: отключаем pawn от контроллера игрока - удаляем его - вызываем новый pawn - подключаем к нему контроллер игрока. Здесь сделано так же, так что это дело происходит по спец. блоку из кисмета, например, по триггеру.

класс SM2_PlayerController:
class SM2_PlayerController extends GamePlayerController
var bool SwitchPawn;

simulated event PostBeginPlay()
{
    super.PostBeginPlay();
    //`log("SM2_PlayerController");
}

// вызывается из кисмета и  поменяет перса.
function SwitchPerson(bool Allowed)
{
    Local Pawn ReserveBeef;
    Local vector Loc;
    SwitchPawn = Allowed;
    if(SwitchPawn)
    {
         SwitchPawn = FALSE;
         //Запоминаем текущий pawn
         ReserveBeef = Pawn;
         // Запоминаем его расположение
         Loc = Pawn.Location;
         // отсоединяем текущий pawn
         UnPossess();
         // Уничтожаем отсоединенный pawn
         ReserveBeef.Destroy();
         //Вызываем новый pawn
         ReserveBeef = Spawn(class'SM2_AnotherPawn', ,, Loc + vect(50,0,50));
         // Присоединяем новый pawn
         Possess(ReserveBeef,false);
    }
     
}


defaultproperties 
{
    SwitchPawn = FALSE 
}



Переключение между двумя различными pawn

    На уровне появляются сразу два меша, один под котролем AI. По спец блоку из кисмета происходит обмен между ними мешами - переключение котроллеров.
    По принципу этот способ такой же как и предыдущий. Его пункты таковы: отключаем меши от контроллеров - переназначаем котроллеры другим мешам.

класс SM3_PlayerController:
class SM3_PlayerController extends GamePlayerController;
var   bool    SwitchPawn;
var   Pawn   ReserveBeef;

simulated event PostBeginPlay()
{
    // Вызываем другой pawn, по умолсчанию он под AI Controller 
    ReserveBeef = Spawn(Class'SM3_AnotherPawn',,, Location - vect(100,0,0) , Rotation);
    super.PostBeginPlay();
}

// Вызывается из кисмета и говорит что можно поменять перса.
function SwitchPerson(bool Allowed)
{
    Local Controller Cont;
    Local Pawn OldPawn;
    SwitchPawn = Allowed;
    if(SwitchPawn == TRUE)
    {
        SwitchPawn = FALSE;
        //Запоминаем текущий pawn 
        OldPawn = Pawn;
        //Запоминаем AI Controller  того  pawn куда переселимся
        Cont = ReserveBeef.Controller;
        //Отсоединяем наш старый  pawn
        UnPossess();
        //Отсоединяем новый  pawn от AI Controller
        Cont.UnPossess();
        //Присоединяемся
        Possess(ReserveBeef, false);
        //Старый pawn ставим под контроль AI Controller 
        Cont.Possess(OldPawn, false);
    }
}

defaultproperties 
{
    SwitchPawn = FALSE
}


Результат на видео:



Скачать все три способа

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

PS. Все делалось в мартовской версии UDK(2011).

No comments:

Post a Comment