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

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

ただいまの
回答率

88.83%

拡張エディターからアニメーションクリップの編集

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,379

Yamakagasi

score 9

アニメーションクリップの中身を拡張エディタのスクリプトから編集しようとしています
UnityEditor.EditorCurveBindingの取得はできているようですが、AnimationUtility.GetEditorCurveでエラーが出てしまいます
何が原因と考えられるでしょうか?
イメージ説明

ユニティパッケージ
dlpass : unity

コード全文

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System.Reflection;
using System;

public partial class MakeProj : EditorWindow
{
    [MenuItem("Tools/MakeProj")]
    static void ShowWindow()
    {
    EditorWindow.GetWindow<MakeProj>();
     }


    //================================================================
    void OnGUI()
    {
        if (GUILayout.Button("Set_Clip", EditorStyles.miniButtonRight)) { Set_Clip(); }

    }


    //================================================================
    //アニメーションクリップを編集する
    void Set_Clip()
    {
        int Num_Debug = 1;
        string Temp_Path;
        AnimationClip Temp_Clip;
        AnimationCurve Temp_Curve;
        GameObject Select_Obj = Selection.activeGameObject;

        Temp_Path = "Assets/Anim01.anim";
        Temp_Clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(Temp_Path);
        SetAnimation(Select_Obj , Temp_Clip);
        EditorCurveBinding[] Temp_Bindings = AnimationUtility.GetCurveBindings(Temp_Clip);
        //----------------------------------
        Temp_Bindings[0].path = "a";
        Temp_Bindings[0].propertyName = "m_IsActive";
        Debug.Log(Temp_Bindings[0]);
        Temp_Curve = AnimationUtility.GetEditorCurve(Temp_Clip, Temp_Bindings[0]);
        Temp_Curve.keys[0].value = 1;
        Temp_Curve.MoveKey(0, Temp_Curve.keys[0]);
        AnimationUtility.SetEditorCurve(Temp_Clip, Temp_Bindings[0], Temp_Curve);

        //----------------------------------
        Temp_Bindings[1].path = "b";
        Temp_Bindings[1].propertyName = "m_IsActive";
        Temp_Curve = AnimationUtility.GetEditorCurve(Temp_Clip, Temp_Bindings[1]);
        Temp_Curve.keys[0].value = 1;
        Temp_Curve.MoveKey(0, Temp_Curve.keys[0]);
        AnimationUtility.SetEditorCurve(Temp_Clip, Temp_Bindings[1], Temp_Curve);
    }


    void SetAnimation(GameObject Temp_Obj, AnimationClip Temp_Clip)
    {
        Animation Temp_Anim;
        if (Temp_Obj.GetComponent<Animation>())
        {
            Temp_Anim = Temp_Obj.GetComponent<Animation>();
            DestroyImmediate(Temp_Anim);
            Temp_Anim = Temp_Obj.AddComponent<Animation>();
        }
        else
        {
            Temp_Anim = Temp_Obj.AddComponent<Animation>();
        }
        Temp_Anim.AddClip(Temp_Clip, Temp_Clip.name);
        Temp_Anim.clip = Temp_Clip;
    }
}

エラーメッセージ

NullReferenceException: Object reference not set to an instance of an object
MakeProj.Set_Clip () (at Assets/Editor/MakeSameProject/MakeProj_Main.cs:47)
MakeProj.OnGUI () (at Assets/Editor/MakeSameProject/MakeProj_Main.cs:22)
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:232)
System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115)
UnityEditor.HostView.Invoke (System.String methodName, System.Object obj) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:295)
UnityEditor.HostView.Invoke (System.String methodName) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:288)
UnityEditor.HostView.InvokeOnGUI (Rect onGUIPosition) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:255)

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • Bongo

    2019/04/05 06:27

    「Assets/Anim01.anim」はどのような内容でしょうか?Animationビューのスクリーンショットなどがあると手がかりになるかもしれません。
    またおうかがいしますが、エラーメッセージにある「MakeProj_Main.csの47行目」というのが「Temp_Curve = AnimationUtility.GetEditorCurve(Temp_Clip, Temp_Bindings[0]);」の行である、ということでよろしいでしょうか(ご提示のコードの行を数えてみたところずれてしまっているようで、念のための確認です)。

    キャンセル

  • Yamakagasi

    2019/04/05 16:50

    ありがとうございます!
    画像を追加・プロジェクトもアップロードさせて頂きました
    エラーが出ているのは、その1つ下の行の
    Temp_Curve.keys[0].value = 1;
    のようです

    キャンセル

