0 支持
1.5k 閲覧
(120 ポイント) Q&A

こんにちは。

現在自分はUnityでSpriteStudio6を使い、汎用キャラクターを作ろうとしています。

インポートした同じプレハブから複数のインスタンスを作り、それぞれにスクリプトからテクスチャを張り付けてそのテクスチャをマテリアルに適用させることでいろんな種類の歩行キャラクターを表示しようと思っています。ここの質問を参考に以下の実装で作ってみたところ、1体だけだとテクスチャを変更できるのですが同時に複数体出すとすべてが同じテクスチャになってしまいます。

/* マテリアルテーブルのシャローコピー(簡易複製)をとる */

/* MEMO: ここの時点ではマテリアルは全部プロジェクト内のものを指しています。 */

Material[] tableMaterial = ScriptRoot.TableCopyMaterialShallow();

Material[] tableMaterialOriginal = ScriptRoot.TableCopyMaterialShallow();

/* テクスチャを変更(セルマップ0を変更) */

/* MEMO: 最後の引数にtrueを与えることで、該当するマテリアルを複製した新しい別の実体を割り当てています。 */

Script_SpriteStudio6_Root.Material.TextureSet(tableMaterial, 1, SwapTexture, true);

/* 2つのシャローコピーを比較する */

for(int i=0; i<tableMaterial.Length; i++) {

    /* MEMO: TextureSetをtrueで行っているので、書き換えたところは参照が異なっている */

    if(tableMaterial[i] != tableMaterialOriginal[i]) {

        Debug.Log("Different Material [" + i.ToString() + "]");

    }

}

/* 複製したテーブルを設定 */

ScriptRoot.TableSetMaterial(tableMaterial);

同じマテリアルを共有してしまっているのかと思いましたが、マテリアルを複製しているので奇妙です。どのようにすれば個別にテクスチャを適用できるでしょうか?

SS6forUnityのバージョンは最新版で、使用OSはWindows10です。

このページをシェアする

回答 2

0 支持
(5.0k ポイント)

どんたろう 様

お世話になっております。SS6Player for Unity担当です。

ご質問ありがとうございます。


まず、結果から申し上げますと、ご指摘の状況が再現できませんでした。

申し訳ありません。

端的に、下記の実装を行いましたところ、各インスタンス毎で異なるテクスチャが設定されております。

※下記は結局、上記でご提供いただいたものから不要部分を削除したもので、これをSS6PUのサンプルプロジェクト「Doll」を改造してテストしてみました。ただしデータの状況が異なる(と思われる)ため「Script_SpriteStudio6_Root.Material.TextureSet」関数に与えているセルマップ番号のみ0に変更しています。

Material[] tableMaterial = ScriptRoot.TableCopyMaterialShallow();

Script_SpriteStudio6_Root.Material.TextureSet(tableMaterial, 0, SwapTexture, true);

ScriptRoot.TableSetMaterial(tableMaterial);

見た目は単なる色替えではありますが、これらは「色を変えたテクスチャ」をそれぞれに割り当てることで再現を試みております。


ですので、テクスチャが正常に設定できない(テクスチャがすべてのマテリアルで共通になってしまっている)理由が、他の処理に存在している可能性がございます。

当方でも、ご指摘の事象が起こる条件がないか精査してみようと思いますが、調査のためにプロジェクトをお送りいただくことは可能でしょうか?

可能でしたら、登録されているメールアドレスにサポート担当から連絡させていただきます。

※ご指摘の状況が再現できれば構いませんので、実際に作成されているプロジェクトでなく・状況が再現できる最低限のプロジェクトでも構いません。

お忙しい中、お手数をおかけして申し訳ございませんが、ご検証とご検討をお願い申し上げます。

今後とも何卒よろしくお願いいたします。

(120 ポイント)
ありがとうございます。調査のためにプロジェクトを送りたいので、連絡していただきたいです。
(5.9k ポイント)
ウェブテクノロジ・ユーザーサポート 瀬良です。

プロジェクトをお送りいただく案内を送らせていただきました。
ご確認よろしくお願いいたします。
(120 ポイント)
送りました。CharacterControlのインスペクタのTextureに、Assets/Animation/Character/Textureをアタッチしてください。二つ別々のテクスチャをアタッチしても両方同じになると思います。
(5.9k ポイント)
プロジェクトのアップロード、ありがとうございます。

担当に共有して、詳細を確認させていただきます。
よろしくお願いします。
0 支持
(5.0k ポイント)
編集

お世話になっております。SS6Player for Unity担当です。

検証用のプロジェクトのご提供ありがとうございます。

プロジェクトの実行状態を拝見させていただきました。


まず、本件が起こっている理由ですが……

  1. CharacterControl.csのAnimationListに設定されているアニメーションのプレハブが、「Anim_Contorl」である。
  2. CharacterControl.csの246行目と247行目で取得している、ScriptRootは、2つのアニメーションオブジェクト(それぞれ、Hierarchy上の「test1」「test2」の子)が参照している「プレハブそのもの」であること(Script_SpriteStudio6_ControlPrefab.csのPrefabAnimationは、名前の通りInstantiate際の実体化元のデータです)。

