• Runtimes
  • 加算トラックを使用した際、下位トラックにキーがない場合、セットアップポーズのボーン位置を参照してほしい

こんにちは。いつもお世話になっております。
以前の質問に関連して要望を失礼いたします。

加算トラックを使用した際、下位のトラックにキーが存在しない場合、セットアップの値を参照してほしいです。

以前の質問にて 下位トラックにキーがない場合、加算トラックのプロパティ値が増え続けることは仕様の範囲内ということをご教授頂きました
ただ正直なところ、これ自体がとても扱いづらく、なぜこんな仕様になっているのか分かりません…
理由としては

●1.エディタで事前に検知しづらい
エディタ上では下位トラックにキーがない状況でも値が増え続けることなく、セットアップの値を考慮する作りになっています。
その為、下位トラックにキーがないことに気付きづらいです。
アニメ作成はエディタの動きを見て調整が一般的だと思うのですが、ランタイム側がその仕様から外れているように感じます

●2.汎用的な加算モーションが作りづらい
例えば瞬き、口パク、呼吸の上下運動など加算を前提としたアニメは、特定のボーンのみ操作して
歩行やジャンプといったベースアニメ(下位トラックのアニメ)と組み合わせたいケースがほとんどだと思います。
しかし、それらベースアニメに上位トラックのキーが存在するか常に気にしなければなりませんし、
アニメが量産されていくに連れ、ベースアニメにキーが存在するか存在しないか、把握が困難になっていきます。

●3.新規加算モーションを追加しづらい
新しくボーンを追加して加算モーションを作成する必要があった場合、新規ボーンは既存のアニメにはキーが存在しません。
そのため既存のアニメ全てにキーの打ち直しが発生します。既存のアニメが100以上あった時はとても大変です。

●4.アニメーションクリーンアップと相性が悪い
セットアップと同じ値のキーは、アニメーションクリーンアップで消えるため、セットアップと異なるキーを下位トラックに打たなければなりません。
本来必要のない0.01の移動や回転を入れてキーを増えすことが適切な仕様とは言い難いです

●5.プロパティが加算し続けることにメリットを見いだせない
ランタイム上で下位トラックにキーが無いことによるプロパティ値の無限増加を利用したいケースが思いつきません。

仕様と言ってしまえばそれまでなのですが、どちらかというとシステム上の穴のように感じてしまいます
可能であればSpineエディタと同様に、下位トラックにキー不在の場合はセットアップのプロパティ値を参照する仕様になってくれると大変ありがたいです…。

