Jump to content

Последовательность включения анимации.


photo

Recommended Posts

Posted

Всем привет!

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

Есть простые клипы анимации сделанные в блендере: 

1. Достаём топор. 2. Движение топора когда стоим. 3. Движение когда идём. 4. Убираем топор. 5. Удар топором.

С помощью клавиш F1 - F3, Input.MOUSE_BUTTON.LEFT , включаю анимации по отдельности. Работает это хорошо. Но,  теперь вопрос - как мне заставить их работать слитно, как единое целое? Хорошо тут работают только 2 анимации - это когда стоишь и когда идёшь. 

Что бы включить после первой анимации: [Достаём топор] вторую: [Движение топора когда стоим], надо задать условие окончания 1-й анимации, а в нем это равенство:            STATE = ANIM_STATE.AXE_OFF; но как понять когда закончится первая анимация? Пробовал использовать переменную _main_character.Time но это не сработало. 

Надеюсь, понятно объяснил. Код и скриншот (как обычно), прилагаю:

public class hand_axe : Component
{
    [ShowInEditor][ParameterAsset (Filter = ".anim")]
    private string axe_on, axe_off, axe_idle, axe_attak, axe_step;
 
    ObjectMeshSkinned _main_character;
    float _weight = 0;
    bool _is_weight_charget = false;
 
    enum ANIM_STATE {PROCEDURAL  = 0, AXE_ON, AXE_OFF, AXE_IDLE, AXE_ATTAK, AXE_STEP, COUNT}
    ANIM_STATE STATE = ANIM_STATE.PROCEDURAL, PREV_STATE;
 
    private void Init()
    {
        _main_character = node as ObjectMeshSkinned;
        _main_character.NumLayers = (int)ANIM_STATE.COUNT;
 
        int _a_on = _main_character.AddAnimation(axe_on);
        int _a_off = _main_character.AddAnimation(axe_off);
        int _a_idle = _main_character.AddAnimation(axe_step);//  поменял местами для корректной работы  
        int _a_attak = _main_character.AddAnimation(axe_attak);
        int _a_step = _main_character.AddAnimation(axe_idle);// поменял местами для корректной работы
 
        _main_character.SetAnimation((int)ANIM_STATE.AXE_ON, _a_on);//1
        _main_character.SetAnimation((int)ANIM_STATE.AXE_OFF, _a_off);//2
        _main_character.SetAnimation((int)ANIM_STATE.AXE_IDLE, _a_idle);//3
        _main_character.SetAnimation((int)ANIM_STATE.AXE_ATTAK, _a_attak);//4
        _main_character.SetAnimation((int)ANIM_STATE.AXE_STEP, _a_step);//5        
    }
   
    private void Update()
    {
        _main_character.SetFrame((int)ANIM_STATE.PROCEDURAL, Game.Time * 30);
        _main_character.SetFrame((int)ANIM_STATE.AXE_ON, Game.Time * 30);
        _main_character.SetFrame((int)ANIM_STATE.AXE_OFF, Game.Time * 30);
        _main_character.SetFrame((int)ANIM_STATE.AXE_IDLE, Game.Time * 30);
        _main_character.SetFrame((int)ANIM_STATE.AXE_ATTAK, Game.Time * 30);
        _main_character.SetFrame((int)ANIM_STATE.AXE_STEP, Game.Time * 30);
       
        //достаём топор
        if(Input.IsKeyDown(Input.KEY.F1))
            STATE = ANIM_STATE.AXE_ON;
        //убираем топор
        if(Input.IsKeyDown(Input.KEY.F2))
            STATE = ANIM_STATE.AXE_OFF;
        //анимация простоя
        if(Input.IsKeyDown(Input.KEY.F3))
            STATE = ANIM_STATE.AXE_IDLE;            
        //атака топором
        if(Input.IsMouseButtonDown(Input.MOUSE_BUTTON.LEFT) && (STATE == ANIM_STATE.AXE_IDLE || STATE == ANIM_STATE.AXE_STEP))
            STATE = ANIM_STATE.AXE_ATTAK;  
 
        AnimCharger();
 
        _weight = MathLib.Clamp(_weight + Game.IFps, 0f, 1f);      
    }
 
