Unity Animator.Play, как перейти на другую анимацию одновременно - PullRequest
0 голосов
/ 04 февраля 2019

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

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

Вот пример грубого примера моего кода:

if (!shooting) {animator.Play("PlayerRunning");}

if (shooting) {animator.Play("PlayerRunningShoot");}

Я думаю, что лучшим примером будет одна из анимационных съемок мегаман в играх NES, где, когда вы нажимаете «B» во время бега, его рука немедленно поднимается, чтобы выстрелить.

Если что-то из этого запутано, дайте мне знать.

1 Ответ

0 голосов
/ 04 февраля 2019

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


Однако Animator.Play имеет необязательный параметр

normalizedTime : Смещение по времени от нуля до единицы.

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

вы можете использовать Animator.GetCurrentAnimatorStateInfo, чтобы получить текущее состояние, а normalizedTime текущий клип в

и Animator.GetCurrentAnimatorClipInfo чтобы получить информацию (например, длину) клипа.

И либо укажите ваш целевой клип (я бы предпочел это), либо вы можете использовать Animator.runtimeAnimatorController, чтобы получить все AnimationClip с, а затем использовать LinQ FirstOrDefaultчтобы найти тот с целевым именем:

(набрав это на моем смартфоне, так что никаких гарантий)

using System.Linq;

// ...

if (!shooting)
{
    // assuming layer 0
    var state = animator.GetCurrentAnimatorStateInfo(0);
    var clipInfo = animator.GetCurrentAnimatorClipInfo(0);

    // so the time you want to start is currentNormalizedTime * current.length / newClip.length
    // if your clips will always have the exact same length of course you can
    // simply use the currentNormalizedTime
    var currentNormalizedTime = state.normalizedTime;
    var currentRealtime = currentNormalizedTime * clipInfo[0].clip.length;

    var newClip = animator.runtimeAnimatorController.animationClips.FirstOrDefault(c => string.Equals(c.name, "PlayerRunning"));

    var newNormalizedTime = currentRealtime / newClip.length;

    // for some reason it seems you can not use the optional parameters as you usually would
    // like ("PlayerRunningShoot", normaizedTime = newNormalizedTime)
    animator.Play("PlayerRunning", -1, newNormalizedTime);
}

if (shooting)
{
    var state = animator.GetCurrentAnimatorStateInfo(0);
    var clipInfo = animator.GetCurrentAnimatorClipInfo(0);
    var currentNormalizedTime = state.normalizedTime;
    var currentRealtime = currentNormalizedTime * clipInfo[0].clip.length;

    var newClip = animator.runtimeAnimatorController.animationClips.FirstOrDefault(c => string.Equals(c.name, "PlayerRunning"));

    var newNormalizedTime = currentRealtime / newClip.length;

    animator.Play("PlayerRunningShoot", -1, newNormalizedTime);
}

Вы также можете создать плавный переход во время выполнения, используя

Animator.CrossFade или Animator.CrossFadeInFixedTime

if (!shooting) 
{
    // ...       

    // here the transition takes 0.25 % of the clip
    animator.CrossFade("PlayerRunning", 0.25f, -1, 0, newNormalizedTime);
}

if (shooting) 
{
    // ...

    // here the transition takes 0.25 seconds
    animator.CrossFadeInFixedTime("PlayerRunningShoot", 0.25f, -1, 0, newNormalizedTime);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...