SpriteStudio / SS5PlayerForUnity

OPTPiX SpriteStudio 5 Player for Unity
http://www.webtech.co.jp/spritestudio/
MIT License
39 stars 15 forks source link

PartsRoot以下に複数のPartsNullが存在した場合のUpdateコール数について #97

Closed ghost closed 9 years ago

ghost commented 9 years ago

2014-12-16 16 27 33

お疲れ様です。 下記の条件の時について質問があります。

親(xx_motion)はPartsRootで、アニメーションを10程所持しています。 親の下(xx1_motion, xx2_motion...)には3つのPartNullが存在し、 それぞれの下には複数のパーツが存在し、Triangle2で構成されています。

この条件の際、例えばanimation1という名前のアニメを再生した際、 animation1はxx1_motionに属しているのですが、 使われていないxx2_motion, xx3_motion以下のパーツのUpdateも呼ばれてしまいます。 パーツが多いため、コールがかなりの量になります。

こういった使われていないものはActiveをfalseにし、Updateが呼ばれないようにしたいのですが、 これを実装するという考えはないでしょうか?

希望としては、例えば画像の例で言いますと、 animation1, 2, 3はxx1_motionに属している animation4はxx2_motionに属している animation5はxx3_motionに属している 等が分かるようになると、こちらで制御が可能になるかと思います......。

ghost commented 9 years ago

すみません、こちら解決出来そうなので一度閉めます。

SpriteStudio commented 9 years ago

回答が遅くなってしまい申し訳ありません。

解決できそうとのことで良かったです! よろしければ後続の方のためにもその手法を共有していただけると大変ありがたいです。

入れ違いになってしまいましたが、ご用意した回答をお知らせします。

こういった使われていないものはActiveをfalseにし、Updateが呼ばれないようにしたいのですが、これを実装するという考えはないでしょうか?

更新が不要なパーツのGameObjectに対してActive 状態を切り替えるといった機能を実装する予定は残念ながらありません。 active 状態を再生中に切り替える処理コストが大きいことと、更新の要不要を監視するコードの追加もまた パーツ数に比例して処理コストが多くかかってしまい、多くのケースでは不要な処理になってしまうからです。 ご了承いただけますと幸いです。

希望としては、例えば画像の例で言いますと、 animation1, 2, 3はxx1_motionに属している animation4はxx2_motionに属している animation5はxx3_motionに属している 等が分かるようになると、こちらで制御が可能になるかと思います......。

上記の状況で、属しているか?を調べる機能なども残念ながらご用意しておらず実装の予定もありません。

今回頂いた要望を実現するには、SSAE内の各アニメーションのrootパーツの最初のフレームに、 「このアニメーションは、どの子NULLノードを使ってます」 という番号を入れておいて、 「その番号をコールバックで取得して、他の子NULLノードはactiveをdisableにする」 という方法が低コストで行うのによいと思われます。

ただし「Updateが回って重い」規模のデータとなると、activeの切り替えに非常に多く時間がかかると思います。 (※定かではありませんが、各ノードの並列処理を全て止めて・並列処理オブジェクト列の組み直しをUnity内部で行っていたように思います)。 場合によっては数フレーム、一瞬デッドロックしたのかと思うような間ができるかもしれません。

したがいまして、既にお試しかもしれませんが、xx1_motion, xx2_motion, xx3_motion 単位でSSAEファイルを分割する方法が、メモリ消費量や、実行時間のコストから見ても有利になると考えられます。

多少なりともご参考になれば幸いです。

ghost commented 9 years ago

返信ありがとうございます。

「このアニメーションは、どの子NULLノードを使ってます」 という番号を入れておいて、 「その番号をコールバックで取得して、他の子NULLノードはactiveをdisableにする」 という方法が低コストで行うのによいと思われます。

正にこんな感じで実装しました。 フレームの開始番号を元に、XMLパース時にいくつかの情報を追加しました。 これを実際に行うと、下記の画像のように、ScriptRootのエディター拡張から情報が見えるようになっています。 2014-12-17 14 55 59

画像で言いますと、左側がアニメーション名で、右側がPartsNULLのオブジェクト名となっています。

active 状態を再生中に切り替える処理コストが大きいことと、 更新の要不要を監視するコードの追加もまた パーツ数に比例して処理コストが多くかかってしまい、 多くのケースでは不要な処理になってしまうからです。

PartNULLさえOffにすれば、Unityでは子オブジェクトもOffになりますので、 そこまでコストが掛かるか。と言うと、そこまでかからないです。

また、SS再生用のラッパーをしっかりと実装すればある程度柔軟なことも出来るようになります。 今回実装した内容だと、FPSで言えば5~7上昇した程度ですが、 少しでも上昇したのは良かったかなと思っています。

また、正直な事を言えば、

既にお試しかもしれませんが、xx1_motion, xx2_motion, xx3_motion 単位で SSAEファイルを分割する方法が、 メモリ消費量や、実行時間のコストから見ても有利になると考えられます。

この通りだと思っており、パーツを分割しすぎたことや、1つにまとめすぎたのも原因だったかなと感じています。 今のプロジェクトではSpriteStudioにまだ慣れていないこともあり、 プログラム的に解決することが多くなってしまった気がします。

ご希望であれば、サンプルコードをお渡ししますので、 気軽に言って頂ければと思います。 (コード整理に少し時間をいただくかと思いますが)

ちょっとしたことですが、 ArrayListを多様しているように見えますが、 List型を使うといいと思います。 毎回キャストをやっており、パフォーマンスに影響を及ぼしてしまいます。

MasamiYitsuse commented 9 years ago

takumi-hatta様

お世話になっております。

ちょっとしたことですが、 ArrayListを多様しているように見えますが、 List型を使うといいと思います。 毎回キャストをやっており、パフォーマンスに影響を及ぼしてしまいます。

ご助言ありがとうございます。 本件(ランタイム側のArrayListで記載されている部分をListに変更すること)に関しては、以前から懸案をしているのですが……現在、描画マネージャ部の基底処理で、現在他のユーザー様から頂いているご要望等や、想定している追加仕様などの実装の兼ね合いから、現状(Listで統一できるかの確証がないため)ArrayListを使用しているままになっています。

そちらの追加仕様などの実装時に、Listに置き換えて問題がないようでしたら、一緒に行ってしまおうと現状考えております。

そう遠くない先でそれらの追加仕様などの実装作業を行うつもりではおりますので、少々(正式にラインタイム側のArrayListの処理をListの形に変更可能かどうかの判断と)実装をお待ち頂けますと非常に助かります。 重ねてありがとうございました。

SpriteStudio commented 9 years ago

takumi-hatta さま

FPSがいくらか上昇したとのことでなによりです!

また、サンプルコードご提供の件ありがとうございます! 喜んでお言葉に甘えたいと存じます。 エディタ拡張のみでしたら、本流への取り込みもやりやすいかと思います。

いつでも構いませんので、お手隙の際にお願いできれば幸いです。 PullRequest か、下記メールアドレス宛てに関連ファイルを添付してお送りいくださいませ。 github-spritestudio@webtech.co.jp

他の方法でも問題ございません。

どうぞよろしくお願いいたします。