Tiled Map Editorで作成したマップデータを元にして、背景を描画したかったので方法を調べました
1つのタイルごとにオブジェクトを並べても良いのですが、1枚の画像を描画するだけの方がドローコールが少なく済むので高速に描画することができます。
元のスプライトの設定
元となるスプライトですが、Advanced
の Read/Write Enabled
にチェックを入れます。これをしないとスプライトからテクスチャを取り出すことができません。Pixels Per Unit
は1つのタイルサイズが 32x32 なので 32
としました。
それと、スクリプトから Resources
でアクセスするため、Resources
フォルダ以下に配置するようにします
描画先のオブジェクトの作成
描画先のオブジェクトを作成しておきます。オブジェクト名は地形を描画するので FieldManager
としました。
描画用に 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()
を呼び出すと書き込んだピクセルが反映されます