このチュートリアルでは、カメラのアクティベート方法、またあるカメラから別のカメラへアクティブなカメラを切り替える方法を紹介します。
1 - ワールドにカメラを配置する
Unreal Engine を初めて使用する場合は「
まず「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; // 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. OurPlayerController->SetViewTarget(CameraOne); } else if ((OurPlayerController->GetViewTarget() != CameraTwo) && (CameraTwo != nullptr)) { // Blend smoothly to camera two. 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.
OurPlayerController->SetViewTarget(CameraOne);
}
else if ((OurPlayerController->GetViewTarget() != CameraTwo) && (CameraTwo != nullptr))
{
//Blend smoothly to camera two.
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.
OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);
}
else if (CameraOne)
{
//Cut instantly to camera one.
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」を参照してください。
詳しいチュートリアルは「C++ プログラミング チュートリアル」を参照してください。