回答 1

checkベストアンサー

0

画像のみならずファイル類までご用意いただいてありがとうございます。実験が容易になって助かりました。
いろいろ触ってみたところ、おそらく下記のような手順でいけるんじゃないかと思います。

    //================================================================
    //アニメーションクリップを編集する
    void Set_Clip()
    {
        string Temp_Path;
        AnimationClip Temp_Clip;
        AnimationCurve Temp_Curve;
        GameObject Select_Obj = Selection.activeGameObject;
        Temp_Path = "Assets/Anim01.anim";
        Temp_Clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(Temp_Path);

        // 変更を記録させておくと、誤操作してしまっても取り返しがつきそうです
        Undo.RecordObjects(new Object[]{Select_Obj, Temp_Clip}, "Set Clip");

        SetAnimation(Select_Obj , Temp_Clip);
        EditorCurveBinding[] Temp_Bindings = AnimationUtility.GetCurveBindings(Temp_Clip);
        //----------------------------------
        // どうやらバインディングパスが「a」、プロパティ名が「m_IsActive」のカーブを探そうとして、
        // それが存在しないために失敗していたようです
        // まずはTemp_Bindingsに取得されたバインディング情報を書き換えずにそのままカーブを取得し...
        Temp_Curve = AnimationUtility.GetEditorCurve(Temp_Clip, Temp_Bindings[0]);

        // カーブを編集して...
        // (keysは複製された配列を返すので、「取得」→「編集」→「再代入」の手順を踏む必要があるようです)
        Keyframe[] Temp_Keys = Temp_Curve.keys;
        Temp_Keys[0].value = 1;
        Temp_Curve.keys = Temp_Keys;
        Temp_Curve.MoveKey(0, Temp_Curve.keys[0]);

        // もしバインディング先を変えたい場合は、古いカーブは削除し...
        AnimationUtility.SetEditorCurve(Temp_Clip, Temp_Bindings[0], null);

        // Temp_Bindings[0]の書き換えたい項目を書き換え...
        Temp_Bindings[0].path = "a";

        // その新しいバインディング情報を添えてSetEditorCurveを行うという手順になるようです
        AnimationUtility.SetEditorCurve(Temp_Clip, Temp_Bindings[0], Temp_Curve);
        //----------------------------------
        // bの方も同様の手順に変更しました
        Temp_Curve = AnimationUtility.GetEditorCurve(Temp_Clip, Temp_Bindings[1]);
        Temp_Keys = Temp_Curve.keys;
        Temp_Keys[0].value = 1;
        Temp_Curve.keys = Temp_Keys;
        Temp_Curve.MoveKey(0, Temp_Curve.keys[0]);
        AnimationUtility.SetEditorCurve(Temp_Clip, Temp_Bindings[1], null);
        Temp_Bindings[1].path = "b";
        AnimationUtility.SetEditorCurve(Temp_Clip, Temp_Bindings[1], Temp_Curve);
    }


    void SetAnimation(GameObject Temp_Obj, AnimationClip Temp_Clip)
    {
        // 念のため、コンポーネントの追加・削除もUndoに記録させることにしました
        Animation Temp_Anim;
        if (Temp_Obj.GetComponent<Animation>())
        {
            Temp_Anim = Temp_Obj.GetComponent<Animation>();
            Undo.DestroyObjectImmediate(Temp_Anim);
            Temp_Anim = Undo.AddComponent<Animation>(Temp_Obj);
        }
        else
        {
            Temp_Anim = Undo.AddComponent<Animation>(Temp_Obj);
        }
        Temp_Anim.AddClip(Temp_Clip, Temp_Clip.name);
        Temp_Anim.clip = Temp_Clip;
    }


ご提示いただいた当初のプロジェクトファイルの状態だと、オブジェクト「a」や「b」が存在しないためAnimationビュー上の項目が黄色表示になるかと思いますが、オブジェクトさえ用意すればちゃんとバインドされるようでした。
もしかすると、Animationビューを表示しながらSet_Clipを実行しても、すぐにはAnimationビュー上の表示が更新されないかもしれません。Animationビュー上でマウスポインタを動かしたりすると表示も書き換わるかと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

同じタグがついた質問を見る