SpriteStudio / SS5PlayerForUnity

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

v1.1 基本的なUnity上からの利用方法を教えて欲しい #64

Open Sou107 opened 9 years ago

Sou107 commented 9 years ago

version 1.1 Unity 4.15fx

お世話になります。 こちらが必要としてる情報は、どのようにUnity上で利用するか? です。 データーのインポート等はできており、表示もできています。

あるタイミングで「1回だけ表示する」というエフェクトが目的です。 「トリガーを引くまでアニメーションをしてはならない」 表示した後、また「トリガーを引いたら再び表示をおこなう」

以上が実現したい事です。 1)・プレハブを動的に生成する方法 2)・配置しておいて、必要な時に表示する

2つの方法が考えられます。利点。欠点があります。

1)の方法を利用した場合、アニメーションのスクリプトを管理する必要がなく、表示してそのままオブジェクト毎消せば実現?できる 2)の方法はアニメーションスクリプト上でコントロールする必要がある

2の方法を利用する場合、シーンに以下のように定義して [SerializeField] private Script_SpriteStudio_PartsRoot mInstantReword01 = null; ヒエラルキー上でセットした状態にする

シーンの初期化処理 void Awake () { if (Instance == null) { Instance = this; mInstantReword01.AnimationStop(); mInstantReword01.HideSetForce(true);//非表示 } else { Destroy (this); } }

表示したいタイミングで以下のコード mInstantReword01.HideSetForce(false);//表示 mInstantReword01.AnimationPlay(0 , 1 , -1, 1.0f, (Script_SpriteStudio_PartsRoot.PlayStyle.NORMAL), "",int.MaxValue,"",int.MaxValue);

実際に動かしてみると、再生されません。 初期化の処理を消した場合、アニメーションが表示されます。(データーの問題ではない)

そもそも、このようなアプローチで正しいのでしょうか?

サンプルに入っているのは、データーのみでUnity上からの利用方法が書かれていません。 この部分の情報をもっと頂けると助かります。

以上、よろしくお願いします。

追記:enable でコントロールした場合、trueにしてから大変時間がかかり実用ではない事もご報告します。

Sou107 commented 9 years ago

追記 アニメーションデータのInspactorに Force-Hide というチェックがありますが、プログラムの上からコントロールができていないと思われます。

このチェックを入れないと、インスタンス化(シーンの詠み込みタイミング)で、アニメーションが始まってしまいます。 

以下のコードで、チェックを外して表示される…と思ったのですが、再生されません。 mInstantReword01.HideSetForce(false, true, true);//表示 mInstantReword01.AnimationPlay(0 , 1 , -1, 1.0f, (Script_SpriteStudio_PartsRoot.PlayStyle.NORMAL), "",int.MaxValue,"",int.MaxValue);

このあたりの方法が明示されると、有り難いのですが。

MasamiYitsuse commented 9 years ago

お世話になっております。レポートありがとうございます。

申し訳ございません。 当方で頂いたレポートを元に再検証いたしましたところ、まず、HideSetForceについては、(各スクリプトから)共通で呼び出されているLibrary_SpriteStudio.csのHideSetForce関数の処理にバグがありました。 次のマイナーもしくはメジャーバージョンアップの際に正式に訂正させていただきますが、取り急ぎ同関数を修正したものを下記させて頂きます。 同関数の内容を下記に修正していただけますと、mInstantReword01.HideSetForceの処理が動作すると思われます。 ※対象ノードが、Rootパーツの場合での処理に問題がありました。


(Library_SpriteStudio.cs 275行目からの記述関数)

    public static void HideSetForce(GameObject InstanceGameObject, bool FlagSwitch, bool FlagSetChild, bool FlagSetInstance)
    {
        GameObject InstanceGameObjectNow = InstanceGameObject;
        Transform InstanceTransform = InstanceGameObjectNow.transform;
        Script_SpriteStudio_PartsRoot ScriptRoot = InstanceGameObjectNow.GetComponent<Script_SpriteStudio_PartsRoot>();
        if(null != ScriptRoot)
        {
            if((false == FlagSetInstance) && (null != ScriptRoot.PartsRootOrigin))
            {   /* "Instance"-Object */
                return;
            }
            else
            {
                ScriptRoot.FlagHideForce = FlagSwitch;
            }
        }
        else
        {
            Script_SpriteStudio_Triangle2 ScriptTriangle2 = InstanceGameObjectNow.GetComponent<Script_SpriteStudio_Triangle2>();
            if(null != ScriptTriangle2)
            {
                ScriptTriangle2.FlagHideForce = FlagSwitch;
            }
            else
            {
                Script_SpriteStudio_Triangle4 ScriptTriangle4 = InstanceGameObjectNow.GetComponent<Script_SpriteStudio_Triangle4>();
                if(null != ScriptTriangle4)
                {
                    ScriptTriangle4.FlagHideForce = FlagSwitch;
                }
                else
                {
                    Script_SpriteStudio_PartsInstance ScriptInstasnce = InstanceGameObjectNow.GetComponent<Script_SpriteStudio_PartsInstance>();
                    if(null != ScriptInstasnce)
                    {
                        ScriptInstasnce.FlagHideForce = FlagSwitch;
                    }
                }
            }
            if(true == FlagSetChild)
            {
                for(int i=0; i<InstanceTransform.childCount; i++)
                {
                    HideSetForce(InstanceTransform.GetChild(i).gameObject, FlagSwitch, FlagSetChild, FlagSetInstance);
                }
            }
        }
    }

現状、上記の修正で、ご希望の動作が行えるか、再度ご確認をお願いできますでしょうか? (一応当方で確認した状態ですと、正常に動作しているように見受けられます) ご迷惑をおかけして大変申し訳ございませんが、何卒ご検証の程お願い致します。

また、

1)・プレハブを動的に生成する方法 2)・配置しておいて、必要な時に表示する

