投稿記事

ものららい 2022/01/28 17:00

UnityでQuadのテクスチャUVを切り替える的なやつ


ちょっとゲーム開発がBGMで止まっていてネタがないので、振り返りもかねて自分のために今まで作った機能についてのおさらいしようかなと思います。
※あくまで自分のためのやってることなので、コードが見にくかったり、コードの書き方の癖が…とか、そもそももっといい方法があるとか、説明文がワカメ的なのは優しく流してください。🐄



今回はUnityでQuadのテクスチャUVを切り替える的な処理について。

とりあえずソース。
MeshUvControl.cs

using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
#endif

//QuadメッシュのUV操作
public class MeshUvControl : MonoBehaviour
{
	//広げ設定
	float _spread = 0;
	
	//マスの位置とマスの最大数
	public int offsetX = 0;
	public int offsetY = 0;
	public int lengthX = 1;
	public int lengthY = 1;
	
	//設定保存用の変数なのでエディタ内では非表示
	[HideInInspector] public int saveOffsetX = 0;
	[HideInInspector] public int saveOffsetY = 0;
	[HideInInspector] public int saveLengthX = 0;
	[HideInInspector] public int saveLengthY = 0;
	
	Mesh _mesh;
	Vector2[] _uv;
	float _uvWidth;
	float _uvHeight;
	
	
	//エディタの時のみ動作
	#if UNITY_EDITOR
	void OnValidate ()
	{
		EditorApplication.delayCall = () => 
		{
			if(!EditorApplication.isPlaying)
			{
				Init();
			}
		};
	}
	#endif
	
	
	void Awake ()
	{
		Init();
	}
	
	
	//初期化
	void Init ()
	{
		//メッシュの取得
		MeshFilter _meshFilter = GetComponent<MeshFilter>();
		_mesh = _meshFilter.sharedMesh;
		
		//メッシュが無い場合か初回セットの時はメッシュを生成する
		if(_mesh == null || _mesh.name != "DummyMesh")
		{
			//メッシュの生成
			_mesh = new Mesh();
			_mesh.name = "DummyMesh";
			
			//頂点
			Vector3[] _vertices = new Vector3[4];
			_vertices[0].Set(-0.5f, -0.5f, 0);
			_vertices[1].Set(0.5f, -0.5f, 0);
			_vertices[2].Set(-0.5f, 0.5f, 0);
			_vertices[3].Set(0.5f, 0.5f, 0);
			_mesh.vertices = _vertices;
			
			//頂点インデックス
			_mesh.triangles = new int[] {0, 3, 1, 3, 0, 2};
			
			//法線
			Vector3[] _normals = new Vector3[4];
			_normals[0].Set(0, 0, -1);
			_normals[1].Set(0, 0, -1);
			_normals[2].Set(0, 0, -1);
			_normals[3].Set(0, 0, -1);
			_mesh.normals = _normals;
			
			//メッシュのセット
			_meshFilter.sharedMesh = _mesh;
			
			//設定保存用の変数初期化
			saveOffsetX = 0;
			saveOffsetY = 0;
			saveLengthX = 0;
			saveLengthY = 0;
		}
		
		//UV更新用配列
		_uv = new Vector2[4];
		
		//あらかじめ一マスの大きさを求める
		_uvWidth = (1f / (float)lengthX) - _spread;
		_uvHeight = (1f / (float)lengthY) - _spread;
		
		//UV更新
		UpdateUV();
	}
	
	
	//UV更新
	public void UpdateUV ()
	{
		//一つでも設定が違っていれば処理
		if(
			offsetX != saveOffsetX || 
			offsetY != saveOffsetY || 
			lengthX != saveLengthX || 
			lengthY != saveLengthY
		)
		{
			//設定の保存
			saveOffsetX = offsetX;
			saveOffsetY = offsetY;
			saveLengthX = lengthX;
			saveLengthY = lengthY;
			
			//表示するUV座標を求める
			float _x = (float)offsetX / (float)lengthX;
			float _y = (float)(lengthY - 1 - offsetY) / (float)lengthY;
			float _width = _x + _uvWidth;
			float _height = _y + _uvHeight;
			_x += _spread;
			_y += _spread;
			
			//新しいUV値のセット
			_uv[0].Set(_x, _y);
			_uv[1].Set(_width, _y);
			_uv[2].Set(_x, _height);
			_uv[3].Set(_width, _height);
			_mesh.uv = _uv;
		}
	}
}

やってることは非常にシンプルでメッシュに対して一度Quadを再構成しつつUV座標を設定したoffsetとlengthの値をもとに指定したマスを表示してる感じです。

lengthの値が各X、Yのマスの最大値の設定で、offsetは実際にマスの位置をX、Yで設定していく形になります。

実際に使用するときは、あらかじめ表示させたいテクスチャの設定したマテリアルをセットしたQuadを生成しておいてから上記のスクリプトを入れると面倒が無く良いと思います。


