SpriteStudio / SS5PlayerForUnity

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

v1.1 SpriteStudioのデータを含むGameObjectのDestroyについて #73

Open OpenSesameDevelop opened 9 years ago

OpenSesameDevelop commented 9 years ago

お世話になっております、UnityのGameObject下にSprite Studioのデータを 配置した場合のGameObjectのDestroyについて質問をさせて下さい。

ヒエラルキー上でのツリー状態。 Camera  +View3D   +NodeObj    +SSObj

Camera:カメラ View3D:Sprite StudioのView3D NodeObj:UnityのGameObject SSObj:Sprite Studioのデータ(コントローラ)

この状況でNodeObjに対してDestroyをするとerrorが出てしまいます。 このような使い方には問題があるのでしょうか?

開発環境: Unity4.5.5 MacOS10.9.5 SS5 Player for Unity 1.1

エラーメッセージ: MissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object. UnityEngine.Transform.get_localToWorldMatrix () Library_SpriteStudio+DrawManager+ArrayListMeshDraw.MeshSetCombine (UnityEngine.MeshFilter InstanceMeshFilter, UnityEngine.MeshRenderer InstanceMeshRenderer, UnityEngine.Camera InstanceCamera, UnityEngine.Transform InstanceTransform) (at Assets/SpriteStudio/ScriptLibrary/Library_SpriteStudio.cs:991) Script_SpriteStudio_DrawManagerView.LateUpdate () (at Assets/SpriteStudio/Script/Script_SpriteStudio_DrawManagerView.cs:178)

テストコード: using UnityEngine; using System.Collections;

public class Test : MonoBehaviour {

    // インスペクタでNodeObjをリンク
    public GameObject       m_NodeObj;
    // SpriteStudioのデータをリンク
    public GameObject       m_Prefab;

    void OnEnable()
    {
        UICamera.fallThrough = gameObject;
    }

    void OnDisable()
    {
        UICamera.fallThrough = null;
    }

    // Use this for initialization
    void Start () {
        GameObject obj = (GameObject)Instantiate(m_Prefab);
        obj.transform.parent = m_NodeObj.transform;
    }

    // Update is called once per frame
    void Update () {

    }

    public void OnClick()
    {
#if false
        // 問題無し
        GameObject.Destroy(m_NodeObj.transform.GetChild(0).gameObject);
        GameObject.Destroy(m_NodeObj);
#else
        // エラー
        GameObject.Destroy(m_NodeObj);
#endif
    }
}
MasamiYitsuse commented 9 years ago

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

これはまだ、頂いたリストを見ての初見なのですが、OnClickの場合、クリックイベントなので、イベント内でSSのオブジェクトを削除するとタイミング的に危険かと思います。 (恐らくマウスイベントが入ってきたタイミングとUpdateが実行されたタイミングとで、「Updateが実行され・描画予約がされたのちに、マウスイベントでオブジェクトがDestroyされてしまい、その後にLateUpdateが呼び出されて描画最適化が行われる段階では、描画するオブジェクトのインスタンスが消去されてしまっている」ために起こっているのだと思われます。

できれば、OnClickの中では「オブジェクトを消去する指定’(bool値などでのフラグを立てる)」ことにとどめ、SSオブジェクトを制御しているGameObjectについているスクリプトのUpdate関数の中ででも、そのフラグを見てDestroyしていただけると、恐らく大丈夫なのではないかと思われます。 (また、GitHubのSS5PUのスクリプトの実行順序設定を行っていただいている必要もあるかと思います) ※こういったことは、FixedUpdate(衝突判定関係定期的呼出関数)とUpdate/LateUpdateなどとの間でも起こることがある症状ですので、ご注意頂けますと幸いです。

念のため、こちらでも詳細状況を調査・確認致しますので、詳細情報については少々お待ち下さいますようお願い申し上げます。 お忙しい中ご迷惑をおかけいたしますが、何卒ご理解の程お願いいたします。

OpenSesameDevelop commented 9 years ago

サンプルの方の問題は了解いたしました。 ただ、開発中のコードの方ではUpdate内でDestroyをしている状況となっています。 また、スクリプトの実行順序設定もGitHubの方を参考に設定を行っています。 以上、引き続きよろしくお願いいたします。

MasamiYitsuse commented 9 years ago

お世話になっております。 こちらでも、(OnClickを使用しない形などでも)状況を再現できましたので、現在対応策を検討中です。 もう少々お待ちくださいますようお願い致します。 (エラーメッセージの通り、すでにDestroy済みのオブジェクトが、まだ描画最適化マネージャの登録に残ってしまっており、それを参照しようとして例外が出ているのが原因のようです)

ご迷惑をおかけいたしますが、何卒ご理解とご容赦の程お願いいたします。

MasamiYitsuse commented 9 years ago

お世話になっております。 一応暫定ではありますが、(現状に対してプロジェクトに一番ダメージが少ないと思われる)上記症状に対するバグ対応方法を下記させて頂きますので、OpenSesameDevelop様の環境で上記例外が起こらないかをチェックいただけますと幸いです。 (この方法でのバグ解消だと、スプライトパーツ毎に判定処理を行っているため、ランタイムに少々非効率ではありますが、後の正式バージョンアップで、もう少し判定効率を上げて解消したものをご提供できればと思っております。ただ、恐らく喫緊と思われたので、パッチ充て的で申し訳ございませんが、暫定対処法をお知らせさせて頂きます旨、ご了承ください)

リスト: SpriteStudio/Library_SpriteStudio.cs

行番号: 998行目以降 (部位内包関数名: 「MeshSetCombine」)

                        CombineMesh[IndexMesh].transform = MatrixCorrect * DataMeshInformation.DataTransform.localToWorldMatrix;
                        IndexMesh++;

                        IndexVertexNow += DataMeshInformation.DataMesh.vertexCount;
                        IndexTriangleNow += DataMeshInformation.DataMesh.triangles.Length / 3;

改定後

                        if(null != DataMeshInformation.DataTransform)
                        {
                            CombineMesh[IndexMesh].transform = MatrixCorrect * DataMeshInformation.DataTransform.localToWorldMatrix;
                            IndexMesh++;

                            IndexVertexNow += DataMeshInformation.DataMesh.vertexCount;
                            IndexTriangleNow += DataMeshInformation.DataMesh.triangles.Length / 3;
                        }

以上となります。お手数とは存じますが、ご検証の程お願い致します。

OpenSesameDevelop commented 9 years ago

お世話になっております。 Library_SpriteStudio.csの修正で動作的には問題なくなりました。 引き続き対応よろしくお願いいたします。