この双方については、他のエフェクト類の多さやアプリケーション中での使用頻度・複数生成するか否か等の仕様状態にもよります。 ・複数表示される場合や、使用頻度が低いのであれば、Instantiateのロスを加味したとしても、都度インスタンス化した方が恐らく運用などが行い易い ・常に1つしか同エフェクトが表示されないのであれば、シーン上に設置しておいて、都度HideSetForce/AnimationPlay等を使用し・基準位置となるGameObjectの子として設定するか・座標を移動して運用する方がランタイムロスが少ないと思われます。

以上となります。 重ねてご迷惑をおかけして大変申し訳ございませんが、何卒今後とも宜しくお願い致します。


追伸: すでにご存知とは存じますが、念のため記載させて頂きます。

Awake関数内で他のGameObjectに絡むものを初期化・操作を行うことは、Unityの仕様上なるだけ避けていただけますようお願い致します(Awakeの時点では、他のオブジェクトや自身についている他のコンポーネントなどが初期化や実体化が安定して終了している保障がございません)。 それらの処理については、Start関数ないしはUpdate関数の中で行われることを推奨いたします。

特に、Unityのシーン上、SSからインポートしたアニメーションPrefab(のインスタンス化されたオブジェクト)は、スクリプトがついたGameObjectの子GameObjectとして扱われることも少なくないと思われるため、スクリプトの着いたGameObjectのAwake/Startが実行されている際に、子であるアニメーションPrefabのインスタンスが実体化されて安定動作に入っている保障がありませんため、SSからインポートしたアニメーションデータの制御は、できるだけ(制御側のスクリプトの)Update関数の中で処理していただけることを推奨いたします。

MasamiYitsuse commented 9 years ago

また、初期運用サンプル等が、現在ない点についても、大変申し訳ございません。

オフィシャルのサンプルではなく、(頂いた内容から推測すると喫緊かと思いましたので)恐縮ではございますが

http://befool.co.jp/blog/ayumegu/unity-study-SpriteStudio/

上記URL等でご紹介いただいている方法などが、比較的簡便な運用方法の一つではあります旨、取り急ぎ紹介させて頂きます。

Sou107 commented 9 years ago

ご担当者さまへ

お世話になります。 お返事が遅れてすみません。 修正パッチによって動作する事を確認できました。 素早い対応ありがとうございます。

>Awake関数内で他のGameObjectに絡むものを初期化・操作を行うことは、Unityの仕様上なるだけ避けていただけますようお願い致します 了解しました。

サンプルの件は参考にさせていただきます。

以上、ありがとうございました。

追記:サンプルが欲しいもの  動的にアニメーションをプレハブで表示する方法  カメラを専用のものではなく、既にあるカメラに統合する際に、何を気をつけるべきか?  このとき、VIEWはどのように扱うべきか? 等

MasamiYitsuse commented 9 years ago

ご希望の動作ができたようで、安堵しております。 バグの件、申し訳ございませんでした。 また、サンプルが欲しいものについてご要望ありがとうございます。サンプル作成時の参考とさせて頂きます。

ただ現状、サンプルがない状態ですので、一旦このIssue上でお答えさせて頂きます。

動的にアニメーションをプレハブで表示する方法

これは、通常のUnityのプレハブをシーンに置く行為と近似しています(というより、ほぼ同じです。アニメーション再生を制御するためのコンポーネントを取得するための追加処理があるだけです)。

