##これを解説します
###分解するとこう
一番右の4コマ目が今回目指す完成形です。
###完成品
##はじめに
どうも!再び登場B'z大好き芸人のウルトラ深瀬です!(またお前か)
当記事ではARKitを使ったFPS風ゲームの作り方を解説します。
今回は その2 ということで「ゆらゆらモーション」を解説していきます!
前回の記事はこちら▶︎【ARKit】社長が好きすぎて駆逐するアプリを作った話 その1. FPS視点への固定編
続きはこちら▶︎【ARKit】社長が好きすぎて駆逐するアプリを作った話 その3. 爆発の作り方編
##そもそもなぜ必要?
立体感とゲームらしさの演出の為です。
これをやらずにFPS視点に固定しただけだと、まるで静止画を貼り付けているようにも見えてしまいます。
もともと立体的でリアルな3Dモデルがそれでは勿体ないので、是非トライしてみましょう!
##SCNActionを使います
公式で用意されているSCNActionというものを使用します。↓
https://developer.apple.com/documentation/scenekit/scnaction
また、SCNActionについてはこの方の記事もとても参考になりますので是非ご覧ください。
##大まかな流れ
冒頭でも載せましたが、まさに下記の4コマの流れで作っていきます。
###コード
//【1コマ目】(上4コマでは往復1.6秒(片道0.8秒)にしていますが、4コマ目で最終的に下記の往復2.4秒(片道1.2秒)になります)
//銃の先端が上に跳ね上がる回転のアニメーション
let rotate = SCNAction.rotateBy(x: -0.1779697224, y: 0.0159312604, z: -0.1784194, duration: 1.2)
//↑の逆(下に戻る回転)
let rotateReverse = rotate.reversed()
//上下のアニメーションを直列に実行するアニメーション
let rotateAction = SCNAction.sequence([rotate, rotateReverse])
//【2コマ目】(往復1.6秒(片道0.8秒))
//銃が垂直に持ち上がるアニメーション
let moveUp = SCNAction.moveBy(x: 0, y: 0.01, z: 0, duration: 0.8)
//↑の逆(垂直に下に下がる)
let moveDown = moveUp.reversed()
//上下のアニメーションを直列に実行するアニメーション
let moveAction = SCNAction.sequence([moveUp, moveDown])
//3コマ目を飛ばして【4コマ目】
//回転と上下移動のアニメーションを並列に同時実行するアニメーション(それぞれのdurationをずらすことによって不規則な動き感を出している)
let conbineAction = SCNAction.group([rotateAction, moveAction])
//↑を永遠繰り返すアクション
let gunnerShakeAction = SCNAction.repeatForever(conbineAction)
//アクションをピストルに付与 & 実行 (*今回はピストルの親ノードではなくピストル本体に対して行います)
sceneView.scene.rootNode.childNode(withName: "parentNode", recursively: false)?.childNode(withName: "M1911", recursively: false)?.runAction(gunnerShakeAction)
##ポイント
コードをみていていただくとわかりますが、今回はコンボ技を多用しています。
rotate(回転)、move(移動)、reverse(巻き戻し)などの単一アクションに加え、
・sequence([A, B]) → ABを直列に(順番に)
・group([A, B]) → ABを並列に(同時に)
の2種類の複数アクションを使い分けています。
また、
一番のポイントは AとBの実行時間をずらす ことで自然な動きに見せているところです。
###備考
1コマ目の銃口を跳ね上げる回転の指定値の計算方法については、今回かなり複雑な計算になってしまったため、別途整理ができてから追記しようと思います。
ピストル本体のeulerを前回の記事と全く同じに設定している方は、今回の回転指定値でそのままコピペで動くかと思います!
別のオブジェクトなどで試したい方は、まずscnファイルのエディタ上で銃口を跳ね上げた状態まで動かし、その前後のeulerの各値(x,y,z)との差分を求めます。
そしてコード上に取り込んだ実際のピストルの現在のeuler値を出力し、(エディタ上の設定値とコード上に取り込んだPistolのeuler値の単位がなぜか全然違うので)先ほど求めた差分をコード上の値の単位に変換してから設定するといいかと思います。
##応用
今回と同様の発想で次のような動きも実装可能ですので、是非色々試してみてください♪
①ユーザーの移動の速さに応じてピストルを左右に揺らす
②発砲時の反動を演出
##駆逐アプリの続きはこちら
[【ARKit】社長が好きすぎて駆逐するアプリを作ったはなし その3. 爆発編(特殊効果など)]
(https://qiita.com/Takamasa_Fukase/items/78ea8ea26bf0e40fd526)
の解説は12/17(木)のアドベントカレンダーにて投稿予定です。
お楽しみに!
##さいごに
続きまして、アルサーガパートナーズ Advent Calendar 2020 15日目の記事は、我らが大先生 @ovama-koffee さんのご登場です
##おまけ
今回の駆逐アプリの元ネタになった個人ゲームアプリ「AR-GunMan」がAppStoreにて配信中です♪
https://apps.apple.com/jp/app/ar-gunman/id1542082005