SpriteStudio / SS5PlayerForUnity

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

全般 プログラムからのアニメーション制御について #114

Open aki017 opened 9 years ago

aki017 commented 9 years ago

Prefabをプログラムから初期化して使う場合、最初に再生するアニメーションを指定することはできないのでしょうか? 現状以下のコードがエラーとなっており回避方を探しております。

var go = (GameObject)Instantiate(Prefab);
var anim = go.GetComponent<Script_SpriteStudio_PartsRoot>();
anim.AnimationPlay(0);
MasamiYitsuse commented 9 years ago

aki017様

お世話になっております。 エラーというのが何を指しているのか、具体的に把握しかねておりますので、類推を交えて返信させていただきます。

恐らく上記のprefabに与えているのは、「(ssae名)_Control」のプレハブ(またはそれをシーン上で実体化したもの)……だと推測しています。 その前提で……恐らくエラーというのはanimにnullが返って来てしまい、メモリ参照例外が出るのではないかと予想しております。

その件につきましては、

GitHub内Wikiの中にある「スクリプトリファレンス」 https://github.com/SpriteStudio/SS5PlayerForUnity/wiki/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9

の中にある「制御用GameObject等からのScript_SpriteStudio_PartsRootの取得」 https://github.com/SpriteStudio/SS5PlayerForUnity/wiki/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9:-Script_SpriteStudio_PartsRoot%E3%81%AE%E5%8F%96%E5%BE%97

