【げ】UnityのTilemap(2D)いろいろメモ
追記:Pixel per Unitを弄っちゃったら
2Dなら、なにかと活用するUnityタイルマップ(2D)にて、忘れる前にメモという事で。。
(;^ω^)
タイルがズレとる問題
タイルを編集時に、タイルパレットを開きますが、これが盛大にズレてしまう時がある。
また、シーン画面上でもズレたりする事もある。
そのためか、カーソルがトンデモない場所を指してたりもしちゃったりします。
これは、タイルに設定されたアンカーによるものが悪さをしています。
保存したタイルマップアセットを開いて、個々のタイルを編集する事が出来ますが。
ピボットが標準で、Centerとなってるはず。
このピボットを見て、タイルマップ全体の計算がされているそうで(今のバージョンでは)、これを、左上や左下に合わせて置けばピタッとくるでしょう。また、全部合わせる必要があるようです。
これの他、タイルマップオブジェクトのアンカーも確認しておこう。
コライダー範囲がズレとる問題
緑色の線で、コライダー(衝突判定エリア)が、盛大にズレる時(変になる)があります。
何もしてないのに・・、なんでや。・・と言った具合です。
これは、貴方のミスでは無く、Unity側の更新が遅れてるだけなので、ご安心を。
今すぐ更新したいなら、コライダーのオフセットとかイジって、元に戻すなりすれば、更新してくれます。
タイルを配置する時ズレとる問題
ヒエラルキーを確認すれば一目瞭然で御座います。
(;´∀`)
違うやつを編集してるはず。
タイルマップの空白デカすぎる問題
過去に編集した事のある領域外まで、全て情報として保管してしまいます。
なので、削除しても、オブジェクトサイズはそのまま変化無い状態になります。
インスペクターのTilemapの右端をクリックして、「タイルマップ範囲を圧縮」で、最小範囲まで圧縮してくれます。
この方法探すの難儀した。。
(;´Д`)
偶然、Tilemap.CompressBounds()というメソッドを見つけたので、エディタ上にあるんじゃないかと探しまくったら、あったのよ。
無論、このメソッドでゲーム中に動的に再調整する事が可能。
タイルマップが物理演算で暴れる
動くはずが無いマップオブジェクトなんだと思いこんでるのは、貴方だけという落ちなのですが、地面がゴリゴリに暴れるのは驚いてしまいます。
(;^ω^)
書くまでもない初歩的な事ですが、ボディタイプを、「キネマティック」にしましょう。
これで、他オブジェクトには影響を与えるが、自分は物理演算しないという状態になります。
物理演算は必要というなら、Constraintsで移動や回転に制限をかける事が出来ます。
もしくは、極端に重くするとかね(Rigidbody/重力スケール)
パーツ毎にコラーダーを設定したい
スプライトエディタを開いて、直接、個々に緑線を編集する事ができます。
タイルマップアセットから、「コライダータイプ」をスプライトにする事で、画像の形状に合わせて、コライダーを設定してくれるようです。
タイルマップの大きさを知りたい
前述の大きすぎるタイルマップ対策をして頂いた上で、以下のスクリプトで、サイズを知ることが出来る。
Tilemap _tile = tilemap_object.GetComponent<Tilemap>();
BoundsInt _bounds = _tile.cellBounds;
BoundsIntで返される(リファレンス)
タイルマップの中身を知りたい
上記で得たboundsを利用して、タイルを取得できます。
一次元配列で戻ってくるので、bounds.sizeで適切に参照します。
ちなみに、中身が入ってないと、nullとなります。
TileBase[] _allTiles = _tile.GetTilesBlock(_bounds);
for (int x = 0; x < _bounds.size.x; x++) {
for (int y = 0; y < _bounds.size.y; y++) {
TileBase _tileb = _allTiles[x + y * _bounds.size.x];
if (_tileb != null) {
Debug.log(_tileb.name);
}
}
}
上記で中身を見る方法の他、内部のメソッド(正規の方法)を利用するなら、bounds.min/max値を利用する形となりそう(参照値としてマイナス値がある)
for(int x = _bounds.min.x;x < _bounds.max.x;x++){
for(int y = _bounds.min.y;y < _bounds.max.y;y++){
}}
_tile.HasTile(new Vector3Int(x,y,0)); 存在するか
_tile.GetTile<Tile>(new Vector3Int(x,y,0)); Tile.spriteの取得
中心位置はどこよ
VisualSudioデバッグで中身を覗いてみました。
編集時、タイルパレットで一番最初に置いた場所(セル位置)が、(x:0,y:0)となるよう。多分
なので、他オブジェクトのように、中心位置じゃないので注意。
cellBounds.x/yは、アンカーから見た、その場所(ピボット位置)を指してるよう(originを見たほうがいいかも)
※タイルスプライトのピボット設定値からの相対値
タイルパレットを表示した状態で、カーソルを選択してクリックすると、各セルのオフセット値が表示されます。
これでも、中央位置が調べられます。
(こんな機能があったなんて、記事執筆中に気づいたという・・・w)
セル毎に、移動したり回転したり、スケール値が設定できるんですよ。。これは、何かに使えそう・・。さらに、混乱度が増しそうですが。
見た目の中心位置はどこよ?
もちろん、タイルマップの形状にもよりますが、こんな感じで、タイルマップ全領域の中心位置となるとこうなります。
_obj.transform.position.x + _bounds.x + (_bounds.size.x / 2);
_obj.transform.position.y + _bounds.y + (_bounds.size.y / 2);
仕様上、空白セルもありえるので、事前に「タイルマップ範囲を圧縮」をしておいてください。
右端ならこう。
_obj.transform.position.x + _bounds.x + _bounds.size.x;
左端ならこうなりますよね。
_obj.transform.position.x + _bounds.x;
これを必要としてる方は、画面サイズなんかも見るでしょうから、補足。
_oCamera = GameObject.Find(“Main Camera").GetComponent<Camera>();
_fScreenLeftTop = _oCamera.ScreenToWorldPoint(Vector3.zero);
_fScreenLeftTop.Scale(new Vector3(1f, -1f, 1f));
_fScreenRightBottom = _oCamera.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 0.0f));
_fScreenRightBottom.Scale(new Vector3(1f, -1f, 1f));
Pixel per Unitを弄っちゃったら
タイルマップに限らず後から、Pixel per Unit(以下PPU)を弄ると面倒な事になります(座標単位1ユニットで、いくつのピクセルというやつ)
画面サイズは0~1といった解りやすくするのもアリですが、昔ながらのピクセル数に準じた感じでやってみようと思う方も多いはず。
しっかり設定すれば、後からでも直せます。
スプライト側のPPU値を実際のドット数。
画面ではPrefab(プレハブ)のタイルマップ。スケール値をPPU値へ変更(タイルマップアセットは1)
グリッドのセルサイズはそのまま1で。
また、スクリプト側で、PPUを無視した書き方をしてると、こちらも編集が必要になります。
しっかりPPUを意識すべきか、余計な演算を無くして高速化を図るか、座標計算は全てINT型でやるのだ!など
すべては、貴方の自由!m9( ゚д゚)
余談ですが。。。
Pixel per Unitをイジった際、タイルマップを編集後、確認のためにPrefabから、ヒエラルキー(Gridの子)に置いた際に、極端に小さかったり、大きかったりします。
超焦るんですが。。:(;゙゚’ω゚’):
大丈夫、何も見なかった事にして、しっかりプロジェクト保存して、再度やってみてください。
(;^ω^)
覚えてるやつをメモとして記事にしました。
思い出したら追記するかもです。
んでは。