一応、OnValidateでも処理が走るようになっているので、プレイ中でなくてもエディタ上の編集でffsetとlength数値をいじってもグラフィックに反映されるようになっています。

ですので、エディタで視覚的に設定した状態でプレハブに格納してInstantiateでそのUV値に設定した絵柄のQuad生成するのも簡単にできます。

ただし、シーンに展開されていない状態ではあくまで一時的なメッシュ情報なので、リソースとして存在するシーンに表示されていないプレハブみたいな場合はメッシュ自体は消滅してしまいますが、消滅してもまた数値を変更したり表示すれば再構成されるので特に問題はないと思います。


余談ですが。
何年も前の初期の段階ではマテリアルの方のUV値をいじってましたが、パラメータをいじるとその都度新しいマテリアルを生成してる疑惑がありましてドローコールがめちゃ増えそうな予感がしたので、それならって感じにバッチングが効きドローコールが減らせる期待のあるメッシュのUVデータの方だけをいじる方式に切り替えました。(同一マテリアルであれば描画をまとめてくれるはずなので)

今回のは3D空間上の板ポリの絵柄をマップチップみたいな感じで!っていうのやりたい人はいいかもしれません。(もっといい方法があるかもだけど)


あと、今回の機能を地面の草とかキャラとかに使用したい場合はnormalsの設定値をすべて

_normals[0].Set(0, 0, -1);

じゃなくて

_normals[0].Set(0, 1, 0);

にすると上向きの法線になるので光の当たり方が自然になります。


最後に、実際動作するアセットフォルダも置いておきますので、アセットフォルダを空プロジェクトに入れれば確認できます。

2022_01_28_Assets.zip (72.95kB)

ダウンロード

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

ものららい 2022/01/04 15:13

あけました!


あけましておめでとうございます🐅

おめでたいですが、去年中ゲーム完成させたかったなぁとか力の不足等で色々ずれ込み悔いの残る所ではあったりして…うっ🐄。(今年はがんばります

去年末に+αでやらなきゃいけない事とか今現在足りない物とか色々課題が見えてきたのでとりあえず今年初めはそこらへんを取り組んで強化して行ければなとか思います。

今年もよろしくお願いいたします!

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

ものららい 2021/11/30 16:03

そこそこ順調

※追記2021/12/01 「↓一応動いてるやつ」の動画が間違ってたので修正。


コンにちは!
前回から進めてた見下ろし型のゲーム、とりあえず骨だけは出来たかな?って所までは割とサクッと進みました。

一応あんまり手間のかからない繋ぎのゲーム感を目指してるので、ステージ選んでクリアしてくだけのシンプルなものになりそうですが、シンプルとは言えここから肉付けしていくのがどのゲームも一番大変な所なのでガンバリマス。

↓一応動いてるやつ


あと、音楽制作的なのちょっとずつ進めてました。
ド素人なところからスタートしてるので本当に基本的なところから取り組んでますが、以前より無理ゲーな感じはなくなってきたので、今年中に集中的にレベル上げてそれなりなBGM作れるようになれればなって思っています。(ここが出来ないとどのみち現状詰むので

↓作ってた音楽など ※現状は10秒程度だけど




この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

ものららい 2021/11/03 14:21

気が付いたら戻り

コンにちは!

前回「これ以上は巻き戻りは無いと思うの」と言っておいてですが…、あの後すぐ横スクロールから見下ろし視点のゲームに変更しました…!(すぐブレてる

仕組み作り終わった後でなんか横スクロールでのやりたいことのビジョンが見えなくってうーんってなってたところで、見下ろしならあれもこれもと浮かんできてやっぱりこっちの方がいいんじゃ…ってなってきたので取り返しのつくタイミングでマップと操作系の処理の部分書き換えて見下ろし型探索ゲームの土台に作り変えました。

今回作ってるのは、後々のやりたい事のための習作的な側面の強いものなので割と軽い作りになると思いますのであんまり時間かけずにささっと作っていきたいです。

あとそろそろ音関係の練習する時間も取っていかないと…。(ここやらないと先に進まないので

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

ものららい 2021/10/01 16:56

見た目など

コンにちは🍙

仕方ない事ですが、微妙に予定がずれ込んで作業速度が落ちていますが、とりあえず今できる範囲でやれることやろうかなと思って今回は細かなところ手を付けてました。



前々回の更新で機能だけ作っていたミニゲームの大小ゲームの方のグラフィックができたので組み込んでいましたが、見た目良くなると簡単なミニゲームでも結構いい感じに見えますよね。

メカミミの方は終盤に差し掛かってきてだんだんお伝えする内容が薄くなってきたので、更新用に以前着手してたアクションゲームっぽいものをゆっくり再構成してます。


前作ってた時よりもちょっと作業戻っちゃったけど、これ以上は巻き戻りは無いと思うのでこの形をゆっくり良くしていきたいです。

がんばります!

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

6 7 8 9 10 11 12

記事のタグから探す

月別アーカイブ

記事を検索