‫ねえ｡
‫お帰りなさい｡
‫これで､ カーソルの下にヒットした結果を取得する必要があることがわかった｡
‫このビデオでは､ その仕組みと意味についてもう少し詳しくお話しします｡
‫そこで､ ヒット結果をカーソルの下に表示し､ この場所を表示することが目的ですが､ そのためにはデバッグ用の球を描けばいいのです｡
‫その方法も学んでいきます｡
‫そこで､ ヒット・リザルトと呼ばれるものについて説明します｡
‫ゲームでは､ こんなことをしたくなることが多いでしょう｡
‫宇宙に一点突破
‫この点をstartと呼び､ 型はF vector､ 終了位置はendとする｡
‫これもFベクトル型の空間上の点となる｡
‫では､ 始点から終点まで見えない線を引きたいとします｡
‫そして､ この線を引いた瞬間に､ 始点と終点の間に何かオブジェクトがあるかどうかを確認したいのです｡
‫さて､ もしあれば､ 空間に描いているこの線は､ そのオブジェクトにぶつかることになります｡
‫表面上､ このようなことが起こると､ 私たちはこれをヒットイベントと呼んでいます｡
‫さて､ このように見えない線を描くことを､ ライントレースを行うということです｡
‫そして､ 何かにぶつかると､ トレースヒットと言うのです｡
‫さて､ 実際に何かを叩いてヒットイベントが発生した場合､ トレースヒットはヒット結果と呼ばれる構造体に情報を格納します｡
‫タイプはFヒット結果です｡
‫さて､ F hit results structには､ ヒットしたイベントの情報を格納する変数があり､
‫空間のfベクトルとしてのヒット位置や､ ヒットしたアクターなどの情報が格納されています｡
‫さて､ ライントレースを行う際には､ コリジョンチャンネルを指定して行います｡
‫通常､ ライントレースでは､ 可視性というチャンネルを選択します｡
‫E Collision Channelというenumが存在し､ このenumの中にXY visibilityというenum定数が存在します｡
‫ライントレースを行う際に指定するパラメータの一つです｡
‫さて､ 可視チャンネルを指定すると､ コリジョン設定で可視チャンネルをブロックするように設定されているオブジェクトは､
‫ヒットイベントを登録することになります｡
‫可視チャネルをブロックするように設定されていないオブジェクトは､ ヒットイベントを発生させません｡
‫今度は､ カーソルの下にトレース結果を表示させたい｡
‫ここにスクリーンがあり､ ここにカーソルがあると想像してください｡
‫カーソルの先端には､ カーソルの下にヒットした結果を得るための関数を使用したときの画面上のポイントがあるのです｡
‫カメラには､ この床のようなものが映ります｡
‫そして､ カーソルの位置に対応する画面上のポイントでカメラからライントレースを行い､ そのライントレースをまっすぐ世界へ向けて撮影しているのです｡
‫また､ 何かにぶつかったら､ ヒットイベントを生成して､ その情報をヒット結果構造体に格納します｡
‫では､ どうすればいいのか､ 考えてみましょう｡
‫戦車CPに来て､ やりたいことは毎フレームカーソルの下にヒット結果を取得すること､ つまりtick関数が必要なんです｡
‫そこで､ もう一度､ ベースアポンに戻り､ ここでティック関数を見つけることにします｡
‫さて､ この関数はベースポーンでは何も使っていないので､ Begin Playと同じようにタンククラスに移動させることができます｡
‫そこで､ 関数宣言とそのコメントをハイライトしてコピーしてみることにする｡
‫そして､ このセクションをpublicも含めて全部削除してから､ Tank Hに戻って､ ここのpublicセクションにtick関数の宣言を貼り付けようと思います｡
‫さて､ ベースポーンでは使わないので､ ベースポーンからtick関数を削除します｡
‫CP 今はベースポーンから消えている｡
‫さて､ ここでインテントを宣言しましたが､ タンクで関数も定義する必要があります｡
‫CP ここは戦車DHCPで､ setup player input componentのすぐ下にあります｡
‫だから､ ボイドティックと言うことになる｡
‫デルタタイムと呼ばれるフロートを取ります｡
‫そして､ 私たちの体です｡
‫さて､ ここでもtick関数の直前に､ スコープ解決演算子と一緒にtankが必要です｡
‫そして､ スーパーティックも呼び出して､ デルタタイムを渡す必要があります｡
‫ということで､ タンククラスのティックができました｡
‫やりたいことは､ ヒットした結果をカーソルの下に表示させることです｡
‫そこで､ その方法を紹介します｡
‫今回使用する関数は､ プレイヤーコントローラ上に存在する「get hit result under cursor」という関数です｡
‫という話をしたことがあります｡
‫さて､ ここからが構文です｡
‫トレースチャンネルがかかる｡
‫トレースチャンネルを指定する必要があり､ visibilityを使用することを忘れないでください｡
‫これで､ 2つの入力パラメータが追加されました｡
‫1つ目は､ Bトレースコンプレックスと呼ばれるboolです｡
‫それが何を意味するのかについては､ 後ほどお話しします｡
‫そして､ 3つ目の入力パラメータはFヒット結果である｡
‫ここで､ このタイプをドキュメントで確認するために､ F hit resultをクリックしてみます｡
‫そして､ 下にスクロールすると､ 変数の一部が見えてきます｡
‫そのうちの1つはアクターと呼ばれるもので､ 説明には「Actor Hit by the Trace」と書かれています｡
‫また､ このBブロッキングヒットというのは､ このヒットがブロッキングによる衝突の結果かどうかを示しています｡
‫さて､ その他の変数のうち､ インパクトポイントというものがあります｡
‫これは､ 宇宙空間で実際に何かにぶつかったときの位置です｡
‫では､ さっそくこの関数を呼び出してみましょう｡
‫私達は最初に私達のプレーヤー､ コントローラーを望み､ 私達がここにしたおよび演劇を始めることのおかげで､ 私達はプレーヤー､ コントローラー､
‫refを持っている｡
‫さて､ 最初にやるべきことは､ プレイヤー・コントローラーの参照番号が有効かどうかを確認することです｡
‫if文の中にポインタを渡すことはいつでもできる｡
‫ポインタ自体がヌルポインタでない場合は真を返します｡
‫もし､ NULLポインターであれば､ if文の中でfalseを返してしまい､ if文の中まで到達することはできない｡
‫ポインタを使用する前に､ ポインタがNULLでないことを確認することは､ 常に良いアイデアです｡
‫プレーヤーとコントローラーの参照を取得し､ 矢印演算子を使って関数を呼び出し､
‫カーソルの下にヒット結果を取得します｡
‫これで､ 3つの入力パラメータがあることがポップアップで確認できるようになりました｡
‫1つ目は､ 「トレースチャンネル」です｡
‫EA Collision Channelを使用し､ コロン2つをタイプすると､ EA Collision Channel列挙型の異なる列挙型定数をすべて表示するドロップダウンが表示されるのです｡
‫可視性を使用したいので､ XY visibilityと入力して､ 可視性チャンネルを使用することを指定します｡
‫次のパラメータはBトレースコンプレックスと呼ばれるもので､ これにfalseを渡すことにします｡
‫さて､ これが何を意味するのかについては､ 後ほど説明します｡
‫しかし､ 今はfalseを使うことにします｡
‫さて､ 3つ目のパラメータは､ ヒットした結果が必要です｡
‫これはタイプ F のヒット結果の構造体である｡
‫さて､ この上にカーソルを置くと､ Fのヒット結果が参照として渡されていることがわかります｡ これは､
‫アンパサンドのような参照演算子で示されています｡
‫さて､ 通常､ 何かを参照として渡すとき､ それはコスト参照であり､ つまり､ 関数はそれを変更することができません｡
‫しかし､ ここでは､ Fヒットの結果をnon constリファレンスとして渡している｡
‫これは一般に､ その関数がこの入力パラメータを直接変更するように設計されていることを示唆するものである｡
‫カーソルの下のヒット結果を取得するのは､ ヒット結果内のこれらの変数に､ ヒット結果に関する情報を記入することです｡
‫つまり､ このfヒットの結果を1つだけ渡す必要があるのです｡
‫ここでは､ F hit resultという型のifチェックでローカル変数を作成することにします｡
‫そして､ このヒット結果を呼び出すと､ 3番目の入力パラメータとしてこのNを渡すだけでよいのです｡
‫さて､ この関数を呼び出した後､ このヒット結果には､ このライントレースに関するデータが記入されることになります｡
‫例えば､ ヒット結果のドットアクターにアクセスしてヒットしたアクターを取得したり､ ドットインパクトポイントにアクセスしてヒットイベントが発生した空間上のポイントを取得したりすることができます｡
‫そこで､ ライントレースの情報を得るために利用するのが､ ヒット結果である｡
‫今はよく､ ライントレースの結果を見ることができるのがうれしいですね｡
‫デバッグ球を描くことで､ ライントレースの結果を簡単に視覚化することができます｡
‫デバッグ球は空間に描くシンプルな図形で､ 位置を示すのに適しており､ デバッグの際にはこれを使用します｡
‫実際にシフトゲームでデバッグスフィアを使うことはないんですよ｡
‫では､ このデバッグ用の球体をどのように描画するか見てみましょう｡
‫さて､ ここにdraw debug sphereという関数のドキュメントがあります｡
‫ドローデバッグヘルパーに存在する｡
‫このヘッダーをコピーして､ ドローデバッグスフィアを呼び出したい場所にインクルードすればいいわけです｡
‫ここで､ すべての入力パラメータを見てみましょう｡
‫まず､ どの世界に球体を描けばいいのかがわかるように､ 世界を取り込む｡
‫球の中心を表すFベクトルと､ 半径を表すfloatを受け取ります｡
‫その球の分割数をN 32とする｡
‫セグメント数が多いほど､ 丸い球体でF色をとります｡
‫こうすることで､ この球体をどの色で描画すればよいかがわかるのです｡
‫持続的な回線が必要かどうかを知りたがっているのです｡
‫つまり､ 線はすぐに消えるべきなのか､ それとも持続させるべきなのか｡
‫もし､ それが持続するのであれば､ 球の寿命を知りたいと思う｡
‫球体の描画を停止するタイミングは？
‫もし､ 永続的な線を描かない､ 例えば1フレームだけ描きたいのであれば､ ライフタイムとしてマイナスのものを渡すことになります｡
‫さて､ 最後の2つのパラメータはオプションなので､ 最初の7つのパラメータだけを取り上げて簡単に説明します｡
‫その様子をご覧ください｡
‫デバッグ用の球体を描画します｡
‫そこで､ このドローデバッグ球関数が宣言されているのです｡
‫では､ プレイを開始して､ デバッグ用の球体を描いて､ その動きを見てみましょう｡
‫そこで､ ドローデバッグ球を呼び出し､ その
‫最初の入力パラメータは新しい世界です｡
‫Get Worldを呼び出すことで､ いつでも自分の世界を得ることができます｡ Get Worldは､ 現在の世界に対する新しい世界ポインタを返します｡
‫これで最初の入力を満たすことになるわけです｡
‫次に､ 球の中心を表すfベクトルが必要である｡
‫今､ これを呼び出して再生を開始しているので､ 単純にget actor locationを呼び出すと､ 水槽の池の位置が取得できます｡
‫戦車クラスなので｡
‫今度は球体を少し上にあげます｡
‫そこで､ Fベクトルを追加して､ Xは0ドットF､ Yは0ドットF､ Zは200Fとします｡
‫では､ これらの入力パラメータをそれぞれ独立した行に配置してみます｡
‫だから､ 各入力に対して何を渡しているのかが明確なのです｡
‫2番目の入力は､ アクターの位置と､ 長さ200の上向きのベクトルを加えたこの式を取得しています｡
‫この2つのベクトルを足すと､ Z軸方向に200単位分上がった戦車の位置が分かります｡
‫次の入力パラメータは､ 球体の半径です｡
‫半径100のデバッグ球がどのようなものかを見るために､ 100Fを選択することにします｡
‫次にセグメント数です｡
‫私は12を選びます｡
‫それがどのようなものであるかは､ これからです｡
‫さて､ Fカラーですが､ Fカラークラスというのがあって､ 赤などたくさんの色が組み込まれています｡
‫では､ B persistent linesというブーリアンには､ trueを選んでおきます｡
‫そして､ 次の入力パラメーターには､ ライフタイムノーティスがあります｡
‫初期値はマイナス1です｡
‫つまり､ デフォルトでは1フレームだけデバッグ球を描画します｡
‫しかし､ 30秒間の球を得るために30Fを渡すので､ 最後の2つのパラメータは省略できる｡
‫では､ デバッグ球を描画するための関数コールを以下に示します｡
‫これをコンパイルして見てみましょう｡
‫さて､ そんなわけで編集部に戻ってきました｡
‫2つ目のウィンドウを開いて､ フルスクリーンで見ることができるようにします｡
‫ウィンドウビューポートでビューポート2を選択すると､ この2つ目のウィンドウが表示されるようになりました｡
‫開いたときにフルスクリーンでない場合もありますが､ いつでも最大化することができます｡
‫ここから先はalt pでゲームをプレイすることができます｡
‫では､ これをご覧ください｡
‫これがデバッグスフィアです｡
‫完全な円形ではないことに注意してください｡
‫セグメント数は12を選びました｡
‫セグメントを多く選択すると､ 球体を描くのに必要な線が多くなります｡
‫さて､ これは半径が100の球体です｡
‫かなり大きく､ 球の中心は戦車の位置で､ さらに上空に200台｡
‫つまり､ このようにデバッグ用の球体を描画することができるのです｡
‫そこで､ カーソルの下にあるトレース結果を利用して､ デバッグ用の球体を描くことが課題です｡
‫そこで､ 新しい if 文でデバッグ用の球を描き､ player controller ref が null でないことをチェックします｡
‫次に､ ヒットした結果からインパクトポイントを取得し､ それを球体の中心とします｡
‫ここで､ persistent linesの入力パラメータにはfalseを､ durationには負の値を使用します｡
‫そして､ これは1フレーム分の球体の描画になります｡ これは､ tic関数内で毎フレームこれを呼び出しているので､
‫問題ありません｡
‫そこで､ 動画を一時停止し､ tick関数でデバッグ球を描画します｡
‫なるほど｡
‫だから､ 私はここタンクに帰ってきたのです｡
‫このdraw debug sphere関数の呼び出しをbegin playにコピーして､
‫begin playから削除して､ if文の中のtickに戻り､ ここにペーストして､
‫入力パラメータをいくつか変更します｡
‫ひとつは､ 球体の中心の位置を変えていることです｡
‫ヒットした結果を利用するのです｡
‫だから､ ヒット・リザルト・ドット・インパクト・ポイントと言うことになるんです｡
‫さて､ 半径ですが､ これはもう少し小さくしたいですね｡
‫25くらいにしよう｡
‫それでいいんです｡
‫そうでなかったら､ こうしているだけです｡
‫だから､ 球体はそれほど大きくないんです｡
‫さて､ 最後から2番目のパラメータは､ パーシステントラインのために渡すものです｡
‫falseで通して､ 持続時間は30秒ではなく､ マイナス1ポイントのFを使うつもりです｡
‫この方法では､ 1フレーム分の球体を得ることができます｡ 繰り返しますが､ tick関数の中でこれを呼び出しているので､ 毎フレームこれを呼び出すことになりますが､
‫これは大丈夫です｡
‫では､ これをコンパイルしてみましょう｡
‫さて､ エディタに戻ると｡
‫今､ 再生ボタンを押したら､ これを見てください｡
‫デバッグ球があるのですが､ カーソル下のライントレースのインパクトポイントに描画されています｡
‫次に､ これを壁の上や他のオブジェクトに移動させると､ トレースはこれらのオブジェクトに当たります｡ なぜなら､ これらのオブジェクトは可視性チャンネルをブロックするように設定されているからです｡
‫今､ かなりすごい｡
‫複雑なトレースと単純なトレースについて説明すると約束しました｡
‫ゲームをしながら､ あるものを見せます｡
‫手のひらをコントロールできるように､ ビューポートでクリックしてみましょう｡
‫ここでチルダキーを押しながら､ コンソールコマンドのshow collisionを入力します｡
‫今､ 私の画面ではわかりにくいかもしれませんが､ あなたの画面では確実に見ることができます｡
‫ポーンの衝突に注目してください｡
‫カプセルだけでなく､ 戦車と砲塔のメッシュの周りにあるこの衝突ボリュームも見ることができます｡
‫これは単純な衝突です｡
‫単純なコリジョンを見ることができる場所を簡単に紹介しましょう｡
‫アセットとメッシュに入り､ 例えばここでタンクベースをダブルクリックすると､ 複雑なコリジョンが表示されますね｡
‫この上部の表示アイコンをクリックして､ 複雑な衝突を選択すると､ 複雑な衝突に含まれるすべてのポリゴンが表示され､
‫たくさんのポリゴンが表示されます｡
‫もう一度表示アイコンをクリックし､ 今度はSimple Collisionの隣にあるチェックボックスをチェックすると､ 別のコリジョンボリュームがあることに気づきます｡
‫これはコリジョンハルと呼ばれ､ ジオメトリが非常に少なくなっています｡
‫このコリジョンボリュームを持つポリゴンの数は少なくなります｡
‫これは､ 物理エンジンがヒットイベントの重なりを検出するために使用するものです｡
‫もし､ 複雑な衝突を利用するのであれば､ もっと膨大な計算が必要になります｡
‫そのため､ 単純なコリジョンボリュームを用意して､ 複雑なコリジョンではなく単純なコリジョンでトレースしたほうが､
‫ライントレース時のパフォーマンスが向上します｡
‫これで､ カーソルの下にヒットした結果が出たわけです｡
‫そこに至るまでには多少の苦労がありましたが､ 今では手に入れ､ この場所をデバッグ球で表示することで証明しています｡
‫これは､ トレースヒットが機能していることを確認するための良い方法です｡
‫さて､ これで動作が確認できたので､ その場所を使って戦車の砲塔を回転させます｡
‫そして､ それは次のビデオで行います｡
‫また､ お会いしましょう｡