ニンテンドーラボのゲーム自作モード(トイコンガレージ)マジで凄いです。
特にゲーム内に元から用意されているサンプルゲームのプログラムを見られるのが非常にいいです。
任天堂の社員が設計したモノホンのプログラムを5000円払って見放題ってとんでもない事ですからね。
そこら辺のUnity参考書よりよっぽどゲーム作りの勉強になると思います。
今回はそのサンプルプログラムを使って「ゲームのカメラ制御はどのように行われているか」をプログラミングをやったことがない人にも出来るだけ分かるように解説したいと思います。

目次
視点の動き方
マリオの例
マリオ カメラ #スーパーマリオオデッセイ #SuperMarioOdyssey #NintendoSwitch pic.twitter.com/bt79DSN93o
— コガネ (@Kokintamadekao) August 28, 2020
マリオやゼルダ、モンハンなどの三人称視点ゲームはだいたいこのようなカメラの動き方です。
ダメな例
駄目なカメラ #NintendoSwitch pic.twitter.com/fl3kyIHIc2
— コガネ (@Kokintamadekao) August 28, 2020
まず自力でTPSカメラを作ってみようとしましたが失敗に終わりました。
右スティックを入力してもカメラが動きませんし、
プレイヤーを下方向に動かすとカメラがクルクル回転して使い物になりません。
理想の視点
▲がカメラで真ん中の●がプレイヤーキャラだと思ってください。
カメラは図のように
- 常にプレイヤーを中心に映す
- 常にプレイヤーと一定の距離を保つ
の二点を守ると比較的ストレスの少ない三人称視点になります。
ただし、壁際の時などの視点操作は非常に複雑なので今回は省略します。
また、視点操作の種類として、
- 右スティックでメイン視点操作
- 左スティックでプレイヤーが移動する際の視点補正
の2つが挙げられます。
メイン視点操作
プレイヤーが移動する際の視点補正
プログラム解説
ニンテンドーラボで実装されている、その理想のカメラ操作のプログラムがこれです。
意味が分からないですね。
これから1つ1つ解説します。
スティックから入力
最初の「スティックが入力されたらカメラの角度を変更しますよ」という部分です。
ジョイコンのスティックは倒す強さによって、[0~1]の範囲で出力をします。
本気で倒せば[1]が、何もしなければ[0]が、少しの力で倒せば[0.3]や[0.5]が出力されるってことです。
なお、右に倒せば正の値が、左に倒せば負の値が出力されます。
上のL左右スティックがジョイコンLのスティックで
下のR左右スティックがジョイコンRのスティックです。
Lスティックの右に「マッピング」という処理が挟まっていますね。
この「マッピング」によってLスティックの[0~1]の入力を[0~0.6]の範囲に変換して入力値を小さくしています。入力値が負の場合は自動で出力値も負の値になります。
要は、「Lスティックでの視点移動はあくまで補正なので、Rスティックの入力値よりも小さくする必要があるよ」って事です。

角度を表現
それぞれのジョイコンR・Lの出力を「+」で足し合わせてから出力し、右下の「カウンター」に貯めています。
「カウンター」は入力された値をセーブしてそのまま出力するものです。
カウント範囲(今回は360)を超えた数値はループするようにしています。
つまり、[0,1,2,3,4,,,,358,359,360,0,1,2,3,4,,,,]
とカウントして出力します。
こうすることで、カウンターは「初期位置から現在どれくらいの角度回転しているか」を表すことが出来ます。
下の図で説明すると、カメラを動かしたときの角度θがカウンターの中身になります。
実はカウンターの範囲は[0~360]じゃなくていいんですが、分かりやすさ優先でこうしています。
範囲を広くするとカメラの速度が速く、狭くすると遅くなります。
範囲を変えると1周に必要なスティックの入力量が変わるからです。
角度を位置に変換
カメラの角度が分かってもそのままでは使えないので、三角関数を使ってカメラの位置を座標に変換します。
「角度を位置に」を使うと入力値θが[0~1]にマッピングされて(cosθ,sinθ)として出力されます。
例えば、[90°]が入力されると[0.25]に変換され(0,1)が出力されます。
[315°]が入力されると[0.75]に変換され(1/√2,-1/√2)が出力されます。
図で表すとこうなります。

カメラとプレイヤーの距離を離す
今の状態ではカメラとプレイヤーの距離が1なので近すぎます。
なので、カメラの位置(cosθ,sinθ)の範囲[0~1]を[0~3]にマッピングすることで、カメラとプレイヤーの距離を3倍にしています。
図で表すとこんな感じです。要はカメラの軌道円の半径を三倍にしただけですね。
カメラの座標にセッティング
今までの処理でプレイヤーとカメラの間の角度と距離はわかりましたが、カメラのゲーム内での実際の位置はわかっていません。
例えるなら、「東京タワーの住所とそこまでの道順は分かってるけど、今自分のいる明確な住所が分からない」状態です。
今の自分の場所を特定するには東京タワーの住所から道順を逆算して割り出せばいいのです。(逆に分かり辛いか?)
「X」,「Z」はプレイヤーのx,z座標、
「U」,「W」カメラのx,z座標
の事です。
つまり、プレイヤーのx座標に3cosθを、z座標に3sinθを足せばカメラのゲーム内での実際の位置が分かるので、
その座標をカメラに渡して、そこにカメラを移動させます。これでカメラの位置はOKです。
そして、カメラの向きをプレイヤーの位置に設定すれば完成です。
カメラを反転
「角度を位置に」のa,b出力がクロスしているのに気付いた人はいるでしょうか。
aからcosθが、bからはsinθが出力されますが、cosθをz座標にsinはx座標に代入しています。
cosはx座標、sinはz座標なのになんで逆になってるの?と思った人は流石です。
試しにクロスさせずに動かして比べてみました。
x,zを逆にした クロスあり(サンプルプログラム)
x,zそのまま クロスなし
カメラが反転していますね。
図にすると分かりやすいかもしれません。緑色がクロスありの前者の動画で黄色がクロスなしの後者の動画です。
x成分とz成分がそのまま入れ替わっているので黄色と緑が逆方向に移動するのは考えてみれば当たり前のことです。
クロスなしの後者は手前のカメラ自身を操作しているのに対して、
クロスありの前者は画面奥の視点を操作している
とイメージしてもらえれば分かりやすいかもしれません。
どっちがいいかという話ではないですが、クロスありの前者のほうが筆者は好きです。
完成
#NintendoSwitch pic.twitter.com/nZ1HsSACKX
— コガネ (@Kokintamadekao) August 28, 2020
ストレスフリーな視点操作になりました。
足元の数値を見てもらえればより分かりやすくなるかもしれません。
最後に
説明下手すぎて多分何言ってるか分からないと思うので、コメントで聞いてくれたら答えます。
ニンテンドーラボ文句なしの神ゲーです。
自分の勉強を兼ねて今後もこういう記事書きたいと思います。
↑こっちが完全版
↑こっちが廉価版 今回の記事みたいにゲームだけ作りたい人はこっちでも大丈夫