をご参照頂けますと(サンプルがC#で記載されているのが申し訳ございませんが)、解決できるのではないかと思われます。

お忙しい中お手数とは存じますが、何卒宜しくお願い致します。


補足: 一応、上記Wiki内リファレンスのサンプルコードをJavaScriptに移植してみました。 ただ、私がJavaScriptが得意でないため、ミスもあるかと思いますが、その点についてはご容赦の程お願い致します。

クラス内変数

private var anim : Script_SpriteStudio_PartsRoot = null;

Update関数内

if(null == anim)
{
    var Count : int = go.transform.childCount;
    var tc : Transform = null;
    var i : int;
    for(i=0; i<Count; i++)
    {
        tc = go.transform.GetChild(i);
        anim = tc.gameObject.GetComponent(Script_SpriteStudio_PartsRoot);
        if(null != anim)
        {
            break;
        }
    }
}
……(本来記述すべき処理)……

※本スクリプトを動作させる際には、SS5Player for Unityのパッケージをプロジェクトにインポートした後に、「SpriteStudio」のフォルダを「(Assets/)Standard Assets」内に移動しておく必要があります(JavaScriptでスクリプトを記載する場合、C#で記載されたスクリプトやパッケージ群は「Standard Assets」フォルダ内に格納していないと、UnityとMonoDevelopがC#側のクラスなどを見つけられないという仕様がございます)。

※一応、上記処理は恐らくはStart関数内で記載しても大丈夫だと思いますが(その場合にはanimのnullチェックはいりません)、念のためUpdate関数内で記載してます(様々な設定などの面で、Unity上で本処理をStart関数内で実行する際に、Script_SpriteStudio_PartsRoot.csを持ったGameObjectが安定動作をしているかどうか不明なため、安定動作が保証されているUpdate内で……という考えからです)。


追伸: また、(リファレンス内にある通り)近いうちに既知のバグの解消なども含めてバージョンアップする際に、本Script_SpriteStudio_PartsRootを取得する処理を関数化してユーティリティとして提供させていただく予定がございます。


追伸2: また、上記方法でも上手く動作しない場合、再度ご相談ください。

aki017 commented 9 years ago

ありがとうございます、情報が足りず申し訳ございません。 現在発生している問題はAnimationPlayを呼び出したタイミングで

if((0 > animationNo) || (listInformationPlay.Length <= animationNo))

この部分でlistInformationPlay.Lengthが0に成っており

Library_SpriteStudio.AnimationInformationPlay InformationAnimation = listInformationPlay[animationNo];

ここで範囲外アクセス例外が発生しています。 またPrefabというのはPrefab/の下に生成されるプレハブで、プログラム上で空のゲームオブジェクトのことして初期化しています。

MasamiYitsuse commented 9 years ago

aki017様

お世話になっております。 状況について、詳細なご説明ありがとうございます。 こちらでも検証等いたしますので、少々お時間を下さいますと助かります。

MasamiYitsuse commented 9 years ago

aki017様

お世話になっております。 ちなみに、下記のjsソースを作成して、動作しますでしょうか?

TestJs.js

// #pragma strict

var prefab : GameObject;
private var go : GameObject = null;
private var anim : Script_SpriteStudio_PartsRoot = null;
private var Flag : boolean = false;

function Start()
{
    go = Instantiate(prefab);
    go.transform.parent = transform;

//  var Count : int = transform.childCount;
//  var tc : Transform = null;
//  var i : int;
//  for(i=0; i<Count; i++)
//  {
//      tc = transform.GetChild(i);
//      anim = tc.gameObject.GetComponent(Script_SpriteStudio_PartsRoot);
//      if(null != anim)
//      {
//          break;
//      }
//  }
    anim = go.GetComponent(Script_SpriteStudio_PartsRoot);
}

function Update()
{
    if((null != anim) && (false == Flag))
    {
        anim.AnimationPlay( 0,
                            -1,
                            -1,
                            0.0f,
                            Script_SpriteStudio_PartsRoot.PlayStyle.NO_CHANGE,
                            "",
                            int.MinValue,
                            "",
                            int.MaxValue
                        );
        Flag = true;
    }
}

空のGameObjectをCamera2Dの子のViewの子の位置に作成して、本スクリプトをコンポーネントとしてつけた後に、インスペクタでprefabに作成するPrefabフォルダ内のインスタンスをドラッグ&ドロップして、再生してみてください。 ※JavaScriptの場合、関数の引数の省略時の意味合いがC#とは異なるため、省略記載ではなく、全引数を明示的に指定してみてくださいますようお願い致します。

もし、この記載で動作しない場合、インポートしたプレハブの内容が破損している可能性も捨てきれないので、再度データをインポートしなおしてみていただけますでしょうか?

また、今お使いのSS5Player for Unityのバージョンはいくつになりますでしょうか? 上部メニューの[Tools]-[SpriteStudio]-[About]で出るダイアログで確認が可能です。

お忙しい中お手数ですが、何卒宜しくお願い致します。

MasamiYitsuse commented 9 years ago

aki017様

お世話になっております。 今になって気が付きました。 もう一点確認です。 変数の頭に「var」が付いていたため、勝手に私がJavaScriptだと思ってしまったのですが、記載されているリストはC#でしょうか? (C#3.0でvarが使えることを頭からすっぽり抜けてしまっておりました)

もしC#でしたら、JSのリストでサンプルを出してしまい、大変申し訳ございません。

C#でのスクリプト記載で・Ver.1.2.3以前からSS5PUをお使いいただいていた場合、当該データの格納形式が以前のバージョンのものである可能性が低くないと思われます。 一度、データの再インポートをしてみていただけます様お願い致します。

aki017 commented 9 years ago

SS5Player for Unityのバージョン: 1.2.3 スクリプトについてですがCSharpでした:hash: 検証コード 試してみた結果、事前に初期化したRootの場合エラーにならず表示されました。 これはエンジン側の制約で1フレーム待たないといけないのでしょうか。

MasamiYitsuse commented 9 years ago

aki017様

お世話になっております。 まず、先に、スクリプト言語の件、大変失礼いたしました。申し訳ございません。

検証ありがとうございます。 StartでInstantiateして、Updateで取得可能な件ですが……恐らくスクリプトのMonoに対する実行優先度指定が原因かと思われます。 現在他のスクリプトで更新した位置などのTransfomrの内容をそのフレームで反映するためもあり、Script_SpriteStudio_PartsRoot.csの優先度が0(通常の実行スクリプト)よりも遅く実行するように設定されております。 そのため、通常のスクリプトからInstantiateした直後だと、Script_SpriteStudio_PartsRoot.csのStart関数が実行されておらず、同クラスの内容が未初期化状態になっているため、同クラスの内部ワークなどの設定が行われていないのが原因だと思われます。

そのため、Start関数で実体化した場合、他のスクリプトのStart関数も走った後で、Update関数が呼び出される(はず)のことから、Update関数内での初期再生が成功するのかと思われます。

ですので、もしPrefabのInstantiateをUpdate関数から行った場合、Script_SpriteStudio_PartsRootの取得と再生開始は次の実行時のUpdateで行うのが安全だと思います。

当方の勘違いも含み、お手間をおかけしてしまい、大変申し訳ありませんでした。

aki017 commented 9 years ago

こちらこそ後出しで情報を出したりして申し訳ありませんでした。 仕様となっている旨了解いたしました。 コルーチンなどを利用して一フレーム後で設定するようにします。