制御用ノード(「~_control」と名前のついた、位置・拡大・回転などを各種スクリプトから制御するために用意されている、通常運用のためのノードです)ごと置きたい場合、「置きたいプレハブのGameObjectへの参照」を「PrefabNew」としたとして……

GameObject Instance = null;
GameObject InstanceRootParts = null;
Script_SpriteStudio_PartsRoot  ScriptPartsRoot = null;

/* Prefabからシーン上にインスタンスを生成 */
Instance = (GameObject)Instantiate(PrefabNew);

/* 生成したインスタンスを特定のシーン上のGameObjectの子にする(配置) */
Instance.transform.parent = (親にしたいGameObjectのtransform);

/* MEMO: ここまでの時点でシーン上にインスタンスが配置されるはずです */

/* 生成したインスタンスからルートパーツのコンポーネントを得る */
/* MEMO: これを得ないと、アニメーションのコントロールができないため。 */
/* MEMO: Instanceが制御用ノードである場合を想定して、GetChild(0)で強制的に取得していますが、改造したプレハブなどでInstanceに複数の子が付いている場合などには注意して下さい */
InstanceRootParts  = Instance.transform.GetChild(0);
ScriptPartsRoot = InstanceRootParts.GetComponent<Script_SpriteStudio_PartsRoot>(InstanceRootParts);

/* MEMO: このScriptPartsRootの関数を操作することでアニメーションの再生状態などを制御することが可能です */
/* MEMO: 表示位置などを動かす場合、Instance.transformを設定することで実現可能です(InstanceRootPartsのtransformを書き換えても、無効化されてしまいます) */

ザラ書きの(この返信フォーム上で直接書いた)リストなので、コンパイルエラーなどが出るかもしれませんが……大枠上記のような処理でシーン上に配置することが可能です。 (先日参考として出させていただいたURLの方法ですと、あらかじめプレハブの参照を持っているので、ScriptPartsRootを直接取得する必要がないと思われるので、もう少し楽かもしれません)。

制御の処理構造によっては、制御用プレハブをInstantiateした場合、そこについているScript_SpriteStudio_LinkPrefabのStart関数が処理し終わっていないとアニメーション本体のプレハブが実体化しないため、上記のInstanceRootPartsを取得する処理を、次のUpdate時の処理にまわす必要があるかもしれません。


 カメラを専用のものではなく、既にあるカメラに統合する際に、何を気をつけるべきか?

基本的にはOlthoのカメラであれば問題はありませんし、3D空間と同居するような場合(3D空間中のビルボードのような扱いにする場合)はPerspectiveでも構いません。 いずれの場合についても、最終的にカメラから写した時のZ座標がプライオリティの役目もしますので、ClippingPlanesのNearとFarの間に(カメラ投影後のZ座標が)入っていれば、画面に表示されます。

注意: ただし、Z値がNearないしFarの値に近すぎる場合、その位置でX/Y回転を行うと、視錐台(カメラで写すことができる立体範囲……と解釈いただければほぼ正しいです)を越えてしまうピクセルやパーツなどが出てしまい、そのピクセルやパーツは「表示されない」ことになりますので、ご注意下さい(視錐台範囲でクリッピングされてしまう場合が少なくありません)。

 このとき、VIEWはどのように扱うべきか? 等

Viewは、必ずカメラの子(直接の子でなくても構いません)として存在している必要があります。 また、描画されるSpriteStudioのデータは必ず、Viewの子(直接の子でなくても構いません)として配置されている必要があります。 これは、SS5PUの描画最適化マネージャが、Viewに設置されているため、Viewがないと描画されないためです。

基本的に独自のカメラに設置する場合、View3Dというカメラのプレハブがありますが、こちらをカメラの下に設置していただくことで大丈夫です(この「View3D」というViewは、3Dとついていますが、原則ユーザー様独自のカメラの子として設置するためのViewです。ちなみに、Camera2DについているViewと違いはありません)。

カメラは、サンプルとして「Camera2D Pixel(720p)」「Camera2D Pixel(1080p)」の2つがありますが、現実的には、このプレハブを参考にして、作成されているアプリケーションの想定する「ドット・バイ・ドット(最終的に画面に出る時の解像度ではなく、アプリケーションが画面として何ピクセル×何ピクセルの画面を想定しているか……の意味です)」に合うように、改造していただくのも簡便な手の一つです。 ※特にスマートフォンなどの場合、機種毎に解像度が異なりますので、アプリケーションで想定した「ドット・バイ・ドット」で作成された画面が、スケーリング(拡大・縮小)されて出力されることになります。

以上、簡単ではありますが、Sou107様の現時点での一助となれば幸いです。