3Dでの回転、移動の基礎

わざわざ色々調べて書くことはあるんだけど、ちょろっと繋ぎの簡単な話です。

最近、ゲームエンジンやらが便利なおかげで3Dの基礎的な知識がなくても3Dのゲームを作れたりするけども、なんだかんだ言っても知識がないと思った通りに動かなかったりする。
ということで、3Dでの回転と移動という動きの話。
まあ、こんな話を書くのは、この辺りの知識がなくても出来てない人を見たからなんだけども。

では、とりあえず机上の話ではなく、実際に体を動かして3Dを体感しよう。
なんていったって最も身近な3D環境は現実なんだから。

椅子と机に張り付かずに立ち上がってみよう。
立ち上がったら今いる位置を覚えておく。
それから、以下の順番で動く。
1. 右45度の方向に体を向ける
2. 前に一歩移動する

はい、簡単ですね。よくできました。
じゃあ、今度は逆の動きをして元の位置に戻ってみよう。
1. 左45度の方向に体を向ける
2. 後ろに一歩移動する

元の位置に戻れた人、ハーイ!
その人は最初からやり直しましょう。
元の位置に戻れなかった人は正しいです。

逆のことをしたのに元の位置に戻れないのはなぜか。
それは回転と移動の順番を逆にしていないから。
元の位置に戻るための正しい手順は以下。
1. 後ろに一歩移動する
2. 左45度の方向に体を向ける

というように、3Dでは回転と移動の順番が非常に重要で、これを間違えると思った通りの移動ができない。
例えば回転と移動の量を渡すとその通りに動かしてくれる関数があるとする。
これで今やったように回転と移動をした後、元の位置に戻すために逆の値を渡すとどうしても同じ位置には戻ってくれない。
なので、回転を行う関数と移動を行う関数を別々に呼び出して回転と移動をする必要がある。

まとめてやってくれるのは便利だけど、順番だけは気にしてやらないといけない。
ゲームエンジンとかを使うのであれば、まとめて回転と移動をしてくれる関数を使うとその順番がどうなっているかは見えにくいので、最初から回転と移動を別で行った方が実はいいのかもしれない。

ギルティギア2のサーヴァントの動き方について

作りたいっていう理由もあるので、ゲームの作りについて書いていこうかと。
そのうちUE4でどう作るかも詳しく書いていくかも。
今の時点ではこれで出来るっていうやり方もちゃんと分かってないわけだけど…

で、作りたいゲームっていうのは「ギルティギア2」(以下、GG2)

RTS + アクション でできているゲームで、RTSでも他と比べると内政とかがないので結構取っつきやすいはず。
とりあえずRTS部分の要になるユニット(ゲーム内ではサーヴァント)の動きの中でも、
指示を与えて目的地に移動するための考え方について書いていこうかと。

どんな感じの動きをしているかはYouTubeとかニコニコで対戦動画とか見て欲しいんだけれども、ゲーム中でやることが忙しくてユニットが歩かないようにしていたりするので、とにかく何をやってるか分かりにくい。
分かりやすそうなのはニコニコの公式対戦動画くらいかな?
ギルティギア2 公式対戦動画「HEAVEN OR HELL ? #1」 ‐ ニコニコ動画:GINZA

 

ストーリーモードやってる動画もいいかな?
チュートリアルを兼ねてるし。

この記事を書いてる間にsteamで配信が開始されたようなので、とりあえず買ってみて、やるかどうか考えるのもいいかと思います。

 

GG2ではサーヴァントがとにかく最短経路を歩くようにはなっておらず、途中の陣地(ゴースト)を通るように歩いたりしている。
つまり、予めどこを通るのかが決まっているということ。
イメージとしてはそれぞれのゴーストの間の道に線が引かれていて、その上を歩くようなイメージ。

じゃあ、その線がどういうふうに引かれているのかというと、サーヴァントの動きをよく見ると分かるけれど、道が曲がっているような場所でも真っ直ぐに歩いて、常に同じ地点で向きを変えてまたまっすぐに歩いている。
つまり、全て直線で構成された道になっていそうな感じ。

大雑把にこんなの。
数字はゴースト

f:id:aki_senri:20160401012354p:plain

 

ただ、実際には直線の道だけではないし、障害になるような物があったりもする。
そうなるとどうすればいいのかというと、曲がっているような道にも見えない中継地点が設定されていて、そこに向かって直進し、中継地点で次の中継地点の方を向き、また直進を行っていくということを繰り返せばいいはず。

こんな感じ。

f:id:aki_senri:20160401013802p:plain

 最近見たのだとLoLやParagonなんかはミニオンがこの形で動いていそう。


そこの中継地点がどれくらいあるかとかは場合によるからおいておき、じゃあ実際にどこを通るかを決定するにはどうするのか。
探索の計算量をあまり増えないようにすることを考えると、正方形のタイルで構成されたマップ上を探索するようなのは、マップが広くなると計算量が増えていくのであまり現実的ではなくなっていく。

じゃあどうするのかというと、「グラフ」というデータ構造を利用する。
これはそれぞれの頂点同士を繋ぎ合うデータ構造で、GG2のようにゴーストとゴーストが道で繋がれているのと同じようなイメージのデータ構造になるので、利用するのにはとても都合がいい。
このグラフで現在地の頂点から目的地の頂点までの探索をすれば、そのままサーヴァントが通るルートが出来上がる。

ただ、グラフにも種類があり、GG2のように距離が関わるような場合には「重み付きグラフ」を利用する。
この「重み付きグラフ」のいいところは、頂点に重みをつけるのではなく、頂点同士をつなぐ辺に重みをつけること。
つまり重みを距離と置き換えれば、最短距離になるルートを探索できる、まさにGG2にはおあつらえ向きなデータ構造になっている。
さらにグラフには種類があり、無向と有向のグラフがある。
無向グラフというのは、例えばAとBという頂点がつながっている時に、A→BのルートもB→AのルートもOKになる構造。
有向グラフというのはA→BのルートはOKだけれど、B→Aのルートがないような構造。
例えば崖のようになっている道があり、上から下には行けるけど、下から上には行けないような道にしたい場合には有向グラフ、どちらからも行けるような道だけにしたいのであれば無向グラフを使用するのがいい。


有向グラフの場合には方向だけでなく、重みも方向毎別々に設定ができるので、
A→Bは行きやすいけど、B→Aには行きにくいというような事もできる。

 

無向グラフの例
赤字は重み。

f:id:aki_senri:20160401014915p:plain

 

有向グラフの例

f:id:aki_senri:20160401015013p:plain

 

実際に実装する場合には色々と探索を行うアルゴリズムがあるんだけど、その場で計算するとそれなりの時間がかかったりするので、事前に計算しておいた結果を利用するといいかも。
これをUE4で作りたいけど、データ構造をどうしたものか・・・

ブログ開設のあいさつ

おはこんばんちは!

 

色々なところで前からブログをやるやる言って、ようやく動きました。

このブログでは 基本的にはゲーム制作の手法のことだったり、ゲーム制作に関係することを書いていこうと思っています。

そこから、いつかどこかでゲームをリリースしたりできたりしたらいいなと考えてます。とりあえず考えるだけ。

いつまでどれだけやるのかも分かりませんが、誰かの何かの役に立てればと思います。