ラベル Nostalgia の投稿を表示しています。 すべての投稿を表示
ラベル Nostalgia の投稿を表示しています。 すべての投稿を表示

2014年11月4日火曜日

敵を発生させるスクリプト

またも間が空いてしまった。ブログの記事に時間を割くよりは制作を優先したらこうなった。今回は Nostalgia のマップに配置したタイルの ID に対応する敵をタイルの位置に発生させるスクリプトを晒す。マップコンポーネントを追加したゲームオブジェクトに以下のスクリプトを追加して使う。例によって品質は KS だ。

using UnityEngine;
using System.Collections;
using Nostalgia;

public class EnemySpawner : MonoBehaviour
{
  [SerializeField] private GameObject[] enemyPrefabs;
  private Map enemySpawnerMap;
  private Vector3[] tilePositions;
  private int[] tileIds;
  private Cell[] cells;

  void Start ()
  {
    enemySpawnerMap = GetComponent<Map> ();
    cells = enemySpawnerMap.cells;
    tilePositions = new Vector3[cells.Length];
    tileIds = new int[cells.Length];
    for (int i = 0; i < cells.Length; i++) {
      tilePositions[i] = enemySpawnerMap.MapPointToWorldPoint (cells[i].position);
      tileIds [i] = cells [i].tileID;
    }
    StartCoroutine (SpawnEnemy ());
  }

  IEnumerator SpawnEnemy ()
  {
    while (true) {
      for (int i = 0; i < cells.Length; i++) {
        bool b1 = true; // 待ち時間以外の敵インスタンスの出現条件を書く
        bool b2 = true; // 敵インスタンスの向き変更条件を書く
        if (b1) {
          GameObject enemyInstance = (GameObject)Instantiate (enemyPrefabs [tileIds[i]], tilePositions[i], (b2 ? Quaternion.identity : Quaternion.Euler (0f, 180f, 0f)));
        }
      }
      yield return new WaitForSeconds (5f); // 待ち時間
    }
  }
}

敵の種類だけ異なるタイルを作るわけだが、全部透明の同じグラフィックにするとインスペクターなしで区別できない。これでは扱いづらいのでどうしたものか。それにしても Tile Component の使いどころがわからんな〜。

2014年9月6日土曜日

