ゲーム開発の概要 - Unity で境界付き 2D マップを作成する方法
Unity で 2D ゲームの境界マップを作成し、エッジを接続します。これは、Clash Royale やその他の種類のゲーム向けの軽量でシンプルなソリューションです。
マップを作成するとき、プレイヤーを境界内に留めておきたいと考えます。しかし、世界が実際にそれ自体を包み込むことも素晴らしいことです。これは、ゲームの仕組みに興味深い要素を提供すると同時に、プレイヤーに自由度が高まったという印象を与えることができます。
この記事では、2D ゲームでこの動作を実現する簡単な方法を説明します。
N × M グリッド マップでのプレーヤーの位置の制限
ほとんどの場合、2D ゲームのマップは、完全に配置された N × M グリッドとして定義されます。この場合、プレーヤーの位置を境界内に制限するための明らかな解決策は、定義された境界に対する相対的な位置を確認し、それに応じて調整することです。
これは、単純な Monobehaviour コンポーネントで実現できます。
class PositionClamper: MonoBehaviour {
public int mapWidth;
public int mapHeight;
void LateUpdate() {
Vector3 pos = transform.position;
//假设地图从(0,0)开始
pos.x = Mathf.Max(Mathf.Min(pos.x, mapWidth), 0);
pos.y = Mathf.Max(Mathf.Min(pos.y, mapHeight), 0);
// 设置transform position.。尽可能使用本地位置local position
}
}
これにより、プレイヤーの位置がマップの寸法内に固定されるようになります。
注意すべき点の 1 つは、複数のゲーム オブジェクトがこれらの境界をチェックするため、Scriptable オブジェクトやシングルトンなどの外部データ ソースを使用するようにオブジェクトを書き直すことを検討する必要があることです。これは、各ゲーム オブジェクトでフィールドを直接指定するよりも便利で、エラー耐性が高くなります。
ラップアラウンド座標を実装する
これも非常に簡単で、トランジション位置が範囲外かどうかを確認し、それに応じて調整するだけです。
また、ブール値を使用して、位置をラップアラウンドするかどうかを確認します。
class PositionClamper: MonoBehaviour {
public int mapWidth;
public int mapHeight;
public bool isWrapping;
void LateUpdate() {
Vector3 pos = transform.position;
if (bIsWrapping) {
如果我们到达地图的x边界,请将位置回绕到0,使用地图尺寸
if (pos.x > mapWidth) {
pos.x -= mapWidth;
} else if (pos.x < 0f) {
pos.x += mapWidth;
}
// 我们对y也做同样的事情
if (pos.y > mapHeight) {
pos.y -= mapHeight;
} else if (pos.y < 0f) {
pos.y += mapHeight;
}
} else {
pos.x = Mathf.Max(Mathf.Min(pos.x, mapWidth), 0);
pos.y = Mathf.Max(Mathf.Min(pos.y, mapHeight), 0);
}
// 设置transform position。尽可能使用本地位置local position
transform.position = pos;
}
}
このようにして、プレイヤーがマップの境界に到達すると、実際にはマップの反対側の端にテレポートされます。
実際には、上記のコードを記述して if の記述を避ける、よりクリーンな方法があることに注意してください。モジュロ演算子を使用してください。
pos.x = pos.x % mapWidth;
pos.y = pos.y % mapHeight;
より多くのスプライトを描画して、シームレスなトランジションをシミュレートします
上記のアプローチの主な問題は、他のプレイヤーから見たときにプレイヤーが「テレポート」しているように見えることです。
ここでも簡単なトリックを使用します。もっと元気を引き出すだけです。
現在のプレーヤー ゲームオブジェクトを中心として使用し、同じスピリットを含む他のゲームオブジェクトを異なる位置に追加する必要があります: (-mapWidth, 0)、(mapWidth, 0)、(0, -mapHeight)、(0, mapHeight )。
シンプルではありますが、このアプローチでは、スピライトの現在の状態を子間で共有する必要があり、スピライト レンダラーを持つすべてのゲームオブジェクトにそれを適用する必要があります。
それでも、同じスピリットを複数回描画するのでバッチ処理されるため、パフォーマンスへの影響はそれほど大きくないはずです。