Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
13
Help us understand the problem. What is going on with this article?
@toRisouP

【Unity】 AnimatorのTriggerをBoolを使って再現する

More than 5 years have passed since last update.

UniRxについての記事のまとめはこちら


やりたいこと

  • PhotonAnimatorViewを使ってTriggerの同期がしたい
  • ただし現時点でTrigger同期は未対応
  • 仕方がないのでAnimatorのBoolを使ってTriggerを再現する

そもそも「Trigger」とは

  • 基本はBoolと同じ
  • ただしTrueにすると自動的にFalseに戻る性質がある
  • 一瞬だけ動作するアニメーションに切り替える時等によく使う

つまり、BoolにTrueを設定したら次フレームでFalseに書き換えてやればよい

作ってみた

私は何でもコンポーネントに分割する派なので、今回はアニメーション管理コンポーネントを作り、そこにTrigger機能を持ったメソッドを作りました。
外から「SetTriggerAttackA」「SetTriggerAttackB」を実行すれば、アニメーション遷移するようにしてあります。

PlayerAnimationController.cs
[RequireComponent(typeof (Animator))]
public class PlayerAnimationController : MonoBehaviour
{
        private enum AnimatorParameters
        {
            IsAttackA,
            IsAttackB
        }

    private Animator _animator;

    /// <summary>
    /// Actionデリゲートを流すSubject
    /// </summary>
    private Subject<Action> _actionSubject = new Subject<Action>();


    private void Start()
    {
        _animator = GetComponent<Animator>();

        //1フレーム遅延させてActionデリゲートを実行
        _actionSubject.DelayFrame(1).Subscribe(x => x());
    }

    /// <summary>
    /// 攻撃アニメーションA開始
    /// </summary>
    public void SetTriggerAttackA()
    {
        //IsAttackATriggerをTrueにする
        _animator.SetBool(AnimatorParameters.IsAttackA.ToString(), true);
        //IsAttackATriggerを次のフレームでFalseにする
        _actionSubject.OnNext(() => _animator.SetBool(AnimatorParameters.IsAttackA.ToString(), false));
    }

    /// <summary>
    /// 攻撃アニメーションB開始
    /// </summary>
    public void SetTriggerAttackB()
    {
        //IsAttackBTriggerをTrueにする
        _animator.SetBool(AnimatorParameters.IsAttackB.ToString(), true);
        //IsAttackBTriggerを次のフレームでFalseにする
        _actionSubject.OnNext(() => _animator.SetBool(AnimatorParameters.IsAttackB.ToString(), false));
    }
}

処理を次フレームに持ち越す方法

Trueにした次のフレームでFalseにする」といった処理はUniRxを使って実現しています。
Actionデリゲートを流せるSubjectを生成し、それにDelayFrame(1)を挟むことでフレームを遅延させてSubscribeでActionデリゲートを実行するようにしています。

UniRxを使った遅延実行
private void Start()
{
    _animator = GetComponent<Animator>();

    Subject<Action> _actionSubject = new Subject<Action>();

    //1フレーム後にActionデリゲートを実行する
    _actionSubject.DelayFrame(1).Subscribe(x => x());

    Debug.Log(string.Format("Startで実行:{0}",Time.frameCount));

    //_actionSubjectに流したActionデリゲートが次フレームで実行される
    _actionSubject.OnNext(() => Debug.Log(string.Format("1フレーム後に実行:{0}", Time.frameCount)));
}
実行結果
Startで実行:1
1フレーム後に実行:2

まとめ

ちゃんとTriggerと同じ挙動をしてくれました。
やはりUniRxは便利ですね(今回の使い方はかなり変則的な方だと思うけど)

ちなみにこの方法で作ったTrigger(中身はただのBool)をPhotonAnimatorViewに食わせたところ、ちゃんと動いてくれました。
ただ同期してくれないタイミングがあったりしたので調査が必要そうです。

3/29 追記

次のフレームに処理を実行するならObservable.NextFrameを使うだけで良さそうです

public void SetTriggerAttackA()
{
    _animator.SetBool("IsAttackATrigger", true);
    Observable.NextFrame()
        .Subscribe(_ => _animator.SetBool("IsAttackATrigger", false));
}
13
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
toRisouP
virtualcast
VRシステム(バーチャルキャスト)の開発、運営、企画

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
13
Help us understand the problem. What is going on with this article?