    float _t;
 
    void AnimCharger()
    {
        switch (STATE)
        {
            //достаём топор
            case ANIM_STATE.AXE_ON:
                ResetWeight(); PREV_STATE = ANIM_STATE.AXE_ON;
                _main_character.LerpLayer((int)ANIM_STATE.PROCEDURAL, (int)PREV_STATE, (int)ANIM_STATE.AXE_ON, _weight);            
            break;
            //анимация во время простоя
            case ANIM_STATE.AXE_IDLE:
            if(!Input.IsKeyPressed(Input.KEY.W)){ ResetWeight(); STATE = ANIM_STATE.AXE_STEP; PREV_STATE = ANIM_STATE.AXE_IDLE;}
                _main_character.LerpLayer((int)ANIM_STATE.PROCEDURAL, (int)PREV_STATE, (int)ANIM_STATE.AXE_IDLE, _weight );
            break;
            //анимация во время ходьбы
            case ANIM_STATE.AXE_STEP:
            if(Input.IsKeyPressed(Input.KEY.W)) {ResetWeight(); STATE = ANIM_STATE.AXE_IDLE; PREV_STATE = ANIM_STATE.AXE_STEP;}
                _main_character.LerpLayer((int)ANIM_STATE.PROCEDURAL, (int)PREV_STATE, (int)ANIM_STATE.AXE_STEP, _weight );
            break;
            //убираем топор
            case ANIM_STATE.AXE_OFF:
                if(!Input.IsKeyPressed(Input.KEY.W)) {ResetWeight(); PREV_STATE = ANIM_STATE.AXE_IDLE;}
                if(Input.IsKeyPressed(Input.KEY.W)) {ResetWeight(); PREV_STATE = ANIM_STATE.AXE_STEP;}
                _main_character.LerpLayer((int)ANIM_STATE.PROCEDURAL, (int)PREV_STATE, (int)ANIM_STATE.AXE_OFF, 1);
            break;
            //атакуем топором
            case ANIM_STATE.AXE_ATTAK:
                _main_character.LerpLayer((int)ANIM_STATE.PROCEDURAL, (int)PREV_STATE, (int)ANIM_STATE.AXE_ATTAK, _weight);
            break;
 
            default:
                break;
        }
    }
 
    void ResetWeight()
    {
        _is_weight_charget = true;
        if(_is_weight_charget){ _weight = 0; _is_weight_charget = false;}
    }
}

Ну и скрин:

image.thumb.png.f4857276cf2269803fc877fbdc759d0f.png

 

 

Posted

Что бы узнать когда заканчивается анимация нужно узнать какой кадр сейчас утановлен. Это можно посчитать отстатком от деления текущего кадра на количество кадров анимации:

_main_character.GetFrame(0) % _main_character.GetNumFrames(0)

Рывок анимации может быть из-за того что, при переключении анимации вес слоя сбрасывается резко в 0. Лучше сделать плавное уменьшения веса:

 _weight = MathLib.Clamp(_weight - Game.IFps, 0f, 1f);

  • Thanks 1
Posted

yingaz

Спасибо за ответ!  Кое-что стало получаться, думаю допилю переходы. Сильно помогла эта строчка: 

_main_character.GetFrame(0) % _main_character.GetNumFrames(0)

Правда, попутно, назрел еще один вопрос: как к костям (или заскиненным мешам) привязать ноду?  Например, у меня на руках висят наручные часы. Они показывают время суток. Скрипт для движения стрелок готов. Но как привязать наручные часы к предплечью?  Я вижу что можно нодами управлять костью,  используя Create Dummy Hierarchy. А наоборот? Или я что-то недопонял? Любая наводка пригодиться! 

Спасибо! 

Posted

silent 

Спасибо! То что нужно)

×
×
  • Create New...