Unityを使った3Dゲームの作り方(かめくめ)Unityを使った3Dゲームの作り方(かめくめ)ゲーム開発エンジンUnityを使った3Dゲームの制作に参考になる情報を公開しています。0今回はUnityでソニーから発売されたホラーゲームSIRENの視界ジャック機能を作成してみたいと思います。SIRENの視界ジャック機能は屍人の視界(屍人の目線)で周りを見ることが出来、屍人の行動や喋っている言葉等を体感出来る機能です。わたくしがSIRENを好きなので作ってみました。上のように移動キーを押した方向に一番近い敵の視界になり、敵から見たゲーム世界を見ることが出来ます。最初はキーボードの方向キーで確認し、途中からPS4コントローラーを接続し確認しました。PS4コントローラーを接続すると音声がコントローラーヘッドホンの方に流れるようなので音声が消えたようになりました(動画では音声が流れます)。視界ジャック機能を作る前にまずはどうやって作るか?を考えていきたいと思います。操作キャラクターは通常通り移動や攻撃等(今回は移動機能だけ作成)が出来るようにして、視界ジャックを行うボタンを押した時に視界ジャックモードに入るとします。今回はPS4コントローラーの△ボタンを視界ジャックモードに入るボタンに割り当てる事にします(キーボードでも出来ます)。視界ジャックモードになったらキャラクターの移動や攻撃は出来ないようにし、コントローラーのアナログスティックで周りにいる敵を検索します。視界ジャック中はテレビの砂嵐動画と音声を再生します。アナログスティックの入力は横軸と縦軸の入力を3D空間のX軸とZ軸に割り当ててワールド軸の前方からの角度を計算し、敵のいる角度はワールド軸の前方からの角度で計算します。「ワールド軸の前方から見たアナログスティックの入力角度」と「ワールド軸の前方から見た敵の角度」を比較しより近い敵を視界ジャックする敵とします。Input.GetAxis("Vertical"));上のようにXZ軸に割り当てた場合は必ずVector3.forward(ワールド軸の前方)が縦軸の入力であるInput.GetAxis(“Vertical”)になってしまいます。キャラクターを90度回転させてアナログスティックの↑を押したとしてもVector3.forwardの方向の入力になってしまい、キャラクターの前方の入力になりません。本来であればアナログスティックの↑を押したらキャラクターの前方方向を押したと判定したいところです。ここでややこしくなるのが、アナログスティックの↑を押した時にキャラクターの前方方向を押した事に出来た場合でもアナログスティックの↑を押した時はワールド軸の前方からの角度を求めるということです。敵の角度もワールド軸の前方からの角度で、アナログスティックの角度もワールド軸の前方からの角度を求めます。キャラクターを90度回転させた時にアナログスティックの↑を押した時に90度が得られるようにします。入力はキャラクターの前方から見た方向を得る必要はあるが、比較する敵の角度とアナログスティックの入力方向はワールド軸の前方からの角度で計算するということですね。わたくしはここら辺でかなりこんがらがりました。(^_^;)一番近い敵がわかったらアナログスティックの入力角度の差によって砂嵐の濃さと音量を変化させます。Listenerを有効にします。これが視界ジャック機能の概要となります。視界ジャック機能をどうやって作るか?がわかったので、実際に作っていきましょう。操作キャラクターの作成まずは操作キャラクターを作成します。今回の操作キャラクターは↑のキーを押したらキャラクターの前方に進み、↓を押したら後方に進み、←→を押したらその方向に回転するようなキャラクターになります。キャラクターが前に進むには必ず↑のキーを押す必要があり、←→のキーで方向を定めます。キャラクターのモデルにはスタンダードアセットのEthanを使用し、CharacterControllerの取り付けをしてコライダの調整をしておきます。キャラクターのAnimatorControllerは立っている状態のIdle状態、歩いているWalk状態、後ろ向きに歩くWalkBack状態を作成します。それぞれの状態のアニメーションは以下のように設定します。IdleにはスタンダードアセットのHumanoidIdleWalkにはスタンダードアセットのHumanoidWalkWalkBackにはスタンダードアセットのHumanoidWalkを設定します。WalkBack状態を選択し、Speedに-1を設定してWalkBackでは歩くアニメーションを逆再生するようにします。アニメーションパラメータ―にFloat型のSpeedを作成します。Timeのチェックを外して直ぐに次の状態に遷移するようにします。新しいスクリプトViewJackCharaスクリプトを作成し、キャラクターであるEthanに取り付けます。heroState;}}スクリプトで行っていることは概要で説明したキャラクターの動きをさせる事とキャラクターの状態の取得と設定を出来るメソッドを用意していることです。横軸の入力があればtransform.Rotateを使ってキャラクターを回転させます。0f);}横に回転する時はアニメーションパラメータ―のSpeedを1にしてWalk状態に遷移させます。縦軸の入力の場合はアニメーションパラメータ―のSpeedに縦軸の入力値をそのまま入れて↑だったらWalk状態、↓だったらWalkBack状態へと遷移するようにします。0f);}また進む方向はキャラクターの向いている方向の前後になります。キャラクターを移動出来るのはキャラクターの状態がHeroState.Normalの時だけで、HeroState.ViewJackの時は移動出来ません。これで操作キャラクターが出来ました。視界ジャック機能のスクリプトを作成していきます。新しくViewJackScriptという名前のスクリプトを作成しEthanに取り付けます。スクリプトが長いので少しづつ解説します。フィールド宣言部まずはフィールド宣言部を見ていきます。currentAudioListener;}enemyListには視界ジャックが出来る敵をインスペクタで設定します。isViewJackは視界ジャックをしているかどうかのフラグです。fieldOfViewは視界ジャックをする敵のキャラクターの視野の角度です。この範囲外の敵は視界ジャック適用外とします。limitAngleOfViewJackはアナログスティックを押した角度と敵の角度の差がこの範囲内の時に一番近い敵かどうかの判定をします。snowNoiseMaxValueAngleLimitは砂嵐の強度の最大値を設定します。snowNoiseIntensityOffsetはアナログスティックの角度と敵の角度が完全に一致した時の砂嵐の強度の補正値を設定します。viewJackCharaはキャラクターの操作スクリプトであるViewJackCharaです。snowNoiseImageObjは砂嵐を表示するRawImageゲームオブジェクトを設定します。mainCameraはメインカメラを設定します。Listenerを設定します。currentCameraは視界ジャックをしている敵のカメラを入れます。currentAudioListenerは視界ジャックをしている敵のカメラに設定されているAudioListenerを入れます。Updateメソッド次にUpdateメソッドを見ていきます。Managerで設定したViewJackボタンを押した時に視界ジャック機能のオン・オフをします。Managerに関しては下記の記事の「UnityのInputManagerでキーとボタンの設定をする」の項目を参照して設定してみてください。PS3はいらないっぽい?ので他のソフトのダウンロードやインストールはせず「UnityのInputManagerでキーとボタンの設定をする」の項目だけまずは設定してみてください。PS3がいらなくなってるかも?)UnityでPS3コントローラー(ゲームパッド)に対応して動かしてみるUnityのゲームでPS3コントローラー等のゲームパッドを使用してみます。キャラクターの状態をGetStateメソッドで取得し、ノーマル状態なら視界ジャック状態へ、視界ジャック状態ならノーマル状態へと切り替えます。その時に砂嵐を表示しているRawImageの有効・無効、砂嵐の音声を設定しているAudioSourceの再生・停止を切り替えます。視界ジャック状態からノーマル状態へと移行する時はInitializeViewJackメソッドを呼び出して視界ジャック設定の初期化を行います。isViewJackがtrueの時は視界ジャック中なのでViewJackメソッドを呼び出します。ViewJackメソッドViewJackメソッドを見ていきます。{InitializeViewJack();}}方向キーの上下左右を押している時はInitializeViewJackメソッドを呼んで初期化します。Mathf.Infinity;アナログスティックの入力をXZ軸に割り当てます。closestEnemyはアナログスティックの入力方向と一番近い敵を入れます。closestEnemyRotは一番近い敵とアナログスティックの角度の差を入れます。inputDirectionRot));enemyDirectionはY軸を0に固定したキャラクターから見た敵の方向ベクトルを計算しています。enemyAngleFromFrontOfCharaは敵の方向とキャラクターの方向の角度を求めてキャラクターの視野内にいるかどうかの判定に使います。実際の角度とは別に二つの正規化されたベクトルの内積を求めると0はキャラクターの横、1は前方、-1は後方になるのでそれを使って視野内にいるかどうかも求められますが、今回はわかりやすく角度を使いました。enemyRotはワールド軸の前方からの敵のY軸の角度を求めています。inputDirectionRotはアナログスティックの入力方向のY軸の角度にキャラクター自身の向いているY軸の角度を足してワールド軸の前方からのアナログスティックの角度を計算しています。キャラクター自身の角度を足さないとアナログスティックの入力方向はキャラクターの向きにかかわらず全て同じになってしまいます。Mathf.Repeatを使って0~360度に値を補正しています(角度を0~360度未満にする為)。heroAndEnemyAngleではワールド軸前方からの敵の角度とワールド軸前方からのアナログスティックの角度を引いてMathf.Absで絶対値を計算し、Mathf.Roundで指定した値に最も近い整数を返します。heroAndEnemyAngle;}}}敵がキャラクターの視野角度内にいる敵だけを判定します。敵と入力の角度が視界ジャック範囲より大きい時はheroAndEnemyAngleを360から引いて再度代入します。これは角度が0から反時計回りに回転した時に359→358と0から数字が増えてしまうので、そういった時の為に360から引いた値にします。敵の角度が355で入力の角度が0の時は実際はheroAndEnemyAngleが5だが、計算上355になってしまうのでこれの対応です。その後、敵と入力の角度の差がlimitAngleOfViewJack(視界ジャックをする範囲)内の時でclosestEnemy(一番近い敵)が設定されていない時はその敵を登録し、敵と入力の角度の差をclosestEnemyRotに入れます。closestEnemyが登録されている時は今調べている敵と入力の角度差とclosestEnemyRotの大きさを調べで角度差が小さい方をclosestEnemyとclosestEnemyRotに設定します。{InitializeViewJack();}一番近い敵が存在した場合は砂嵐動画を再生するRawImageの透明度とAudioSourceの音量を調整します。colorやvolumeは0~1の間の数値を指定する必要があるので砂嵐の透明度と音量は最大値を1、最低値を0に変換する必要があります。今回の場合は最大値はsnowNoiseMaxValueAngleLimitで指定した値にしていて、初期値を40にしているので40の時に1にして0の時の0にする必要があります。Mathf.InverseLerpを使って比率を求めます。Mathf.InverseLerpは第1引数と第2引数の間の第3引数の割合を求めます。60f);上の場合は結果として0.6が得られます。closestEnemyの子要素のCameraコンポーネントやAudioListenerコンポーネントを取得し有効にします。逆にMainCameraのCameraとAudioListenerは無効にします。方向キーを押していない時でメインカメラが無効の状態の時はInitializeViewJackメソッドを呼び出し設定の初期化をします。InitializeViewJackメソッドInitializeViewJackメソッドを見ていきます。1f;}InitializeViewJackメソッドではメインカメラのCamera、AudioListenerコンポーネントを有効にし、currentCameraとcurrentAudioListenerが設定されていれば無効にしnullを設定します。砂嵐の設定も初期値に戻します。これで視界ジャックのスクリプトが出来ました。インスペクタでいくつか設定する必要がありますが、その前に砂嵐やメインカメラの設定、敵キャラクターの作成をしていきます。視界ジャック時に表示する砂嵐を作成していきます。表示する砂嵐動画はBlenderでアナログテレビの砂嵐動画を作成するBlenderでアナログテレビ放送の番組終了後に流れていたザーーーという砂嵐(スノーノイズ)の動画で作成していきます。20:05の記事で作成したものを使います。上の記事では動画内に音声も含ませていますが、Unity内で連続再生させると音声がループする時に途切れてしまう為、音声は別途Audacityで3秒程のザーッという音声をWAV形式で出力しUnityに取り込んでおきます。取り込んだ動画のインスペクタは取り込んだ音声のインスペクタはのように設定しました。次にヒエラルキー上で右クリック→UI→RawImageを選択します。RawImageの横と縦の幅はstretchにして画面全体に流れるようにします。Playerコンポーネントを使用する必要があります。Modeの設定で動画の出力先を設定出来ます。TextureをRawImageのテクスチャに設定することで動画を流すようにします。Textureを選択し名前をViewJackとします。ViewJackを選択しインスペクタでSizeを512に変更します。レンダーテクスチャが出来たので設定をしていきます。Playerを選択します。Imageコンポーネントの横のチェックを外します。これで砂嵐動画は最初は表示されません。ImageのTextureには先ほど作成したViewJackレンダーテクスチャを設定します。ImageのTextureに設定する事で動画を流します。Awakeにチェックを入れて自動で再生され、Loopにチェックを入れて繰り返し再生されるようにします。Textureでは実際のレンダーテクスチャファイルを指定します。OutputはNoneにして音声は出力しないようにします。Sourceを選択します。AudioClipに砂嵐用の音声クリップを設定し、Loopにチェックを入れて繰り返し再生されるようにします。AudioClipのLoopにチェックした場合は繰り返し再生しても終わりと初めの部分で途切れるという事はありませんでした。これで砂嵐の設定が終わりました。メインカメラの設定メインカメラの設定をしていきます。メインカメラはシーン作成時にあるMainCameraをそのまま使用します。ComponentからScripts→UnityStandardAssets.Utility→SmoothFollowを選択します。Targetには操作キャラクターの頭付近に空のゲームオブジェクトを作成し、名前をCameraFocusPositionとし、それをTargetに設定しました。この辺りはUnityでカメラの設定とキャラクターの追従をさせるUnityで使うカメラの設定値を変更したり、カメラがキャラクターを追従するようにするしていきます。13:16を参照してください。敵キャラクターの配置と設定をします。今回はアセットストアで無料でダウンロード出来るゾンビを敵キャラクターとして使用します。High)を選択すると上位で出てきます。インポートしたらZombie→Prefabs→Zombiをヒエラルキー上に配置します。ヒエラルキー上のZombiを選択した状態で右クリック→Cameraを選択します。Headの子要素に移動させ目の辺りに移動)。Listenerコンポーネントのチェックを外し無効化しておきます。今回は敵キャラクターは動かさないのでカメラは単にZombiの子要素に置きました。Animatorに設定されているアニメーターコントローラーは選択してDeleteキーを押し未設定の状態にしておきます。これで敵キャラクターの設定は終了です。視界ジャック機能スクリプトViewJackScriptのインスペクタの設定これで機能が全て出来たのであとはViewJackScriptのインスペクタの設定をするだけです。EnemyListには全ての敵キャラクターを登録します。ViewJackCharaには自身SnowNoiseImageObjにはRawImageMainCameraにはMainCameraMainAudioListenerにはMainCameraをドラッグ&ドロップして設定します。これで視界ジャック機能の完成です。(^^)/終わりに今回の機能で方向キーと敵の方向を比較する時の角度の計算で結構混乱しました。角度計算するにも色々なメソッドがあって、Vector3.Angle、Vector3.SignedAngle、Quaternion.Angle、Quaternion.LookRotation、Quaternion.FromToRotation等々。Unityの角度計算メソッドをわかりやすくするサンプルの作成Unityの角度計算メソッドの使い方をわかりやすくする為にシーンビューでゲームオブジェクトを動かして計算された角度を視覚的に確認出来るサンプルを作成していきます。20:28どれが一番使えるかなぁと色々試しているうちに何が何やらわからなくなりはまってしまいました。賢いやり方もあるかもしれませんが、とりあえず出来た方法で作りました。SIRENの視界ジャックがどのように作られているかはわかりませんが、似たようなものは出来たのではないかと思います。機能を近づけるならば、一番近い敵の視界ジャックをしている時に〇ボタンを押したらその敵の視界ジャックに固定するという風にすると良さそうですね。コメントをキャンセルメールアドレスが公開されることはありません。コメントデータの処理方法の詳細はこちらをご覧ください。サイト内検索が出来ますプロフィール管理人のかめくめちゃんです。(-_-)メールはこちらにお願いします(記事への質問はコメント欄にお願いいたします)。kamekumechan@gmail.comいずれはSIRENやバイオハザードみたいなアクションゲームを作りたいと思っています。ゲームシナリオが書けないので面白いゲームはなかなか作れません・・・・。(^_^;)名前の由来はカメが好きだからです。Д`)シクシク...お知らせ2020/01/18個人的にUnity2019.2.18f1をインストールしました。2020/01/01あけましておめでとうございます。(^^)/ユニティちゃんのRPGを作ってみようのPartyStatusスクリプトでpartyMembersのListの型がCharacterStatusとなっていたのでAllyStatusに変更しました。変更したというか、元々AllyStatusに書き換える前のスクリプトを掲載していたので修正しました。ユニティちゃんのRPGを作ってみよう10ーコマンド画面の作成とステータスの表示ーユニティちゃんのRPGでコマンド画面の作成とステータスコマンドを作成し、選択したキャラクターのステータスを表示するようにしていきます。20:00GetPartyStatusメソッドの戻り値もそれに伴って変更しています。2018/08/07コメント欄へのわたくしの返信は停止しております。わたくしに出来る事は既に記事にしてあるので、ブログ右上の検索窓を活用してください。(._.)またブログの最初の方の機能を積み上げていく記事に関しての疑問点は当ブログ記事のスクリプトの説明と寄せられた質問への回答Unityを使った3Dゲームの作り方(かめくめ)の機能積み上げ形式の記事のスクリプトの説明と寄せられた記事の機能についての質問への回答を掲載しています。21:41も参照してみてください。コメントの返信はありませんが、回答は記事に反映されている可能性があります。当ブログはハイスピードプランです。WordPressの編集画面の動作が早くなった。Unityを使った3Dゲームの作り方(かめくめ).。