つまり、「test1」「test2」がInstantiateしているそれぞれのアニメーションオブジェクトが参照している「共通の元データ」を書き換えてしまっているために、画面上の全てのオブジェクトのテクスチャが変化してしまっております。


具体的な解消方法ですが……

  1. (お手元のプロジェクトの)「CharacterControl.cs」のAnimationListに設定するアニメーションのプレハブを(Assets/Animation/Character/Anim_Controlではなく)「Assets/Animation/Character/PrefabAnimation/Anim」に設定する。
  2. CharacterControl.csの246行目と247行目のソースを下記に書き換える。

変更前:

                GameObject x = (GameObject)m_characterSprite.GetComponent<Script_SpriteStudio6_ControlPrefab>().PrefabAnimation;

                ScriptRoot = x.GetComponent<Script_SpriteStudio6_Root>();

変更後:

                 ScriptRoot = m_characterSprite.GetComponent<Script_SpriteStudio6_Root>();

……この1と2の変更で、それぞれ「test1」「test2」の子としてInstantiateした、それぞれのインスタンス(実体)を個別に変更できます。


その上で……老婆心ながら、一点補足させていただければと思います。

自力でTransformを持っているGameObjectの子として自力でInstantiateする場合、「~_Control」(制御用プレハブ)は元プレハブとして使用しない方が良いです。

https://github.com/SpriteStudio/SS6PlayerForUnity/wiki/%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E5%86%8D%E7%94%9F#ControlPrefab

に詳細の解説があるのですが、制御用プレハブは、Herarchy(シーン)にオブジェクトを置く際に、座標などの制御を行うために「上位に1つ余分なGameObjectを置いて・その子としてアニメーションオブジェクトを展開する」場合に使用する目的が主となります。

そのため、「どうしても、(本来のアニメーションオブジェクトのプレハブではなく)制御用プレハブを自力でInstantiateして使用したい場合」については、下記のような手順案を提示することができます。

  1. 「~_Control」のオブジェクトが持っている「Script_SpriteStudio6_ControlPrefab.cs」のスクリプトが実行され・実際のアニメーションオブジェクトが展開されるまでに1フレーム程度のラグ(処理遅れ)が発生する場合があり……Unityの実行状況によって、Instantiateされた各GameObjectのAwakeとStartの実行タイミングが次のフレームに持ち越される場合があります。そのため、Instantiateした直後に、その子となる実際のアニメーションオブジェクトのGameObjectやScript_SpriteStudio6_Rootクラスが取得できない場合がある(GetComponentなどがnullを返す場合があります)。……ですので、スクリプト上から自力でInstantiateする場合、制御用プレハブではなく・実際のアニメーションの元データ(子フォルダ「PrefabAnimation」の下にあるプレハブ群です)を直接Instantiateした方が、色々都合が良いはずです。
  2.  実際には「test1」「test2」で座標などの制御を行う構造であるため、制御用プレハブの一番親のGameObject(Script_SpriteStudio6_ControlPrefab.csが付いているGameObjectです)が無駄な存在になる。
  3. Script_SpriteStudio6_ControlPrefab.csは「その子にアニメーションオブジェクトを展開するためだけに存在しているので、実体化後の(子の)Script_SpriteStudio_Rootを取得できない(これをできるようにするためには、Script_SpriteStudio6_ControlPrefab.csに改造を加える必要があります)。その上で、改造後の「Script_SpriteStudio6_ControlPrefab::InstanceScriptRoot」をアニメーションオブジェクトへの指定に利用する必要があります。

改造前: 

14行目から

#region Variables & Properties

public Object PrefabAnimation;

#endregion Variables & Properties

33行目から

 if(null != instanceScriptRoot)

{

    instanceScriptRoot.InstanceGameObjectControl = gameObject;

}

改造後:

#region Variables & Properties

public Object PrefabAnimation;

internal Script_SpriteStudio6_Root InstanceScriptRoot;

#endregion Variables & Properties

 if(null != instanceScriptRoot)

{

    instanceScriptRoot.InstanceGameObjectControl = gameObject;

}

InstanceScriptRoot = instanceScriptRoot;

※本来は「Script_SpriteStudio6_ControlPrefab.cs」を改造すると、後々メンテナンスとか(例えばSS6Player for Unityを更新する場合など)で面倒になってしまうため、別の方法で解決するのが良いのですが(Instantiateした後のGameObjectの子のGameObjectを取得して・そこからGetComponentでScript_SpriteStudio6_Rootを取得する……など)……ここでは、「より端的に・わかりやすい」ことを優先した解決方法を記載させていただいております。


以上となります。

お忙しい中お手数とお手間をおかけして申し訳ありません。

何卒今後ともよろしくお願いいたします。

(120 ポイント)
丁寧にご回答いただき、非常にありがとうございます。試してみます。
...