不躾な要望となってしまいすみません。
ここまで読んでくださってありがとうございます。

    Related Discussions
    ...

    こんにちは。

    ご質問ありがとうございます。加算トラックを使用した際に、下位トラックにキーがない場合にセットアップポーズのボーン位置を参照する仕様についての要望ですね。

    現在の仕様では、下位トラックにキーがない場合、加算トラックのプロパティ値が増え続けることが仕様の範囲内とされています。これは、エディタ上ではセットアップの値を考慮する作りになっているため、ランタイム側での動作と異なることが原因です。

    以下の理由から、セットアップポーズのボーン位置を参照する仕様に変更することを希望されているとのことですね:

    1. エディタで事前に検知しづらい
    2. 汎用的な加算モーションが作りづらい
    3. 新規加算モーションを追加しづらい
    4. アニメーションクリーンアップと相性が悪い
    5. プロパティが加算し続けることにメリットを見いだせない

    この要望は非常に合理的であり、アニメーション制作の効率を大幅に向上させる可能性があります。現時点では仕様の変更について具体的な回答はできませんが、開発チームにフィードバックとして伝えることが重要です。

    koyu2 ご質問・ご要望をいただきありがとうございます。MixBlendAddにしてアニメーションを加算的にブレンドする場合に下位トラックのアニメーションに同じキーが存在する必要がある理由については後ほど別のスタッフから説明があるかと思いますが、ただ一般的にMixBlendAddに変更してアニメーションを適用することはそれほど多くのケースでは必要ないということをまず補足しておきたいと思います。

    特に例に挙げていただいたような、まばたきや口パクなどのアニメーションを他のアニメーションと一緒に再生したい場合、多くの場合は加算ブレンディングをする必要がありません。
    そもそもトラックを使って複数アニメーションを再生する場合、デフォルトのReplaceのままであっても上位トラックが下位トラックのアニメーションのポーズを上書きしますので、単に複数アニメーションを同時に再生したいだけの場合はAddを利用する必要はありません。
    (Replaceの場合は全てのプロパティをキーにする必要はありません。)

    では加算ブレンディングが必要な場合がいつかというと、基本的にはTrackEntryのalphaを使用して複数のアニメーションの適用割合を調整しながらブレンドしたい場合になります。具体的には、こちらのOwlの例のように特定の条件でアニメーションの適用割合が増えたり減ったりするようにしたい場合に便利です。Owlの例のコードは以下で確認できます:
    EsotericSoftware/spine-runtimesblob/c85000b5f81bd93bcdd9cd2ae6e3789ac2907492/spine-ts/spine-webgl/demos/additiveblending.js#L46-L59

    Owlの例はマウスカーソルの位置を元に、トラック2、3、4、5にセットされたleftrightupdownのアニメーションのアルファ値が変化するように組まれています。
    正確にはMixBlendAddにしなくてもアルファ値の変更自体は可能ですので、Owlがマウスカーソルの位置に合わせて動くようにすることができますが、斜めの部分(leftupなど2つのアニメーションが混ざる部分)で結果が異なります。

    カーソルがほぼ同じ位置にある状態で比較すると以下のようになります:

    デフォルトのReplaceのままだと単にupアニメーションのアルファが上がってそちらが優先されていきますが、Addの場合は下位トラックのleftのポーズとupのポーズが加算されて斜めのポーズが出来ます。このような結果が欲しい場合にはAddを利用するのが便利です。

      Spine doesn't automatically set all values every frame. Animations only change values that are keyed. There can be many properties and setting them all would be wasted effort if something else is just going to set them to a new value.

      That usually doesn't matter, but if you are applying additive animation then it does. You can either set an animation on a lower track that sets all the properties that you will apply additive animations for, or you can reset everything every frame, eg using Skeleton setToSetupPose. If you are annoyed by needing to reset all the properties, then setToSetupPose is probably what you want.

        • Edited

        Misaki Nate

        Misakiさん、Nateさん。お返事ありがとうございます。

        私は下位トラックにプロパティがないと、値が増加し続ける仕様は
        加算ブレンドのメリットと存在意義を大きく損なっていると思います。
        この認識に開発者の方とギャップがあると思うので、具体的なユースケースを提示します

        ■加算ブレンドを使うケースは多い

        左のプレビューは、通常より目を細め考え事をしている「Thinking」アニメです
        右は汎用的な瞬きアニメです。Track0のアニメと合成してキャラに瞬きを追加します。
        これをMixBlend:Replaceで組み合わせてみます。
        (0:08~)
        すると目を大きく開き表情が変化してしまいました。
        Replaceは下位トラックを上書きするため、柔軟に対応できないケースが多いです。
        (0:21~)
        加算でブレンドしたアニメは相対変化のため、Track0の表情を変えずに瞬きが実現できています。

        Unityで確認します。
        Thinking&瞬きは問題がありません。
        しかし、瞬きのような汎用アニメは多くのアニメと組み合わせるためにあります。
        防御態勢を取る別のモーション「Guard」との組み合わると、瞬きの度に加算が繰り返され奇妙な絵ができました。
        Guardは瞬きのボーンを操作しないためプロパティがないからです。
        これはSpineエディタでは確認できず、ランタイムでテストをして初めて気付く問題です。

        ■複数の要因が重なって対処が困難

        それではGuardアニメに瞬きボーンのキーを予め打っておくべきでしょうか?
        しかし前述の通り、セットアップと同じプロパティはアニメーションクリーンアップで消えます。
        そのため僅かに動かしたクリーンアップで消えないキーを0フレーム目に打つ作業が要求されます
        Guardだけでなく、待機、歩行、しゃがみなど多岐にわたり、今後も増え続ける新しいモーション一つ一つに、本来不必要なセットアップポーズとほんの僅かに異なる値を入れていく工程が発生します

        別のケースでは呼吸モーションがあります。
        上半身がわずかに膨らみ上下する単純なものですが、多くのアニメと組み合わせられそうです。
        Replaceではポーズが崩れるため、加算ブレンドが必要です。

        呼吸モーションには12個のキーが存在します。
        これらをクリーンアップで消えない値で、下位トラックで再生する既存のアニメ全てをチェックし、キーを使用しているかいないかを把握して打ち直す。もしもキーが増えたり、汎用アニメが新しく必要になる毎に、全アニメ再点検です。でなければいつゲーム中で描画バグが発生するか分かりません。

        それにかかる労力は若干、非現実的に感じます。

        ■加算ブレンドを使用する意義
        私は動かしたいボーンを、下位トラックの位置、回転、スケールなどを考慮せず相対的に動かせることが最大の利点だと思っています。
        Replaceはボーンの稼働範囲を限定する分には有用ですが使用できる状況も限定的です。
        複数のアニメに使い回す汎用モーションを作る場合、加算ブレンドでなければなりません。

        この下位トラックにプロパティがない場合、ランタイムで値が増加し続けるという仕様は、
        エディタとランタイムで動作が異なる時点で混乱を招く上、
        本来下位トラックの状況を選ばず相対的に動かせる加算ブレンドのメリットと利便性を大きく損なっていると感じます。

        eg using Skeleton setToSetupPose. If you are annoyed by needing to reset all the properties, then setToSetupPose is probably what you want.

        SetUptoSetUpPoseとはどのように使用すべきでしょうか?
        現在はこのようにTrack0のアニメを変更する時に使用していますが、アニメのループ中は加算ブレンドのプロパティが増え続けてしまいます。

        ここまで読んでくださってありがとうございます。

          koyu2 SetUptoSetUpPoseとはどのように使用すべきでしょうか?
          現在はこのようにTrack0のアニメを変更する時に使用していますが、アニメのループ中は加算ブレンドのプロパティが増え続けてしまいます。


          すみません、画像を貼り忘れていました。
          このようにTrack0(ベースアニメ)が変更される度にSetToSetUpPose()が走っています

          Your use case for using additive animation does look appropriate.

          You're right it's misleading that the editor doesn't show the ever increasing values from additive animation. We have an issue for improving that. The editor does the equivalent of setToSetUpPose.

          You need to call setToSetUpPose every frame, before applying your animations. It's not enough to call it only when animations change.

          koyu2 加算ブレンディングを使用する例について詳しく説明していただき誠にありがとうございます。最初の返信の中でこのようなケースがあることについて考慮できておらずに申し訳ありません。

          Nateが既に返信している通り、このようにたくさん加算ブレンディングを使用する場合にはアニメーションにキーを追加するよりも setToSetUpPose を毎フレーム呼び出すようにした方が良いですが、ただアニメーションのクリーンアップについては補足があります。
          最初にお伝えしていれば良かったのですが、アニメーションの レイヤード のプションにチェックが入っている場合はクリーンアップを実行しても0フレーム目にあるキーはセットアップポーズと同じ値を持っていても保持されます。

          なのでクリーンアップでキーが消えてしまわないようにするための手間に関しては、レイヤードを使うことである程度解消できますが、ただ無駄なキーが多くなってしまうとスケルトンデータの容量が増えてしまう要因になるため、このスケルトンのように多数のアニメーションで加算ブレンディングを行う場合は setToSetUpPose を毎フレーム呼び出すのが最も簡単な解決策になると思います。

          プレビュー上で問題が確認できないのはおっしゃる通り不便だと思いますので、Spineチーム内で改善のためにどのような方法を取るのが良いのかについて議論しています。

          Nateさん、MIsakiさん。お返事ありがとうございます!
          詳しい解説を頂けて助かります。

          setToSetUpPose について
          UpdateにSetToSetUpPoseを入れてみたところ、プロパティの加算問題は解決したのですが、右のキャラクターのように描画順序や手首、表情などのアタッチメントの切り替えがセットアップポーズになってしまいます。
          (右のキャラクターはSetToSetUpPoseをUpdateで適用しており、左は適用していません)

          コードはこのようになっています。
          APIのSkeleton Methodsではボーンやスロット描画順をセットアップに戻すとあるので、毎フレームセットアップに戻っているのかと思いますが、その場合描画したいアニメのアタッチメントや描画順はどのように維持すべきでしょうか? 
          ボーンは描画したいアニメのポーズが維持されているので挙動がよく分かりません。
          使用方法が間違っていますでしょうか? お手数おかけしますがお願いいたします。

          レイヤードのチェック項目のご紹介もありがとうございます!
          わずかに値の違うキーを入れる手作業がかなり大変なのでこちらも活用させていただきますね!

          本スレッドに関連したバグ報告です。

          教えて頂いた、0フレーム目のキーをクリーンアップで消さないレイヤードですが、エクスポート設定のアニメーションクリーンアップで機能していないように見えます。

          上記のようにレイヤードにチェックを入れたTestLayerdアニメがあります。
          heartはセットアップから動かさずにキーを打っています
          starは0フレームはセットアップから動かさず、30フレームにセットアップと異なるキーががあります
          spadeは0フレームにセットアップと異なるキーを打ちました。

          これをアニメーションクリーンアップありでJsonでエクスポートしたのが上記の画像です。
          ご覧のようにstarとspadeの項目はありますが、heartの項目は消えています。

          レイヤード項目のすぐ下にあるクリーンアップボタンでは消えずにレイヤードが機能するのですが、エクスポートのクリーンアップでは機能しないのは非常に分かりづらく、ゲーム中の描画バグの原因特定と対処を困難にします…。

          エクスポート設定のクリーンアップへの対応をご検討いただけましたら幸いです

          In 4.2.37 we have fixed Layered not being respected during export. Thanks for letting us know!

          As for when to call SetToSetupPose, it needs to be before applying animations. I think you are calling it after applying animations, so you are losing what the animations set. Our Unity expert Harald would normally explain how to do this, but unfortunately he is unavailable today due to a personal emergency. I can only try to help: SkeletonAnimation Update is the method that applies animations. Likely you need to override the method, call SetToSetupPose, then call the original Update method.

          @koyu2 I'm sorry for the late reply! It is actually possible with just your script, without the need of writing a subclass of SkeletonAnimation and overriding Update.

          In order to call skeleton.SetToSetupPose() at the right time before SkeletonAnimation.Update, you need to ensure that the script execution order of your script (TestSpineAnim) is set to execute before the SkeletonAnimation component.

          You can either change script execution order via Project Settings in Unity, or by adding the following attribute to your class:

          [DefaultExecutionOrder(-1)]
          public class TestSpineAnim : ChrSpineView
          {
             ...
          }

          Also see the recently added Unity documentation here.

          こんばんは。Nateさん、Haraldさん。
          お返事ありがとうございます!

          >Layeredについて

          迅速なご対応ありがとうございます!
          アニメーションクリーンアップはエクスポート時に使用していたのでとても助かります。
          4.2.37のSpineで活用させていただきますね!

          >SetToSetUpPose

          DefaultExecutionOrderを使用して、実行順序を-1してみました。
          左はSetToSetupPose未使用、右が使用したものです。
          SetToSetUpPoseを使用しつつ期待されたアタッチメントの変更や描画順序の描画が実現できました!
          ご助言に感謝します!

          気になるところがあるとすれば、毎フレームごとのSetToSetUpPoseにかかる処理負荷が、どの程度パフォースマンスに影響するかでしょうか。
          しかし、プロパティの増加によるキャラクター崩壊を防ぐことができるメリットはとても大きいです。
          既存のベースアニメと今後量産されるアニメ一つ一つに、同じく量産されていく加算ブレンドアニメ全ての組み合わせでプロパティ確認と修正する労力は現実的ではありませんでした。

          これで安心して加算ブレンディングを使うことができます!

          ユースケースの一つとしてヘルスが減って疲れたゴブリンを作ってみました!

          右は通常より大きく息を切らせた呼吸のアニメです。
          加算ブレンドを使用して、戦闘態勢、歩き、走り、待機、しゃがみといったポーズの異なるアニメに対して、疲労呼吸アニメ一つでバリエーションが増やせました。
          プロパティの無限増加に怯えずアニメを作れるのでとても助かります!

          たくさんのサポートをくださってありがとうございます!
          スタッフの皆さんとSpineに乾杯🍺

          @koyu2 Glad to hear it helped, thanks for getting back to us!

          Regarding the impact on performance:
          Skeleton.SetToSetupPose() is calling SetBonesToSetupPose() and SetSlotsToSetupPose(), as you can see in the code here. As you only need to reset bone locations and don't need to reset slots (slot color) or the active attachment at the slots, you could actually just call Skeleton.SetBonesToSetupPose(). This avoids unnecessary computation and reduces the overhead.

          Regarding the overhead of SetBonesToSetupPose: it should be low and not really noticable, as it's just copying values for each bone and not performing (or leading to) any expensive computations.

          SetToSetupPoseのパフォーマンスについて解説してくださってありがとうございます!
          Skeleton.SetBonesToSetupPose()に記述を変えてみたところ、こちらでもキャラクターのアニメは問題なく描画されていました!こちらを活用させていただきますね。
          計算自体も負荷が高くないとのことで助かります。

          ご助言ありがとうございます✨

          Glad to hear it helped, thanks for getting back to us!