Unity初心者が2Dタワーディフェンスを作っています。今回は砲台オブジェクトの作成、そしてマップのクリックしたタイルに砲台を生成する処理を実装します。
- Mac mini (M1, 2020)
- Unity 2022.3.36f1
画像のインポート
ProjectビューのAssets/Imagesフォルダの下にTurretフォルダを作成して、そこに砲台用の画像データをドラッグ&ドロップしてインポートします。
インポートした画像を全選択し、インスペクターで「Pixels Per Unit」の値を64にして「Apply」ボタンをクリックします。画像の縦横のピクセル数が64なので64にしています。
今後、マップのタイル上に表示する画像はすべてこの設定をするので忘れないでね。
オブジェクトの作成
砲台は台座と砲身の2つの画像を重ねて作ります。
ヒエラルキーに空のオブジェクトを作成して、名前をTurretにします。その配下に砲台の画像(台座と砲身)をドラッグ&ドロップします。
名前をそれぞれTurretBase, TurretHeadにします。
砲台をレイヤーの最前面に表示したいので、TurretBaseとTurretHeadのインスペクターで「Sprite Renderer > Additional Settings > Sorting Layer」を「Object」にします。
砲身(TurretHead)を台座(TurretBase)よりも前面に表示したいので、TurretBaseの「Sprite Renderer > Additional Settings > Order in Layer」を0に、TurretHeadは1にします。
同じSorting Layerのオブジェクトの重なり順はOrder in Layerで設定します。数値が大きいほうが手前に表示されます。
オブジェクトをプレハブ化
ProjectビューのAssets下にPrefabsフォルダを作成します。そこにTurretオブジェクトをドラッグ&ドロップしてプレハブ化します。
プレハブができたら、ヒエラルキーのTurretオブジェクトは用済みなので削除します(かわいそう)。
クリックしたタイルに砲台を生成
いよいよスクリプトを書いていきます。
Assetsフォルダの下にScriptsフォルダを作成します。そこにC#スクリプトを作成して、名前をTurretGeneratorにします。
TurretGeneratorスクリプトの内容は次のとおりです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps; // Tilemapを扱うために必要な宣言
public class TurretGenerator : MonoBehaviour
{
[SerializeField]
private GameObject turretPrefab; // 砲台のプレハブ
[SerializeField]
private Grid grid; // Grid_BaseのGrid、Tilemapの座標を取得するため
private Vector3Int gridPos; // Tilemapのセル座標
void Update()
{
if (Input.GetMouseButtonDown(0)) // 画面をクリックしたら
{
// クリック位置のスクリーン座標をワールド座標に変換しそれをセル座標に変換
gridPos = grid.WorldToCell(Camera.main.ScreenToWorldPoint(Input.mousePosition));
// 砲台を生成
GenerateTurret(gridPos);
}
}
/// <summary>
/// 砲台生成
/// </summary>
/// <param name="gridPos"></param>
private void GenerateTurret(Vector3Int gridPos)
{
// クリックした位置に砲台を配置
GameObject turret = Instantiate(turretPrefab, gridPos, Quaternion.identity);
// 砲台の位置がタイルの左下を 0,0 として生成しているので、タイルの中央にくるように位置を調整
turret.transform.position = new Vector2(turret.transform.position.x + 0.5f, turret.transform.position.y + 0.5f);
}
}
ヒエラルキーで空オブジェクトを作成し名前をTurretGeneratorにします。
TurretGeneratorオブジェクトにTurretGenerator.csをドラッグ&ドロップしてアタッチします。
TurretGeneratorのインスペクターで、「Turret Prefab」には「Assets/Prefabs/Turret」を、「Grid」にはGrid_Baseオブジェクトをドラッグ&ドロップしてアサインします。
ゲームを実行して動作確認をしてみます。
うまくいきました。わーい。
配置可能なタイルだけに砲台を生成
現在のところ、道や障害物(木、石)の上にも砲台を配置できてしまいます。また、すでに砲台があるタイルの上にも砲台を配置できてしまいます。
配置可能なタイルだけに砲台を配置できるようにスクリプトを修正します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps; // Tilemapを扱うために必要な宣言
public class TurretGenerator : MonoBehaviour
{
[SerializeField]
private GameObject turretPrefab; // 砲台のプレハブ
[SerializeField]
private Grid grid; // Grid_BaseのGrid、Tilemapの座標を取得するため
[SerializeField]
private Tilemap tilemaps; // Grid_WayのTilemap
private Vector3Int gridPos; // Tilemapのセル座標
private HashSet<Vector3Int> occupiedCells = new HashSet<Vector3Int>(); // 砲台配置済みセルを代入
void Update()
{
if (Input.GetMouseButtonDown(0)) // 画面をクリックしたら
{
// クリック位置のスクリーン座標をワールド座標に変換しそれをセル座標に変換
gridPos = grid.WorldToCell(Camera.main.ScreenToWorldPoint(Input.mousePosition));
// クリックしたタイルのコライダーがNoneならば
if (tilemaps.GetColliderType(gridPos) == Tile.ColliderType.None)
{
// 砲台を生成
GenerateTurret(gridPos);
}
}
}
/// <summary>
/// 砲台生成
/// </summary>
/// <param name="gridPos"></param>
private void GenerateTurret(Vector3Int gridPos)
{
// 配置済みの場合は処理を中断
if (occupiedCells.Contains(gridPos))
{
Debug.Log("このセルにはすでに砲台が配置されています");
return;
}
// クリックした位置に砲台を配置
GameObject turret = Instantiate(turretPrefab, gridPos, Quaternion.identity);
// 砲台の位置がタイルの左下を 0,0 として生成しているので、タイルの中央にくるように位置を調整
turret.transform.position = new Vector2(turret.transform.position.x + 0.5f, turret.transform.position.y + 0.5f);
// 配置されたセルを登録
occupiedCells.Add(gridPos);
}
}
TurretGeneratorのインスペクターでTilemapsにGrid_WayのTilemapをドラッグ&ドロップしてアサインします。
動作を確認します。
さいごに
まずは、砲台をマップ上に生成することに成功しました。いえい。
最終的にはいろんな種類の砲台の中から選択して配置するという処理をしたいのですが、まずは1つの砲台の配置を実装しました。楽しいね。
でわでわ
コメント