下からすり抜けて上に乗ることができる床の実装例 (Unity C#) Nostalgia (Version 1.0.2) 対応版

Nostalgia (Version 1.0.2) では前回示したようなコライダーごとにスクリプトを付ける手法は使えないようなので、プレイヤーの近傍のセルを調べてcollider.enabled を切り替える方法にした。

図で示すとこういう感じ。画像の赤色のセルはプレイヤーのいるセル、緑色のセルは、中にコライダーがあれば collider.enabled = false にするセル、青色のセルは、中にコライダーがあれば collider.enabled = true にするセルを示す。

KS コードを公開するよ。コメントをつけたやたらに長い名前の3つの変数の値をお好みで適当にいじればいいんじゃないかな。


using UnityEngine;
using System.Collections;
using Nostalgia;

public class NostalgiaColliderEnabledSwithcher : MonoBehaviour
{
  Transform playerTransform;
  Map map;
  Vector3 playerPosition;
  int numberOfHalfOfHorizontalCells;

  // 中にコライダーがあれば collider.enabled の値を変更するセル (図の青色または緑色のセル) の水平方向の数。
  int numberOfHorizontalCells = 7;
    
  // 中にコライダーがあれば collider.enabled = false にするセル (図の緑色のセル) の垂直方向の数。
  int numberOfVerticalCellsEachOfWhichMayHaveColliderToBeDisabled = 6;
    
  // 中にコライダーがあれば collider.enabled = true にするセル (図の青色のセル) の垂直方向の数。
  int numberOfVerticalCellsEachOfWhichMayHaveColliderToBeEnabled = 1;
  Point2[] offset1;
  Point2[] offset2;

  void Start ()
  {
    playerTransform = GameObject.FindGameObjectWithTag ("Player").transform;
    map = GetComponent <Map> ();
    numberOfHalfOfHorizontalCells = (numberOfHorizontalCells - 1) / 2;
    offset1 = new Point2[numberOfHorizontalCells * numberOfVerticalCellsEachOfWhichMayHaveColliderToBeDisabled];
    for (int i = 0; i < numberOfHorizontalCells; i++) {
      for (int j = 0; j < numberOfVerticalCellsEachOfWhichMayHaveColliderToBeDisabled; j++) {
        offset1 [numberOfVerticalCellsEachOfWhichMayHaveColliderToBeDisabled * i + j] = new Point2 (i - numberOfHalfOfHorizontalCells, j);
      }
    }

    offset2 = new Point2[numberOfHorizontalCells * numberOfVerticalCellsEachOfWhichMayHaveColliderToBeEnabled];
    for (int i = 0; i < numberOfHorizontalCells; i++) {
      for (int j = 0; j < numberOfVerticalCellsEachOfWhichMayHaveColliderToBeEnabled; j++) {
        offset2 [numberOfVerticalCellsEachOfWhichMayHaveColliderToBeEnabled * i + j] = new Point2 (i - numberOfHalfOfHorizontalCells, - 1 - j);
      }
    }
  }
  
  void FixedUpdate ()
  {
    playerPosition = playerTransform.position;
    Point2 mapPointOfPlayerPosition = map.WorldPointToMapPoint (playerPosition);

    Point2 [] listOfPoint2InCellWhichMayHaveColliderToBeDisabled = new Point2[numberOfHorizontalCells * numberOfVerticalCellsEachOfWhichMayHaveColliderToBeDisabled];
    for (int i = 0; i < numberOfHorizontalCells; i++) {
      for (int j = 0; j < numberOfVerticalCellsEachOfWhichMayHaveColliderToBeDisabled; j++) {
        listOfPoint2InCellWhichMayHaveColliderToBeDisabled [numberOfVerticalCellsEachOfWhichMayHaveColliderToBeDisabled * i + j] = mapPointOfPlayerPosition + offset1 [numberOfVerticalCellsEachOfWhichMayHaveColliderToBeDisabled * i + j];
      }
    }
    foreach (Point2 p in listOfPoint2InCellWhichMayHaveColliderToBeDisabled) {
      SwitchColliderEnabled (p, false);
    }

    Point2[] listOfPoint2InCellWhichMayHaveColliderToBeEnabled = new Point2[numberOfHorizontalCells * numberOfVerticalCellsEachOfWhichMayHaveColliderToBeEnabled];
    for (int i = 0; i < numberOfHorizontalCells; i++) {
      for (int j = 0; j < numberOfVerticalCellsEachOfWhichMayHaveColliderToBeEnabled; j++) {
        listOfPoint2InCellWhichMayHaveColliderToBeEnabled [numberOfVerticalCellsEachOfWhichMayHaveColliderToBeEnabled * i + j] = mapPointOfPlayerPosition + offset2 [numberOfVerticalCellsEachOfWhichMayHaveColliderToBeEnabled * i + j];
      }
    }
    foreach (Point2 p in listOfPoint2InCellWhichMayHaveColliderToBeEnabled) {
      SwitchColliderEnabled (p, true);
    }
  }

  void SwitchColliderEnabled (Point2 givenPoint2, bool b)
  {
    Cell cellOfGivenPoint2 = map.GetCell (givenPoint2);
    if (cellOfGivenPoint2 != null) {
      Collider2D colliderOfCell = cellOfGivenPoint2.collider;
      if (colliderOfCell != null) {
        colliderOfCell.enabled = b;
      }
    }
  }
}

使用した Nostalgia の Version 1.0.2 を追記した。 2014-09-25

2014年9月4日木曜日

Unity 用タイルマップエディタ AutoTileSet (Version 1.3) と Nostalgia (Version 1.0.2) の比較

  1. 背景
  2. AutoTileSet の特徴
  3. Nostalgia の特徴
  4. 両者の比較

1. 背景

Unity で作成中のゲーム (2D ジャンプアクション) でマップを作成するに当たり、手作業で床、壁、足場等のプレハブをシーンビューに配置したところ、非常にダルかった。それで、テキスト (CSV, TSV, XML等) でタイルマップのデータを作成し、これを読み込んで表示する、ということを検討したところ、Tiled Map Editor (http://www.mapeditor.org/) を使うことで画像の作成は簡単だったが、画像とは別にコライダーやレイヤーの情報を手入力する必要があるため非常に面倒で、Unity 内で作業が完結しないのもいまいちだった。

そこで、 Asset Store にて Unity のシーンビューで直接タイルマップの作成が可能なアセットを検索したところ、いくつか見つかった。本稿では、その中で無料であった AutoTileSet (Version 1.3)と、RPGツクールVX規格またはWOLF RPG Editor規格のオートタイルに対応していると見てとれた Nostalgia (Version 1.0.2) を取り上げ比較した。

2. AutoTileSet の特徴

長所

  • 無料なので資金に余裕の無い個人開発者にとってはありがたい。
  • ペンと消しゴムの切り替えが自動。シーンビューでタイルがないところをクリックするとタイルを配置でき、タイルがあるところでは消去できる。また、ドラッグすると最初のクリック時の動作をし続ける。
  • ヒエラルキーのAutoTileSet のプレハブ以下に各タイルに対応するタイルの名前の GameObject が生成される。それにスクリプトをアタッチして色々できる。
  • 段差があるところを段々にするか斜面にするか切り替えることができる。
  • タイルにバリエーションをもたせることができる。元々のタイルセットに加えて1つ以上のバリエーションをもつときにタイルを配置するとそれらの中のいずれかのタイルセットから適切なタイルが配置される。これにより見た目に単調なマップにならずに済む。
  • サンプルシーンの見栄えがよい。洞窟に光が差し込んでいる感じが出ている。

短所

  • ツールがないので、まっすぐな線を引くのがむずかしく、塗りつぶしするのも面倒。
  • AutoTileSet用のオートタイルセットは48パターンも必要なので素材を自作するのはちょっと大変かも。せっかくあるバリエーションの利点を殺しかねない。同じ開発元の AutoTileGen (Steam等 にて $25 くらい?で販売中) を使えば5パターン (うち2パターンはマスク) の画像を元に48パターンの画像からなるタイルセットを生成できるようだ。
  • サポートが英語。他の外国語よりはずいぶんマシだが。

Nostalgia の特徴

長所

  • ペン、消しゴムの他、矩形範囲のタイル配置 / 消去、塗りつぶしツールがある。
  • RPGツクール VX または WOLF RPG Editor の形式のオートタイルを扱える。
  • 作者が日本人なので日本語でサポートが受けられる。
  • Refreshボタンがあり、タイルセットを更新したときに再描画できる。シーンを複製してタイルセットだけを総換えする等でマップの再利用に便利。

短所

  • 矩形ツールまたは塗りつぶしツールの適用範囲が広いともたつき、広過ぎると最悪 Unity が応答無しになった。死んでもいいプロジェクト等でその辺の感覚をつかんでおいたほうがよい。
  • サンプルシーンが微妙。
  • 斜面のサポートはないようだ。今のところ使う予定はないけど。

その他

  • Map以下の構造 (Cell, Collider等) はインスペクター上では隠蔽されているが、スクリプトでアクセスする手段は用意されているのでそちらを使うべし。作者さんに教えてもらうまで気付いていなかったが、使うの自体はむずかしくない。

4. Nostalgia と AutoTileSet の比較

以下に比較の表を示す。

表. Nostalgia と AutoTileSet の比較
項目 Nostalgia AutoTileSet コメント
ペン Nostalgiaのペン先の矩形の大きさは可変。
消しゴム Nostalgiaの消しゴム先の矩形の大きさは可変。
矩形選択配置 × Nostalgiaの大量配置に難あり。
矩形選択消去 × Nostalgiaの大量消去に難あり。
塗りつぶし × Nostalgiaの大量配置に難あり。
Refresh × あるとマップの再利用等に便利。
バリエーション × あるとマップが視覚的に単調になりにくい。
1タイルセットのパターン数 5 48 少ないほうが素材の自作は楽。
サポート言語 日本語 英語 英語でも可だが、母国語である日本語の方がいい。英語以外の外国語は辛い。
斜面 × -
例は例でしかないが、例買いもある?
価格 20$ 0$ -

◎: よい, ○: わるくない, ▲: よくない, △: わるい, ×: 機能なし.

RPGツクールVX規格またはWOLF RPG Editor 規格のオートタイルに対応という時点で Nostalgia 以外の選択肢がなかった (あるいは筆者が分からなかっただけで実はどこかにあったのかもしれないが、分からないものはないのと同じ)。素材を自作する場合でもわずか5タイルのパターンを作成すればよく、そうでない場合でもフリー素材が利用可能なので、両規格に対応していることはかなりのメリットだと思う。タイルセットのコンバーターを書くのは比較的容易だと思われるが、都度別途コンバートするのは面倒。元から対応していればその面倒はない。AutoTileSet の方が優れている項目のうち斜面、例は今回は重視しない機能だったので不問、バリエーションはあればよかったカモというところ。それよりも矩形選択配置または消去、塗りつぶしの重さが課題か。

機能の優先順位は人それぞれなので、自分の要求にあったものを使えばいいと思うよ。事実誤認トカありましたら教えてください。

両者のバージョン (AutoTileSet (Version 1.3)と Nostalgia (Version 1.0.2)) を書き漏らしていたので追記した。この記事の内容は各アセットの最新版には当てはまらない可能性がある。 (2014-09-25)