本日はUE4勉強会でした。
講演者の方々、運営の方々、すべての参加者の皆さん、お疲れ様でした。
とても勉強になりましたし、このブログを更新する励みになりました。
というわけで、勉強会から持ち帰った知識を使って当初困ってたカメラの設定をやってみます。
このカメラの設定、結構面白いことも分かったのでその辺も交えて解説していきます。
よろしくお願いします。
UE4でカメラを設定する方法としてはMatineeを使うという方法があります。
もともとMatineeはカットシーン(演劇シーンというとわかりやすい?)を作成するのを目的として存在しています。
いわゆるキャラ劇以外にも、初めてのマップに入ってきたときに全体を見回すようにカメラを動かしたりもしますが、これもMatineeが得意とする部分です。
しかし、プレイヤーが操作可能なカメラはMatineeでは作成しづらい(というかできない?)ですし、ただの固定されたカメラであればMatineeを使うのももったいない。
そこで、シーンにカメラを置いてそれを動かしたり、必要な場所に固定したりして使おうということになるのですが、シーンにカメラを置いたらそれだけでOKということにはなりません。
そこで、Blueprintを利用して設定します。
まずはブランクプロジェクトを作成します。名前はCameraProjectとでもしましょう。
いつも通りのテーブルと椅子が表示されたら次に進みます。
この状態でゲームをプレイするとマウスとキーボードでカメラが操作できる状態になっているはずです。
このカメラを別のカメラにしたいわけです。
では、カメラをLevelに置きます。
左上のModesタブ内のPlaceタブ、Basicカテゴリ内のCameraをLevelEditorにドラッグ&ドロップします。
ドラッグ&ドロップするとLevelEditor上にカメラの形をしたオブジェクトが表示さます。
右上のScene OutlinerではCameraActor1というオブジェクトが生成されているはずです。
ドラッグ&ドロップしたときはこのCameraActor1が選択状態になっています。
そして、カメラのActorが選択状態になるとLevelEditorの右下にPicture in Picture形式でカメラから見た映像が出てきます。これは便利。
この状態でゲームをプレイしてみても最初と何も変わりません。
そこでLevelの動作が開始したところで配置したカメラで表示するようにしてみましょう。
まず、ツールバーのBlueprintsボタン -> [Open Level Print]でLevelのBPを開きます。
Levelの動作が開始したら実行されるBPなので、イベントはBeginPlayを選択します。
次に0番のPlayerControllerを取得します。EventGraphで右クリック -> [Get Player Controller]でPlayerControllerのインスタンスを取得します。
Return Valueを左クリックしてからドラッグするとPlayerControllerから使えるBP用関数を表示することができます。
ここからSet View Target with Blendという関数を選択し、BeginPlayイベントからこの関数を実行するようにします。
最後にScene OutlinerからCameraActor1をドラッグ&ドロップし、CameraActor1の出力をNew View Targetに接続します。
BPは以下のようになっているはずです。
この状態でゲームを開始するとカメラから見た映像と同じものが描画されているはずです。
ただ、デフォルトではカメラのアスペクト比が16:9になっています。
LevelEditorのアスペクト比を利用したい場合、CameraActor1のDetailsタブ、[Constrain Aspect Ratio]のチェックを外しましょう。
Set View Target with Blendというカメラ設定命令は、New View Targetに設定したActorのTransform情報をもとにカメラの姿勢を制御する命令のようです。
New View Targetに設定できるのはActorだけなのですが、ActorであればCameraActorでなくても設定が可能とも言えます。
適当なメッシュをLevelEditorに配置して、これをNew View Targetに接続します。
するとつないだActorから見た映像となります。
とはいえ、カメラActorを使った方がアスペクト比や画角を設定することもできるので有利です。
また、この設定命令は名前の通りカメラの姿勢のブレンドを行うこともできます。
Blend Timeの項目に適当な数値を入れてみるとわかると思いますが、カメラが通常のスタート位置から設定したCameraActor1まで補間されることがわかるはずです。
ゲーム中、何らかの理由でプレイヤーカメラから固定カメラに移動し、一定時間後にまた元に戻るというような目的で使用するとよいでしょう。
ちなみに、カメラのPerspective、Ortho設定は当然ながら補間されません。ブレンド終了後にこれらのパラメータは新しいカメラの情報で上書きされます。
カメラの設定方法として、カメラコンポーネントを持っているBlueprintを利用するという手もあります。
Blueprintsボタン -> [New Class Blueprints]でActorを継承したBPを作成します。名前はCameraBPとでもしておきましょう。
[Add Component] -> [Shapes] -> [Arrow]で矢印コンポーネントを作成し、その後にカメラコンポーネントを作成します。
最初からカメラコンポーネントを追加しない理由は、Rootに置かれたコンポーネントはBP内で平行移動や姿勢制御を受け付けてくれないからです。
この状態でCameraBPをLevelに配置してみましょう。配置したCameraBPを選択すると、PiPのカメラ画像がCameraBPのカメラを使って描画してくれているはずです。
CameraBPのComponents内でカメラを動かすとPiPの映像も移動するのがわかるはずです。
実際、このCameraBP ActorをNew View Targetに設定するとBP内部のカメラコンポーネントの情報で描画が行われます。
しかし、BP内には複数のカメラコンポーネントを追加することができます。複数追加された場合はどうなるでしょう?
これは、Componentsブラウザ内で最初に出てくるカメラコンポーネントの情報を利用することになります。
通常、カメラコンポーネントを2つ作成すると、Camera1、Camera2というコンポーネントが生成されます。
この場合はCamera1の方が先にきているので、そのままならCamera1が使用されます。
この状態でCamera2の子になるようにCamera1を移動させると、Camera2が用いられることになります。
では、コンポーネントが以下のようになっていたら?
この場合はやはりCamera1が用いられます。ツリーの深さは考慮されず、あくまでもツリーの上にあるものが優先されます。
New View TargetにCamera1やCamera2を直接設定すればいいのではないか?と考える方もおられるでしょう。
これは不可能です。
このようにエラーが出てしまいますが、それもそのはず、BPに追加しているカメラはカメラActorではなく、コンポーネントなのです。
ActorはC++コード内ではAActorというクラスです。カメラActorももちろんこのクラスを継承しています。
しかしカメラコンポーネントはUCameraComponentというクラスで、UActorComponentというクラスを継承しています。これはActorではありません。
カメラActorはカメラコンポーネントを持っているActorであり、コンポーネントという形ではActorを必要とする入力には接続できないのです。
というわけで今回はカメラの設定方法をやってみました。
あまり使わないと思いますが、カメラの代わりに別のActorを設定してもカメラの姿勢を変更できるというのはちょっと面白かったです。
また、BPに複数のカメラコンポーネントを追加した際の挙動も学びました。わざわざやらないことだと思いますが。
追記:
ソースコードも持ってるんだから、ということでカメラ関連の内部挙動を少し調べてみました。
PlayerControllerはPlayerCameraManagerを持っていて、カメラの処理関連は基本的にこのPlayerCameraManagerが行っています。
Engine/Source/Runtime/Engine/Classes/Camera/PlayerCameraManager.h
Engine/Source/Runtime/Engine/Private/PlayerCameraManager.cpp
これらが対応するコードです。
SetViewTargetWithBlend()メソッドはその名の通りターゲット(この言い方だと注視点っぽく感じますが、実際にはカメラとなるActorのことです)を設定するだけです。
実際にカメラを更新しているのはUpdateViewTarget()メソッドです。
ターゲットがカメラActorであればそのままカメラコンポーネントの情報を取得して利用します。
そうでない場合はまずCameraStyleというパラメータをチェックします。
CameraStyleはFixed, ThirdPerson, FreeCam, FreeCam_Default, FirstPersonという5つのスタイルについては特殊な処理がされています。
そうでない場合、AActor::CalcCamera()メソッドを利用してカメラコンポーネントの情報を取得します。
この命令は自身が持っているコンポーネントからカメラコンポーネントを検索し、最初に見つかったカメラコンポーネントから情報を取得するだけです。
ツリーの上にあるコンポーネントが優先して利用される、というのも頷ける内容ですね。
CameraStyleはPlayerController::SetCameraMode()で設定できるようですが、Blueprintでこの辺りを設定したりする命令を見つけることができませんでしたね。
何か方法があるのかもしれませんが、どなたか教えてもらえませんかね?