このチュートリアルでは、カメラのアクティベート方法、またあるカメラから別のカメラへアクティブなカメラを切り替える方法を紹介します。
1 - ワールドにカメラを配置する
Unreal Engine 4 の初心者は、プログラミング クイックスタート チュートリアル をお勧めします。このドキュメントでは、プロジェクトの作成、プロジェクトへの 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」ヘッダファイルで、いくつかの汎用関数にアクセスすることができます。そのうちの 1 つはこのチュートリアルに必要な関数です。終了後、以下のコードを ACameraDirector::Tick の下部に追加します:
const float TimeBetweenCameraChanges = 2.0f; const float SmoothBlendTime = 0.75f; TimeToNextCameraChange -= DeltaTime; if (TimeToNextCameraChange <= 0.0f) { TimeToNextCameraChange += TimeBetweenCameraChanges; // Find the actor that handles control for the local player (ローカルプレイヤーをコントロールするアクタを検索) APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0); if (OurPlayerController) { if ((OurPlayerController->GetViewTarget() != CameraOne) && (CameraOne != nullptr)) { // Cut instantly to camera one. (カメラ 1 画面に瞬時に切り替え) OurPlayerController->SetViewTarget(CameraOne); } else if ((OurPlayerController->GetViewTarget() != CameraTwo) && (CameraTwo != nullptr)) { // Blend smoothly to camera two. (カメラ 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:
// Sets default values for this actor's properties (このアクタのプロパティのデフォルト値を設定)
ACameraDirector();
protected:
// Called when the game starts or when spawned (ゲーム開始時またはスポーン時に呼び出されます)
virtual void BeginPlay() override;
public:
// Called every frame (フレーム毎に呼び出されます)
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"
// Sets default values
ACameraDirector::ACameraDirector()
{
// Set this actor to call Tick() every frame.You can turn this off to improve performance if you don't need it. (必要がなければパフォーマンスを向上させるためにオフにすることができます)
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned (ゲーム開始時またはスポーン時に呼び出されます)
void ACameraDirector::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame (フレーム毎に呼び出されます)
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;
//Find the actor that handles control for the local player. (ローカル プレイヤーをコントロールするアクタを探します。)
APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
if (OurPlayerController)
{
if ((OurPlayerController->GetViewTarget() != CameraOne) && (CameraOne != nullptr))
{
//Cut instantly to camera one.(カメラ 1 画面に瞬時に切り替え)
OurPlayerController->SetViewTarget(CameraOne);
}
else if ((OurPlayerController->GetViewTarget() != CameraTwo) && (CameraTwo != nullptr))
{
//Blend smoothly to camera two (カメラ 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:
// Sets default values for this actor's properties (このアクタのプロパティのデフォルト値を設定)
ACameraDirector();
protected:
// Called when the game starts or when spawned (ゲーム開始時またはスポーン時に呼び出されます)
virtual void BeginPlay() override;
public:
// Called every frame (フレーム毎に呼び出されます)
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"
// Sets default values
ACameraDirector::ACameraDirector()
{
// Set this actor to call Tick() every frame.You can turn this off to improve performance if you don't need it. (必要がなければパフォーマンスを向上させるためにオフにすることができます)
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned (ゲーム開始時またはスポーン時に呼び出されます)
void ACameraDirector::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame (フレーム毎に呼び出されます)
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;
//Find the actor that handles control for the local player. (ローカル プレイヤーをコントロールするアクタを探します。)
APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
if (OurPlayerController)
{
if (CameraTwo && (OurPlayerController->GetViewTarget() == CameraOne))
{
//Blend smoothly to camera two (カメラ 2 へスムーズにブレンド)
OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);
}
else if (CameraOne)
{
//Cut instantly to camera one.(カメラ 1 画面に瞬時に切り替え)
OurPlayerController->SetViewTarget(CameraOne);
}
}
}
}
4 - 応用編
ここまでで学んだ知識を活かして、以下を行ってみましょう。
クレーンまたはドリーのショットを作成するために動くアクタにカメラをアタッチします。
CameraOne と CameraTwo ではなく 配列 変数を 1 つだけ使ってカメラを保存すれば、2 以外の数字をカメラの台数に使うことができます。
カメラの保存には、アクタ ポインタを使わずに、ポインタとビューの変更前の時間を保持する 構造体 を作成し、新しいビューに対して時間をブレンドします。
以下はこのチュートリアルの内容の詳しい情報のリンク先です。
カメラとその操作に関する詳細は「カメラ 」フレームワークのページ、または「Player-Controlled Cameras 」を参照してください。
詳しいチュートリアルは「C++ プログラミング チュートリアル 」を参照してください。