yumeの日記: Unity制作 メデューサ・ゲーム #20 1
●壁を疑似立体に
現状は壁などの物体は平面だ。これは視界がどう広がるか、やどこが進行不可能なエリアかが一見してわかりやすいものの、表現としては拙いものだ。
そこで壁全体をこのような立体風の表現にしたい。
まずそれに伴い、キャラクターなどの描画順をY軸の順にソートする。
これはUnityデフォルトの設定にあるらしいが、自分の場合UniversalRenderだのなんだのにしたためかその設定がなかった。
そこで、カメラに新たなコンポーネントを追加することとした。
void Start()
{
var camera = GetComponent<Camera>();
camera.transparencySortMode = TransparencySortMode.CustomAxis;
camera.transparencySortAxis = new Vector3(0.0F, 1.0F, 1.0F);
}
これで、カメラはY軸とZ軸を基準に描画順をソートできるようになるそうだ。
Z軸を使っている理由は、そのままではY軸のソートの基準点を細かく調整できないため。
(スプライトの原点はスプライト側で設定できるようだが、ここではZで調整することとした)
実際の壁の描画は、後々テクスチャを載せることなども考えるとSpriteShapeRendererを使う方がよさそうだ。
これは、ある多角形を自由に設定して、それにAdobe Illustartorでいうところの線と塗りをスプライトで設定できる、という代物らしい。
便利なことに、Shapeで定義した多角形をそのままPolygonCollider2Dに当てはめることができる。さらに微調整もできるようだ。
問題は天板だ。現状の壁の領域、つまりShapeRendererのShapeをそのままコライダーとして、
これをコピーした天井用のShapeRendererを子オブジェクトとして追加し、スプライトを天井用のものに差し替え、Y軸を0.5だけ上にあげるとだいたい想定通りのものができる。
しかしすべての壁でこれをやるのはちょっと面倒臭いというか、機械的な処理だからなんかうまいことできそうな気がする。
こういうのはどうか。
まず天井用の頂点(Spline.potision)は全部で3つにしておく(2つ以下にできないので)。それぞれ邪魔にならない位置にセットしておく。
ゲームが開始され、ステージが始まるとき、Wallが読み込まれた後、天井はWallのSpline.positionを取得し、自分のSpline.potisionをすべて破棄し、改めて自分のSpline.potisionをWallと同じローカル座標に配置する。
private void SetCeilPolys()
{
myShapeController.spline.RemovePointAt(0);
myShapeController.spline.RemovePointAt(1);
myShapeController.spline.RemovePointAt(2);
for (int i = 0; i < parentSController.spline.GetPointCount(); i++)
{
myShapeController.spline.InsertPointAt(i, parentSController.spline.GetPosition(i));
}
}
うまくいきそうだが、動かすと壁の形状によってはおかしな形になってしまう。どうもremovePointAtで削除できていないような?
Removeしてから追加、ではなく、最初の3点までは直接ポジションを変更、以降は追加とする。
private void SetCeilPolys()
{
for (int i = 0; i < parentSController.spline.GetPointCount(); i++)
{
if (i < 3)
{
myShapeController.spline.SetPosition(i, parentSController.spline.GetPosition(i));
}
else
{
myShapeController.spline.InsertPointAt(i, parentSController.spline.GetPosition(i));
}
}
}
するとうまく動いた。
これはUnityエディタ上で実行するやり方を使うとよいのかもしれない。エディター用にスクリプトを作ることもできるらしい。しかしひとまずこれで行こう。
同じように扉や窓、スイッチ、カーテンも立体風にしていく。
バグメモ:天井を下側にめり込ませるためにステージからはみ出させると、視界が少しゆがむ
現在のステージ総数:12
spline.removePointAt() (スコア:0)
removePointAt() が意図した通りに動かないのは、たぶんこんな動作になっているから。
// 初期状態では myShapeController.spline の頂点は3個: spline[0~2]
myShapeController.spline.RemovePointAt(0); // spline[0~2]からspline[0]を削除 → 頂点は2個: spline[0~1]
myShapeController.spline.RemovePointAt(1); // spline[0~1]からspline[1]を削除 → 頂点は1個: spline[0~0]
myShapeController.spline.RemovePointAt(2); // spline[0~0]からspline[2]を削除 → spline[2]は無い(spline[0]が残る or エラー?)
こんな場合は 2→1→0 と後ろから削除すればOK。
または、Clear()メソッドが有るみたいだからそれを呼べば全部消えるかも知れない。
myShapeController.spline.Clear(); // splineをクリア