このチュートリアルでは、カメラのアクティベート方法、またあるカメラから別のカメラへアクティブなカメラを切り替える方法を紹介します。
1 - ワールドにカメラを配置する
Unreal Engine を初めて使用する場合は「プログラミング クイックスタート チュートリアル」から始めることをお勧めします。このドキュメントでは、Unreal Engine でのプロジェクトの作成、プロジェクトへの C++ コードの追加、コードのコンパイル、アクタ への コンポーネント の追加に慣れている方を対象として想定しています。
まず「HowTo_AutoCamera」という名前のスターター コンテンツを使用して、新規 Basic Code プロジェクトを作成します。最初にワールドにカメラを 2 つ作成します。さまざまなカメラの設定方法がありますが、ここでは最も一般的な 2 つの方法を紹介します。最初のカメラでは プレースメントブラウザ の [Place Actors] パネルへ移動して [All Classes] タブを選択するか Shift + 1 を押します。[All Classes (すべてのクラス)] セクションに Camera アクタが表示されます。このアクタを レベルエディタ へドラッグして、シーンを良く見渡すことができる位置に置きます。
この操作により、 Camera アクタ を選択している間は、新規作成した Camera アクタ から見えるピクチャイン ピクチャビューが レベルエディタ ウィンドウに表示されます。
2 つ目のカメラは、さらに詳細で正確に制御する方法を使用します。プレースメントブラウザ の [Place Actors] パネルで [Basic (基本)] タブをクリックして キューブ を [レベルエディタ] ウィンドウへドラッグします。
このステップではほぼすべてのアクタ クラスを使用できます。QuickStart チュートリアルで作成した MyActor クラスを Cube の代わりに使用すると面白いかもしれません。
Cube アクタを配置する場合、Camera コンポーネント を追加します。これは、 Cube の [Details] パネルで + Add Component (コンポーネント追加) ボタンをクリックして行います。先に配置した Camera アクタ と異なるビューになるように、この Camera コンポーネント の位置と回転を設定します。
Constrain Aspect Ratio をオンにして Camera アクタ の設定と一致するように Camera コンポーネント をカスタマイズします。この設定によりカメラビュー間の遷移がスムーズになりますが、必須ではありません。
ワールドを設定したので、カメラビューを制御するクラスの作成準備が整いました。
2 - C++ コードでのカメラビューを制御する
カメラビューを制御する C++ クラスの作成準備が整いました。このチュートリアルでは、アクタ を CameraDirector という新規クラスに拡張します。
「 CameraDirector.h 」ファイル内の ACameraDirector クラス定義の下部に次のコードを追加します。
UPROPERTY(EditAnywhere) AActor* CameraOne; UPROPERTY(EditAnywhere) AActor* CameraTwo; float TimeToNextCameraChange;
UPROPERTY マクロは Unreal Engine に変数を公開します。これによりこれらの変数に設定された値は、今後のセッションでゲームを起動したり、レベルやプロジェクトをリロードした時にリセットされないようになります。Unreal Editor に CameraOne と CameraTwo の設定を有効にする EditAnywhere キーワードも追加されました。
"CameraDirector.cpp" ファイル上部の "#include" のすぐ下に以下のコード行を追加します。
#include "Kismet/GameplayStatics.h"
「GameplayStatics」ヘッダファイルで、いくつかの汎用関数にアクセスすることができます。その中にこのチュートリアルに必要な関数があります。終了後、以下のコードを ACameraDirector::Tick の下部に追加します。
const float TimeBetweenCameraChanges = 2.0f; const float SmoothBlendTime = 0.75f; TimeToNextCameraChange -= DeltaTime; if (TimeToNextCameraChange <= 0.0f) { TimeToNextCameraChange += TimeBetweenCameraChanges; // ローカル プレイヤーの制御を扱うアクタを見つける。 APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0); if (OurPlayerController) { if ((OurPlayerController->GetViewTarget() != CameraOne) && (CameraOne != nullptr)) { // カメラ1に瞬時に切り替わる。 OurPlayerController->SetViewTarget(CameraOne); } else if ((OurPlayerController->GetViewTarget() != CameraTwo) && (CameraTwo != nullptr)) { // カメラ2へスムーズにブレンドする。 OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime); } } }
このコードは 3 秒ごとに 2 つのカメラ間でデフォルト プレイヤーのビューを切り替えます。
コードのコンパイル準備ができたので、エディタ に戻って [Compile (コンパイル)] ボタンを押します。
追加のコードは不要です。これで CameraDirector をワールドに設定することができます。
完成コード
CameraDirector.h
// Copyright 1998-2017 Epic Games, Inc.All Rights Reserved.
#pragma once
#include "GameFramework/Actor.h"
#include "CameraDirector.generated.h"
UCLASS()
class HOWTO_AUTOCAMERA_API ACameraDirector : public AActor
{
GENERATED_BODY()
public:
// このアクターのプロパティのデフォルト値を設定します
ACameraDirector();
protected:
// ゲーム開始時またはスポーン時に呼び出されます
virtual void BeginPlay() override;
public:
// フレーム毎に呼び出される
virtual void Tick( float DeltaSeconds ) override;
UPROPERTY(EditAnywhere)
AActor* CameraOne;
UPROPERTY(EditAnywhere)
AActor* CameraTwo;
float TimeToNextCameraChange;
};
CameraDirector.cpp
// Copyright 1998-2017 Epic Games, Inc.All Rights Reserved.
#include "HowTo_AutoCamera.h"
#include "CameraDirector.h"
#include "Kismet/GameplayStatics.h"
// デフォルト値を設定する
ACameraDirector::ACameraDirector()
{
// フレームごとにTick()を呼び出すようにこのアクタを設定する。 必要ない場合は、これをオフにしてパフォーマンスを向上させることができる。
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ACameraDirector::BeginPlay()
{
Super::BeginPlay();
}
// フレーム毎に呼び出される
void ACameraDirector::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
const float TimeBetweenCameraChanges = 2.0f;
const float SmoothBlendTime = 0.75f;
TimeToNextCameraChange -= DeltaTime;
if (TimeToNextCameraChange <= 0.0f)
{
TimeToNextCameraChange += TimeBetweenCameraChanges;
//ローカル プレイヤーの制御を扱うアクタを見つける。
APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
if (OurPlayerController)
{
if ((OurPlayerController->GetViewTarget() != CameraOne) && (CameraOne != nullptr))
{
//カメラ1に瞬時に切り替わる。
OurPlayerController->SetViewTarget(CameraOne);
}
else if ((OurPlayerController->GetViewTarget() != CameraTwo) && (CameraTwo != nullptr))
{
//カメラ2に滑らかにブレンドする。
OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);
}
}
}
}
3 - ワールドに Camera Director を配置する
コードのコンパイルが終了すると、新規クラスのインスタンスを コンテンツ ブラウザ から レベル エディタ へドラッグできます。
次に CameraOne 変数と CameraTwo 変数を設定する必要があります。ワールド アウトライナー で CameraDirector を検索して [Details (詳細)] パネルで編集します。
ドロップダウンから [None (なし)] をクリックして、これらの変数を既に作成した Cube と CameraActor に設定します。
[Play (プレイ)] を押すと、カメラがこのビューにスナップします。
そしてビューへスムーズにブレンドします。
スナップバックする前に数秒間待機します。
これで、純粋にゲームロジックに基づいてプレーヤーのカメラを動かすシステムができました。このコードは、プレイヤーがカメラを直接操作しないゲームやカメラビュー間のブレンディングが役立つゲームなど、任意のゲームで使用できるように変更可能です。
完成コード
CameraDirector.h
// Copyright 1998-2017 Epic Games, Inc.All Rights Reserved.
#pragma once
#include "GameFramework/Actor.h"
#include "CameraDirector.generated.h"
UCLASS()
class HOWTO_AUTOCAMERA_API ACameraDirector : public AActor
{
GENERATED_BODY()
public:
// このアクタのプロパティのデフォルト値を設定する
ACameraDirector();
protected:
// ゲーム開始時またはスポーン時に呼び出される
virtual void BeginPlay() override;
public:
// フレーム毎に呼び出される
virtual void Tick( float DeltaSeconds ) override;
UPROPERTY(EditAnywhere)
AActor* CameraOne;
UPROPERTY(EditAnywhere)
AActor* CameraTwo;
float TimeToNextCameraChange;
};
CameraDirector.cpp
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
#include "HowTo_AutoCamera.h"
#include "CameraDirector.h"
#include "Kismet/GameplayStatics.h"
// デフォルト値を設定する
ACameraDirector::ACameraDirector()
{
// フレームごとにTick()を呼び出すようにこのアクタを設定する。 必要ない場合は、これをオフにしてパフォーマンスを向上させることができる。
PrimaryActorTick.bCanEverTick = true;
}
// ゲーム開始時やスポーン時に呼び出される
void ACameraDirector::BeginPlay()
{
Super::BeginPlay();
}
// フレーム毎に呼び出される
void ACameraDirector::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
const float TimeBetweenCameraChanges = 2.0f;
const float SmoothBlendTime = 0.75f;
TimeToNextCameraChange -= DeltaTime;
if (TimeToNextCameraChange <= 0.0f)
{
TimeToNextCameraChange += TimeBetweenCameraChanges;
//ローカルぷpレイヤーの制御を扱うアクタを見つける。
APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
if (OurPlayerController)
{
if (CameraTwo && (OurPlayerController->GetViewTarget() == CameraOne))
{
//カメラ2に滑らかにブレンドする。
OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);
}
else if (CameraOne)
{
//カメラ1に瞬時に切り替わる。
OurPlayerController->SetViewTarget(CameraOne);
}
}
}
}
4 - 応用編
ここまでで学んだ知識を活かして、以下を行ってみましょう。
クレーンまたはドリーのショットを作成するために動くアクタにカメラをアタッチします。
CameraOne と CameraTwo ではなく 配列 変数を 1 つだけ使ってカメラを保存すれば、2 以外の数字をカメラの台数に使うことができます。
カメラの保存には、
[アクタ](making-interactive-experiences\interactive-framework\unreal-engine-actors)ポインタを使わずに、ポインタとビューの変更前の時間を保持する[構造体](programming-and-scripting\programming-language-implementation\cpp-in-unreal-engine\Structs)を作成し、新しいビューに対して時間をブレンドします。
以下はこのチュートリアルの内容の詳しい情報のリンク先です。
カメラとその操作に関する詳細は「カメラ」フレームワークのページ、または「
[Player-Controlled Cameras](programming-and-scripting/programming-language-implementation/cpp-in-unreal-engine/unreal-engine-cpp-tutorials/PlayerCamera)」を参照してください。詳しいチュートリアルは「
[C++ プログラミング チュートリアル](programming-and-scripting/programming-language-implementation/cpp-in-unreal-engine/unreal-engine-cpp-tutorials)」を参照してください。