Unity1Week 「回」で重力を操る能力者になった
「回」 ← 一つ目の箱が走ってるみたいで可愛い。
2週間ギリギリで投稿しました。ギリギリとは?
書く気が残ってるうちに書きます。
最初は参加する気はなかった
仕事も忙しいし、この前参加したばかりだし、でもせっかくなんで余裕があればプロトタイプな何かを作ろうかなと思ってました。学生さんが参加しやすい時期を狙ったという事なので、なるべくシンプルで参考になるゲームでもと思ったんです。ええ、あのときは。
重力を操るのは簡単?
3Dゲームで物体に吸着する重力を実装するのは意外と簡単でした。
難しい数学や科学の知識などは一切要りません。そもそも僕にその知識がありません。ただし、ゲームにする場合はもっと別のところが課題マシマシアブラカラメになります。
実は以前もマリギャラの重力の仕組みを作ってみたいと思ってチャレンジした事があったんです。しかし、そのときは上手く作れずに失敗しました。その時の方法はこんな感じです。
『箱の周囲にルービックキューブのように重力トリガーを置いて、入っているトリガーに応じた重力を与える』
え、これ酒飲んで考えたのかな?今見るとビックリしますが、当時は若かったんでしょうね…一昨年くらいの話です。
まあ、そもそも「あらゆる地形に対して重力が働く」というルールを成立させようとした場合、何をどう判定するかは非常に難しい問題です。
そこで今回はプリミティブな地形のみで実験してみる事にしました。
今回の重力の計算方法
例えば球の場合は簡単です。中心に向かうベクトルをそのまま重力にすれば良いだけなので。問題は多角形です。まず2Dのボックスで考えてみます。
プレイヤーの位置に対して働く重力の方向は大体こんな感じです。
この場合座標軸ごとに計算すると簡単です。まずプレイヤーから箱の中心への差分を算出し、以下の計算をします。
・X差分が横幅以内の場合、平行に落ちるためX軸の重力は0
・Y差分が縦幅以内の場合、平行に落ちるためY軸の重力は0
・それぞれ外側にいる場合、それぞれの辺の頂点に向かう
関数にすると以下のようになります。
// プレイヤーからボックスへの重力を算出
Vector2 CalcGravity(Vector2 position, Vector2 center, Vector2 size)
{
// 中心へのベクトル
Vector2 vector = center - position;
vector.x = Clamp(vector.x, size.x * 0.5f);
vector.y = Clamp(vector.y, size.y * 0.5f);
return vector;
}
// 差分が辺の内側なら0に、外側なら頂点への差分に変換
float Clamp(float diff, float halfSize) => diff > 0f ? Mathf.Max(diff - halfSize, 0f) : Mathf.Min(diff + halfSize, 0f);
3Dの場合も軸が増えるだけで同じです。
問題は水平な場合はこれで良いですが、キューブ(ボックス)が回転している場合は軸をあわせる必要があります。その場合は一回ベクトルにキューブのrotationの逆回転を掛けてから重力を計算し、また回転を掛けて戻してやれば大丈夫です。
public Vector3 CalcGravity(Vector3 position, Vector3 center, Vector3 size)
{
var vector = center - position;
vector = Quaternion.Inverse(transform.rotation) * vector;
vector.x = Clamp(vector.x, size.x * 0.5f);
vector.y = Clamp(vector.y, size.y * 0.5f);
vector.z = Clamp(vector.z, size.z * 0.5f);
return transform.rotation * vector;
}
後は同じ要領でシリンダーやカプセルも計算できます。
とるにたらぬ重力どもよ!支配してやるぞッ!!
さて、単純なオブジェクトへの重力計算はかなり簡単にできました。
「じゃあすぐ作れるじゃん。二週間何してたの?w」と思うかも知れませんが、ここからが大変でした。まずそれぞれの重力の影響をコントロールしないといけません。また、物体に立てたとしてもキャラクターの操作方向やカメラ制御の問題が残ります。それらについてですが…
疲れたので今回は書きません!
キミの目でたしかみてくれ!
この記事が気に入ったらサポートをしてみませんか?