Unity
Unity2D

【Unity2D】スプライトをテクスチャに描画する方法

More than 1 year has passed since last update.

Tiled Map Editorで作成したマップデータを元にして、背景を描画したかったので方法を調べました

Unity_2017_1_0f3_Personal__64bit__-_Main_unity_-_UnityRL_-_PC__Mac___Linux_Standalone__Personal___OpenGL_3_3__と_001_tmx.png

1つのタイルごとにオブジェクトを並べても良いのですが、1枚の画像を描画するだけの方がドローコールが少なく済むので高速に描画することができます。

元のスプライトの設定

Unity_2017_1_0f3_Personal__64bit__-_Main_unity_-_UnityRL_-_PC__Mac___Linux_Standalone__Personal___OpenGL_3_3_.png

元となるスプライトですが、AdvancedRead/Write Enabled にチェックを入れます。これをしないとスプライトからテクスチャを取り出すことができません。Pixels Per Unit は1つのタイルサイズが 32x32 なので 32 としました。

それと、スクリプトから Resources でアクセスするため、Resources フォルダ以下に配置するようにします

描画先のオブジェクトの作成

描画先のオブジェクトを作成しておきます。オブジェクト名は地形を描画するので FieldManager としました。

Unity_2017_1_0f3_Personal__64bit__-_Main_unity_-_UnityRL_-_PC__Mac___Linux_Standalone__Personal___OpenGL_3_3_.png

描画用に Sprite Renderer を登録しておきます。スプライトは動的に生成するので None のままでOKです。あと、スクリプト FieldManager.cs をアタッチしています

FieldManager.cs の記述

FieldManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FieldManager : MonoBehaviour {
    void Start () {

        // ①描画先のテクスチャ・スプライトを作成
        var width = 1024;  // テクスチャの幅
        var heihght = 512; // テクスチャの高さ
        var pixelsPerUnit = 32; // 1チップのサイズ

        // テクスチャ生成
        var tex = new Texture2D (w, h);

        // テクスチャを指定してスプライト生成
        var spr = Sprite.Create (
            tex,
            new Rect (0, 0, width, height),
            new Vector2 (0.5f, 0.5f), // Pivot
            pixelsPerUnit
        );

        // Sprite Rendererにスプライトを登録
        var render = GetComponent<SpriteRenderer> ();
        render.sprite = spr;

        // ②描画元のスプライト・テクスチャを取得
        // 元のスプライト取得 (Resources/tileset に配置)
        Sprite[] sprites = Resources.LoadAll<Sprite> ("tileset");
        string name = "tileset_2"; // 2番目のスプライト取得
        Sprite sp = System.Array.Find<Sprite> (sprites, (sprite) => sprite.name.Equals (name));
        // テクスチャを取得
        var texture = sp.texture;
        // スプライト矩形を取得
        var rect = sp.textureRect;
        var ox = (int)rect.x;
        var oy = (int)rect.y;
        var rectWidth = (int)rect.width;
        var rectHeight = (int)rect.height;
        var size = width * height;
        var pixels = tex.GetPixels();

        // ③テクスチャを1pixelずつ転送する
        for(int idx = 0; idx < size; idx++) {
            var x = idx % rectWidth;
            var y = (int)(idx/rectWidth);
            var c = pixels[ox + x + ((oy + y) * texture.width)];

            tex.SetPixel(x, y, c);
        }

        // ④書き込んだピクセルを反映させる
        tex.Apply ();
    }

②で、描画元のスプライトとして "tileset"の"tileset_2"を取得していますが、これは各自の環境に合わせる必要があります

③は、1pixelずつ転送しているのですが、矩形転送する方法があるのかもしれません

④最後の Texture2D.Apply() を呼び出すと書き込んだピクセルが反映されます