‫こんにちは､ お帰りなさい｡
‫これで...は動きますが､ 砲塔と呼んでいる上部のパーツは回転させません｡
‫だから､ マウスを使ってできるようにしたいんです｡
‫さて､ ここで何が起こっているのか見てみましょう｡
‫ワールド内でマウスカーソルを動かしていると､ このような赤い球体が出てきます｡
‫これは､ 3D空間に描いているデバッグ用の球体です｡
‫ここで､ 私が壁に向かって移動すると､ その球体は壁の表面に対して移動することに気づきます｡
‫だから､ マウスカーソルが動いている場所には､ カーソルの位置に基づいてヒットしているオブジェクトに対応する恐怖を感じることができるんだ｡
‫これは､ タレットを回転させる場所を空間内に設定するのに便利です｡
‫さて､ これを行うには､ コントローラ上で必要な関数がいくつかあるので､ コントローラ上でそれらの関数にアクセスする必要があります｡
‫このビデオでは､ その設定と､ キャスティングと呼ばれる概念をどのように使用するかについて説明します｡
‫さて､ なぜコントローラが必要かというと､ コントローラにはカーソルの下にヒット結果を取得するための関数があるからです｡
‫今度はマウスカーソルの話です｡
‫例えば､ これが画面､ これがマウスカーソルです｡
‫そして､ カーソルの先端にある点が､ 画面上のある場所に対応しています｡
‫カーソルを移動させると､ 戦車の砲塔部分､ つまりメッシュの上部が回転し､
‫カーソルの方向を向くようにすることが目的です｡
‫カーソルを移動させると､ そのカーソルに対応する位置を取得するための関数がコントローラに用意されています｡
‫カメラからカーソルに向かって直線を引き､ ワールド内の何らかのオブジェクトにぶつければ､
‫その位置を取得し､ その位置を使って戦車の砲塔の回転を設定することができます｡
‫どういうことか､ お見せしましょう｡
‫さて､ このカーソルに対応するヒット位置を取得するために､ コントローラを使用する必要があります｡
‫さて､ ここでちょっとだけコントローラーの話を｡
‫私たちのポーンがあるとしましょう｡
‫ポーンはコントローラーを持つことになります｡
‫これはポーンに関連する目に見えないオブジェクトです｡
‫さて､ ポーンですが､ コントローラはタイプAのプレイヤーコントローラを持ち､ ゲーム開始時にはコントローラがポーンを所持することになります｡
‫そのため､ ポーンタンクが持っているカメラの視点で見ることができるのです｡
‫これで､ このコントローラにアクセスできるようになりました｡
‫戦車クラスはGet Controllerという関数を継承しています｡
‫これは -- クラスから継承されています｡
‫そこで､ このコントローラを取得し､ 変数に格納して､ カーソル下のヒット結果を得るために必要な関数にアクセスできるようにしたいのです｡
‫だから､ そのための準備をしよう｡
‫今､ 私はこのタンククラスにいて､ コントローラにアクセスする必要があるのはplayを始めるところです｡
‫もし､ コンストラクタで実行すると､ 早すぎて､ まだ有効なコントローラができていない可能性があります｡
‫そこで､ このタンククラスでbegin play関数が必要になります｡
‫このクラスは pong クラスのベースになっていますが､ 今のところ pong クラスのベースでは begin play は使っていません｡
‫そこで､ 私がやりたいのは､ それをタンククラスに移すことです｡
‫そこで､ ここのコメントとプロテクトされた部分を含めてビギンプレイを強調し､ シンプルにカットすることにしました｡
‫そして､ タンクステージに戻り､ 貼り付けます｡
‫プライベートセクションのすぐ上に､ このプロテクトセクションを追加し､ 中でプレイを開始するようにしましょう｡
‫これで､ ベースポーンからBegin Playを取り除きました｡
‫もうここにはありませんが､ base pond cpp からも削除する必要があります｡
‫これです｡
‫ここで削除して､ タンクHで宣言したことになりますが､ タンクCPPでも定義する必要があります｡
‫そこで､ プレーヤー入力コンポーネントのセットアップの直下に関数を定義することにします｡
‫つまり､ 入力パラメータがないボイドビギンプレイになるわけです｡
‫関数本体があり､ 関数名を固定するタンクプリも必要です｡
‫これで､ スーパービッグ・イン・プレーを呼び出すことが重要であることがわかった｡
‫そうすれば､ begin play関数や親クラスにある機能はすべて呼び出されたままになります｡
‫そこで､ プレイを開始します｡
‫ここでコントローラを取得し､ 変数に格納することができます｡
‫では､ Hタンクに戻り､ 変数を作ってみましょう｡
‫これはプライベートセクションの一番下に貼り付けて､
‫プレーヤーコントローラーのポインタータイプにします｡
‫これがプレーヤーコントローラーへの参照となります｡
‫今は､ C++のリファレンスの話ではない｡
‫これはまだ単なるポインターですが､ これをプレーヤーのコントローラーを参照するために使用します｡
‫これで､ タイプA player controllerのref変数ができ､ このポインタにコントローラを格納する準備ができました｡
‫では､ ここでTank Dot CPに戻ってプレイを開始し､ このようなことを試みてみましょう｡
‫だから
‫これから行うのは､ プレーヤー､ コントローラー､ レフイコールと言い､ コントローラーの取得を呼び出そうとするものです｡
‫さて､ コントローラの取得ですが､ 先ほど述べたように -- クラスにあります｡
‫右クリックで定義に進み､ この関数がAコントローラを返すことに注目しましょう｡
‫今､ 私たちの変数のタイプはA player controllerであり､ controllerではありません｡
‫つまり､ コントローラポインタ型のget controllerの戻り値を､ Aプレーヤーのコントローラポインタに格納しようとしているのです｡
‫ここで､ 赤い四角い線が見えることに注意してください｡
‫型の値と書いてある｡
‫コントローラポインタは､ タイプのエンティティに割り当てることはできません｡
‫プレイヤーコントローラー｡
‫エラーが発生しました｡
‫ここでは､ コントローラのドキュメントを見てみましょう｡
‫見てみてください｡
‫これがコントローラーです｡
‫そして､ 継承､ 階層と書かれています｡
‫そして､ コントローラーの下には､ コントローラーとプレイヤーコントローラーが見えます｡
‫つまり､ プレイヤーコントローラはコントローラの子クラスということになります｡
‫さて､ C++では､ 型のポインタを持つことはできない｡
‫プレーヤーコントローラーは､ Aコントローラーのアドレスの値を格納します｡
‫コントローラは親タイプです｡
‫プレーヤーコントローラーは子型です｡
‫親型のオブジェクトを子型のポインタに格納することはできません｡
‫では､ どうすればいいのか｡
‫そこで､ 私たちの問題です｡
‫Get controller関数は､ Aコントローラのアドレスを返します｡
‫さて､ これはAコントローラポインタに格納できるものですが､ Aプレイヤーコントローラポインタに格納することはできません｡
‫しかし､ 面白いことに､ get controllerで返されるオブジェクトは､ 実際にはプレイヤーコントローラなのです｡
‫つまり､ このアドレスはAコントローラポインタの形で持っていて､ それがプレーヤーコントローラを格納していることは分かっているのですが､
‫Aコントローラの形で持っていると､ 必要な関数がプレーヤーコントローラ上に存在するため､ アクセスできないのです｡
‫この関数は､ カーソル下のヒット結果を取得するために呼び出されます｡
‫ここで､ タイプAのコントローラポインタの値を持っていて､ プレイヤーコントローラ上に存在するその関数を取得しようとすると､
‫失敗することになります｡
‫コンパイルエラーが出ます｡
‫つまり､ オブジェクト自体がプレイヤーコントローラであることが分かっているので､ Aコントローラポインタに格納されているだけなのです｡
‫この問題をどう回避するか｡
‫答えは､ キャストしなければならない｡
‫コントローラが親クラスで､ プレイヤーコントローラが子クラスであることは分かっています｡
‫そして､ AプレーヤーのコントローラーポインターにAコントローラーを格納させることができないことも分かっています｡
‫逆に､ プレイヤーコントローラーのオブジェクトであるAコントローラーのポインターストアを持つことができることも分かっています｡
‫実際､ get controllerを呼び出すと､ Aプレーヤーのコントローラを指すAコントローラポインタが返されます｡
‫そこで､ A型コントローラポインタの値があれば､ キャストと呼ばれる特殊な関数を使って､ ポインタの型をA型プレイヤーコントローラポインタに変換することができるのです｡
‫つまり､ キャストは､ オブジェクト自体がキャスト先の型である限り､ あるポインタの型を別のポインタの型に変更するのです｡
‫ここで､ 無効な型にキャストしようとすると､ 例えば､ Aコントローラポインタがプレイヤーコントローラオブジェクトを指しているとします｡
‫例えば文字にキャストしようとすると､ キャスト関数はnullを返すので､ キャストに失敗したと言うことになります｡
‫つまり､ キャスト機能は次のようなものだ｡
‫これは､ デフォルトのサブオブジェクトを作成するのと同じように､ テンプレートです｡
‫このテンプレート関数は､ 選択された型に適応し､ この関数では､ 渡す型がキャストする型でもあります｡
‫だから､ その型を渡すのです｡
‫角括弧の中に2つキャストしたいので､ キャストしたいポインタを括弧の中に渡します｡
‫以下はその一例です｡
‫例えば､ プレイヤーコントローラとA型コントローラ型のポインタにキャストしたいとします｡
‫ポインタを括弧で囲み､ キャストする型を角括弧で囲んで渡します｡
‫そして､ 返されるのは､ Aプレイヤー・コントローラー・ポインター型の値です｡
‫この関数呼び出しでは､ 角括弧の中に型を渡し､ 括弧の中にはコントローラを取得した際に返されるコントローラポインタの値を渡します｡
‫そこで､ getコントローラから返されるこの値をキャストする必要があります｡
‫それがあなたのチャレンジになります｡
‫そこでBegin Playでは､ get controller関数を使って､ その値をcast関数に渡し､ プレイヤーコントローラにキャストします｡
‫そして､ その結果をプレイヤーコントローラ参照ポインタ（タイプAプレイヤーコントローラポインタ）に格納することができます｡
‫映像を一時停止して､ キャストを実行する｡
‫なるほど｡
‫これでほぼ全ての作業が完了しましたので､ あとはキャスティングするだけです｡
‫そこで､ これから行うのは､ 括弧だけでなく､ 山括弧もあるキャスト関数を呼び出すことです｡
‫そして､ 括弧の中に入っているのが､ キャストしたい値です｡
‫ここで, get controllerはType Aのコントローラへのポインタを返します．
‫それをここの括弧の中に移動させるんです｡
‫そして､ 今回キャストするタイプは､ プレーヤーコントローラーです｡
‫ですから､ ここでも会計監査人から返された値を採用しています｡
‫comptroller ポインタまたはアドレスを返す｡
‫そして､ castを使ってAプレイヤーのコントローラーにキャストしています｡
‫gate controllerが返すオブジェクトは､ A controller pointerに格納されたA player controllerオブジェクトであることが分かっています｡
‫つまり､ これをキャストした後に返されるのは､ タイプAのプレイヤー・コントローラーのポインターです｡
‫そこで､ プレイヤーコントローラーのrefに格納することにしました｡
‫Aプレイヤーのコントローラポインタという形でコントローラにアクセスできるようになったので､ カーソル下のトレースヒット結果を取得するために必要な関数にアクセスできるようになりました｡
‫つまり､ 要約すると､ get controllerを使って､ コントローラにアクセスすることができたということです｡
‫また､ A型コントローラポインタからA型プレイヤーコントローラポインタへのキャストは､ キャスト関数を使用しています｡
‫これで､ A player controller クラスに存在するカーソルの下のヒット結果を取得する関数にアクセスできるようになりました｡
‫というわけで､ 次回の動画からこの機能を使っていきます｡
‫また､ お会いしましょう｡