質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.22%

AnimationControllerで指定したオブジェクトだけアニメーションさせたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 2,557

silverman

score 6

Unityアニメーションについての質問です。

一つのAnimationControllerを複数のオブジェクトで共有したいと考えています。
指定した一つのオブジェクトだけ再生を行いたいのですが、全てのオブジェクトで同時にアニメーションが再生されてしまいました。
以下のスクリプトを動かしたいオブジェクト全てに適用しています。

using UnityEngine;

public class animation : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
        GetComponent<Animator>().Play("ステート名");
    }
}


AnimatorControllerを共有した状態で、アニメーションをオブジェクト別に制御することはできるのでしょうか。

環境はUnity5.6、c#です。オブジェクトにはfbx、モーションにはvmdを使用し、mmd4mechanimを使いfbxに変換してAnimationControllerに取り込んでいます。
ご存知の方よろしければ回答お願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • fiveHundred

    2017/08/05 17:02

    ソースの記述が足りないです。 「GetComponent<Animator>().Play();」はどこに書いているのでしょうか? あと、「モーションにはvmd」とありますが、vmdは直接使えないですよね? MMD4Mecanimを使っているのでしょうか?

    キャンセル

回答 2

+1

コメントの通り、ソース1行ではなんとも言えませんので、推測ですが、

  1. 1体目のGetComponent<Animator>().Play();によって、1体目のアニメーションが再生される。
  2. 1体目のアニメーションが終わりまで再生される。
  3. 2体目のGetComponent<Animator>().Play();によって、2体目のアニメーションが再生される。
  4. 2体目のアニメーションが終わりまで再生される。
  5. (以下省略)

と考えたのかもしれません。

しかし、GetComponent<Animator>().Play();はアニメーションの終わりまで待つという処理はありません。
よって、アニメーションの終わりになっているかどうかを検知してから、次のGetComponent<Animator>().Play();を実行する、といったことをする必要があります。

アニメーションの終わりになっているかどうかについては、以下のページが参考になると思います。
http://tsubakit1.hateblo.jp/entry/2016/02/11/021743


追記:
void Update()内に書かれた処理は、アタッチされた全てのオブジェクトごとに、毎フレーム実行されます。
よって、アタッチされた全てのオブジェクトで同時に再生されてしまうのは当たり前です。
正直、Update()内に直接書いている時点で、プログラミングをあまり理解していないとしか思えないです。
まずは基本的なことから、プログラミングを理解しましょう。

Animator.Play()を使って、アニメーションをオブジェクト別に制御することは出来ます。
制御の方法については、すごくざっくり言うと、「○○だったとき、Playする」といった感じです。
実装に必要な知識を挙げてみると、以下の通りです(過不足はあると思いますが)。
・if文(ものすごく当たり前ですが)
・「○○だったとき」の○○を取得する方法
・他のオブジェクトにあるComponentを取得・操作する方法


追記2:
解決済みとのことですが、少々問題になりそうな点があったので、追記します。

Update()内に直接書いている時点で~

と言いましたが、これは関数化するべきというわけではありません。
(明らかに誤解を招く表現で申し訳ないです…)
これは、「Animator.Play()は1回呼べば十分なのに、なぜUpdate()で毎回呼んでいるんだ…」ということです。
もし、仮にUpdate()に書くのであれば、このようにif文と組み合わせて書くべきでしょう

    void Update() {
        if (再生したい条件) {
            gameObject.GetComponent<Animator>().Play("ステート名");
        }
    }

また、待機用と再生用の別々のAnimationControllerを用意するよりも、1つのAnimationControllerに待機用のStateと再生用のStateを用意するほうがよいです。
以下、サンプルソースとAnimationControllerの設定です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AnimationPlayer : MonoBehaviour
{
    bool alreadyPlaying = false;  // 再生済みならtrue

    void Update()
    {
        Animator animator = gameObject.GetComponent<Animator>();
        AnimatorStateInfo animInfo = animator.GetCurrentAnimatorStateInfo(0);
        if (!alreadyPlaying)
        {
            if (!animator.GetBool("playFlag"))
            {
                animator.SetBool("playFlag", true); // 再生
            }
            else if (!(animInfo.normalizedTime < 1.0f))
            {
                animator.SetBool("playFlag", false);    //再生が終了し、待機状態に戻す
                alreadyPlaying = true;
            }
        }
    }
}

AnimationController
全体

wait→play間の矢印
wait→play

play→wait間の矢印
play→wait

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

check解決した方法

0

質問文に具体性がなく分かりづらかったかもしれません。
少々強引ですが、以下の方法で実装することができました。

void Updata()
{
   GameObject gameObject = GameObject.Find("アニメーションさせたいオブジェクト名");
   gameObject.GetComponent<Animator>().runtimeAnimatorController = (RuntimeAnimatorController)Instantiate(Resources.Load("AnimatorController"));
   gameObject.GetComponent<Animator>().Play("ステート名");
   AnimatorStateInfo animInfo = animator.GetCurrentAnimatorStateInfo(0);
   if (!(animInfo.normalizedTime < 1.0f))
   {
      actor.GetComponent<Animator>().runtimeAnimatorController = RuntimeAnimatorController)Instantiate(Resources.Load("Wait"));
   }
}


初期状態を待機用のAnimationControllerに設定しておき、アニメーションさせたいときだけ切り替え、アニメーションの終了を検知したなら待機用のAnimationControllerに戻すことにしました。
当初の目的と若干ずれてしまった気もしますが、一応AnimationControllerを共有した状態で個別にアニメーションさせることができたので自己解決とさせていただきます。
fiveHundredさん、アドバイスありがとうございました。まずは関数化から始めてみようと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/07 15:27

    すいません。Update()内に直接書いている云々は、気にしないでください。提示のソースに「GetComponent<Animator>().Play("ステート名");」しか書かれてなかったので、単に驚いただけです。
    ちゃんと理解しているのであれば、Update()に直接書いて大丈夫です。
    (もちろん、適宜、関数分けすると見やすくなるのでいいと思いますが)

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.22%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる