+1 支持
1.3k 閲覧
Q&A
Script_SpriteStudio6_RootコンポーネントにあるTableMaterialにアクセスしmainTextureの変更をしました。ただこれだと元のマテリアルのテクスチャを直接変更してしまい、Unityの再生終了をしてもマテリアルが変更前に戻らなくなってしまいました。希望としては再生中だけテクスチャを変更して再生終了後に元に戻るのがいいのですが、可能なのでしょうか?

口下手で申し訳ございませんが、ご回答の方宜しくお願い致します。
このページをシェアする

回答 1

+1 支持
(5.0k ポイント)
編集

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

SS6Player for Unity担当です。

ご希望の通りの動作にすることはできます(というよりはご希望通りの動作の方を推奨です)。


まず先に注意点を。

  1. ScriptRoot.TableMaterialの内容を直接操作することは「あまり」お勧めしません。
  2. ScriptRoot.TableMaterialに設定されているマテリアルの内容を直接変更すべきではありません。

※ScirptRootはScript_SpriteStudio6_Rootのインスタンス(実体)とします。

1.は絶対にダメとかいうことではありませんし、後述の解消方法で「どうしても」みたいな場合として方法を紹介していますが……

ScriptRoot.TableMaterial[index]のように、ScriptRootが持っているTableMaterialメンバを直接アクセスしないでください(直接アクセスは非推奨です)。

後述のサンプルのように、必ず「Material[] tableMaterial = ScriptRoot.TableGetMaterial();」などのTableGetMaterial関数経由で取得してください。

2.はScriptRoot.TableMaterial[index].mainTexture = AnyTextureというような行為をさしますが……ご指摘の通り、この方法はUnityのプロジェクトの内容を変更してしまいます。

理由として、ScriptRoot.TableMaterialはまさにプロジェクトに格納されているマテリアルへの参照が格納されているためです。


では具体的にご希望の動作をさせる場合ですが……

3つの方法があります。

※「SwapTexture」は、差し替えるテクスチャの参照(Texture2D)とします。

※ちょっとサンプルリストが見づらいので……灰色の枠内をメモ帳やテキストエディタに貼り付けて見てくださると見やすいかと思います。申し訳ありません。

1. マテリアルテーブルの完全な複製を取り・該当するセルマップのテクスチャを全て変更する方法。

/* マテリアルテーブルのディープコピー(完全複製)をとる */

/* MEMO: ディープコピーなのですでにこの時点でtableMaterialの内容は内容が同じ別実体になっています */

Material[] tableMaterial = ScriptRoot.TableCopyMaterialDeep();

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

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

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

ScriptRoot.TableSetMaterial(tableMaterial);

2. マテリアルテーブルの簡易複製を取り・該当するセルマップのテクスチャを全て変更する方法。

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

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

Material[] tableMaterial = ScriptRoot.TableCopyMaterialShallow();

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

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

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

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

ScriptRoot.TableSetMaterial(tableMaterial);

1と2の違いは、「1は最初に全てを複製した別の実体を作成してしまい、それを設定する」ことにあります。つまりこのtableMaterialに設定されているマテリアルの内容をどういじろうが、一切プロジェクトに影響はありません。

一方「2は変更するマテリアルだけを別の実体を作成して設定する」という方法です。TextureSet関数を使って変更したマテリアル以外に何か変更を加えてしまうと、プロジェクトにあるアセットを書き換えてしまうので注意してください。

一般的に2の方が使用メモリが少なかったり・SetPass Calls関係でのトラブルが少なかったりするのですが……1の方が「何をやっても大丈夫」的な面では安全です(どちらを選ぶかはご都合で左右されるかと)。

3. どうしてもピンポイントのマテリアルだけどうにかして・かつScriptRoot.TableMaterialを直接いじりたい場合の例

/* マテリアルテーブルを取得 */

Material[] tableMaterial = ScriptRoot.TableGetMaterial(); /* falseを指定したらだめです */

/* マテリアルを複製 */

Material material = ScriptRoot.MaterialGet(0, Library_SpriteStudio6.KindOperationBlend.MIX, Library_SpriteStudio6.KindMasking.MASK);

Material materialNew = new Material(material); /* これで複製しています */

/* テクスチャを変更 */

/* MEMO: 変更するのは、複製したマテリアル側です。 */

int indexMaterial = Script_SpriteStudio6_Root.Material.IndexGetTable(0, Library_SpriteStudio6.KindOperationBlend.MIX, Library_SpriteStudio6.KindMasking.MASK);

materialNew.mainTexture = SwapTexture;

tableMaterial[indexMaterial] = materialNew;

3は正直、何かの理由がない限り、あまり推奨したくない方法ではありますが……この方法でもご希望の効果は得られると思います。

この方法を推奨したくない理由ですが……これをやらなくてはならない事態というのは、相当複雑なマテリアル変更をしている場合で、正直データの扱い方や実装としては破綻している可能性があるためです(それ以外だと、相当ナーバスに高速化する必要がある場合とかでしょうか……いずれにしてもマニアックなケースといえるかもしれません)。



基本的な考え方としては、「必要(実装の都合)に応じて変更する単位で実体の複製を作る」ということです。

※このあたりはUnity上で他のデータなどを扱っても同様の考慮が必要になる場合が多いです。


また、各関数などの詳細については、下記のURLにスクリプトリファレンスがありますので、こちらをご参照いただけますと幸いです。

(SS6Player for UnityのGitHubのWiki内のスクリプトリファレンスです)

https://github.com/SpriteStudio/SS6PlayerForUnity/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

※アニメーション操作関係の関数群の解説はそろっているはずです。現在、エフェクト関係や主要ではないユーティリティ関係が未記載になっていますが、そちらは随時追記していきます。


長くなりましたが、以上となります。

一助となれば幸いです。

なにとぞ今後ともよろしくお願いいたします。

...