見出し画像

アセットの一部を切り抜き、prefabの寸法に伸縮して表示(Unityのメモ)

Unity2022.2.5f1のメモです。立ち絵の顔だけを駒やピンのように表示したいので、やり方を備忘録として残します。

// 他のusingは省略
using UnityEngine.AddressableAssets;

//アセットの一部を切り抜き、prefabの寸法に伸縮して表示

public class GameManagerTest : MonoBehaviour
{
    // Start is called before the first frame update
    async void Start()
    {
        /* 注:
         * ・スプライトをスケーリングさせるため、Prefab側の描画モードをスライス(9-slices)に設定しておくこと
         * ・アセット側では、スプライトモードのメッシュタイプを完全な矩形、SpriteEditor側ではBorderを(0,0,0,0)に設定しておく。これにより角を残さず伸縮の対象にできる
         */

        //指定位置にユニットを生成
        var position = new Vector3(-1.0f, 0.0f, 0.0f);
        var prefab = await Addressables.LoadAssetAsync<GameObject>("battleUnit").Task;
        var unit = Instantiate(prefab, position, Quaternion.identity);

        //ユニットにスプライトを設定
        //表示するユニットの顔のスプライトを得る
        var sprite = await Addressables.LoadAssetAsync<Sprite>("wintergreen[face]").Task;
        var sr = unit.GetComponent<SpriteRenderer>();
        sr.sprite = sprite;

        //prefabの寸法に合わせるようにスプライトのスケーリングを設定。
        //SpriteRendererの描画モード(スライス)のサイズを設定することで、スプライトだけが伸縮する
        var rect = unit.GetComponent<RectTransform>();
        var unit_width = rect.sizeDelta.x;
        var unit_height = rect.sizeDelta.y;
        sr.size = new Vector2(unit_width, unit_height);

    }
}

やりたいことは以下の通り。
・立ち絵全体をマスク処理するのではなく、顔だけを切り抜いたうえでマスクをかけたい
・アセットには立ち絵だけを使用したい。顔だけのファイルを別途作ることを避けたい
・縦横比はGameObject(Prefab)の比率に合わせて顔を切り抜くが、任意の顔の大きさに対応できる(顔の大きさは絵ごとにばらつく)
・任意のGameObjectのサイズに合わせて顔を表示したい(駒のサイズを変えても出来るだけコードをいじりたくない)
・切り抜いた顔の大きさを伸縮させる場合でも、マスクの(SpriteMask)大きさは固定。

対処法は以下の通りです。

準備
・立ち絵のアセットに対し、SpriteEditorでスプライトを作成。スプライトモードを「複数」、メッシュタイプを「完全な矩形」とする(メッシュタイプ「完全な矩形」の指定は描画モードを「スライス」にするために必要)
・Prefab側の描画モードを「スライス」に指定する
・Prefab側にSpriteRendererとSpriteMaskを持たせる。SpriteMaskにはあらかじめマスクを設定
・SpriteMaskにSorting Groupコンポーネントを追加しておく(マスク範囲が融合しないようにする)

実行時のコード
・Prefabの生成時、PrefabのSpriteRendererに顔のスプライトを指定
・SpriteRenderer.sizeに伸縮後の画像のサイズを設定する。単位はUnit(1Unit=1mのやつ)。今回はPrefabのサイズを取得して指定

ポイントはソースコードというよりはアセットの設定でした。特にGameObjectの描画モードを「スライス」に指定することで問題が解決できました。
アセット上の画像をスプライトとしてそのまま描画モードを「シンプル」として読み込んでも画像の大きさを伸縮表示できるのですが、「シンプル」の場合はマスクの大きさも伸縮されてしまいます。
一方、「スライス」は9-slicesのモードで伸縮表示できます。これは主にウィンドウ表示用のモードで、角を残して枠と真ん中だけを伸縮できます。そして「スライス」の場合、SpriteMaskの大きさは伸縮されず固定されます。

SpriteMaskの大きさを固定してスプライトを伸縮したいので、「スライス」を使用すれば所望の動作を実現できそうです。しかし伸縮時に角が残ってしまうと都合が悪いです。角を残さず伸縮するには…角を残さないように伸縮範囲を設定できないものか。

できました。というかデフォルトの設定で角が残らず伸縮するようになっていました。

顔だけを切り抜くスプライト。Border(0,0,0,0)が該当の角が残らない設定


左:スプライトをPrefabのサイズに縮小し、マスク適用して表示。顔のサイズが元の立ち絵(右)より小さくなっている

アセットの読み込みにはResources.Load()ではなく、Addressablesのメソッドを使いました。Addressablesだとアセット名と実パスを分離することができ、実パスの変更にもコードは書き換えずに対応できます。リソースの差し替えにも対応できるようです。

Unity2022.2.5f1 だと以下の記事のやり方で導入できました。

ちなみに画像から切り出したスプライトを指定するときは、アセット名[スプライト名] という書き方で個々のスプライトを指定できます。冒頭のコードだと、"wintergreen[face]" で wintergreenちゃん(仮)のfaceスプライトを指定しています。

ついでにループで回せるようにし、顔の外枠を作って他のキャラも表示してみた

いいなと思ったら応援しよう!