対象人物
Unityを使った事が有り、
Blueprintを使ってみたけどやっぱりC#みたいな言語で書きたいと思ってる。
けどUnrealC++に手を出そうとしたら出来る事が多すぎて
全体的にボヤッとしてて何をすべきか分からない。
という人を対象にしています。
途中からチュートリアル形式になっており実際にプロジェクトを作りながら進めてゆきます。
完成するとこんな感じになります。
https://www.youtube.com/watch?v=gX87kcvKgA8
完成品ファイルはこちらになります。
7zipで圧縮してるので何とかして解凍してください。
https://bowlroll.net/file/114338
EpicさんのサイトでもUnity→UE4の引っ越し方法をもっと詳しく細かく解説しています。
https://docs.unrealengine.com/latest/JPN/GettingStarted/FromUnity/index.html
※C++用推奨図書
C++をある程度触ったことが有る事を前提としています。
10年くらいに前に仕入れた情報なので、書籍は古めです。
C++ の絵本 amazon
記事内では名前が長い物を下記のように省略する場合が有ります。
割と適当にやってるんであとは雰囲気で察してください。
元 | 省略 | |
---|---|---|
BluePrint | → | BP |
BluePrintEditor | → | BPE |
BluePrintClass | → | BPClass |
BluePrintVisualScript | → | BPVS |
UNITYのプレハブの構造
UNITYではGameObjectに様々なコンポーネントを付けてゆきました。
それがプレハブという入れ物に入って設定込みで保存されています。
UE4のBlueprint Classの構造
UE4ではUNITYと名前は違いますが用途は同じです。
対応は下記の通り。
Unity | UE4 | |
---|---|---|
プレハブ | → | Blueprint Class |
GameObect | → | Actor |
Component | → | Actor Component |
UE4でもActorComponentを追加していけば良いのです。 |
Unityと同じコンポーネント指向的なやり方で作ってみよう!
構造は違うようで似通っています。
ここからはチュートリアル形式になりますので、
Unityのコンポーネントの作り方を似てるポイントを掴みつつ進めてみてください。
以下の動画が完成品の動作になります。
https://www.youtube.com/watch?v=gX87kcvKgA8
ThirdPersonのサンプルを元にして、連射銃を持たせます。
ポイントとしては
・全てをC++で作ろうとするのではなく、部分的にはBPも使用する。
・既存のBluePrintClassを利用しコンポーネントを追加する形で拡張している。
(他人のコードとの連携を上手くやっている。)
・ActorComponentで実装することにより再利用性の高い部品を作っている。
辺りになります。
テンプレートを元にTPSサンプルを作る
2、BluePrintの方のThirdPersonを選んで作成します。
尚、BluePrintの方を選択する理由は後述します。
3、こんな画面が表示されると思います。
今回はこの左側の灰色の人に連射銃を付けてみたいと思います。
弾丸を作る
簡単なコードはBPVisualScriptで作るべきなのでここのコードはBPVisualScriptで作ります。
BPVisualScriptとC++のどちらで作るかの境目は決めておくべきなので
「For,While,Switchの制御文、またはローカル変数が必要になったらC++化する。」
と決めています。
このBluePrintVisualScriptの場合はこれらをどれも使わないため、
BluePrintVisualScriptで作成します。
3、BulletにSphereのSceneComponentを追加します。
5、こんな感じのBSVisualScriptを書きます。
尚、UE4では**+X方向が前方です。
BPClassのエディター上ではあたかも-Y方向が前方であるかのように見えますがアレは罠**です
6、WorldOutlinerに配置し、Playしたら直ぐに前方へ飛んでいけば作成成功です。
C++ファイルを作る下準備
1、まずNewC++classで適当なファイルを作ります。
これを行わないとC++ファイル保存用のフォルダが出てこないためになります。
2、なんでも良いのですが僕の場合はいつもSceneComponentのDummyを作ります。
SceneComponentを選択して。
※Unityで言うところのEmptyObjectの代わりです。
※UE4では標準搭載ではないためこのタイミングでついでに作っておきます。
4、するとプロジェクトのフォルダ内にSourceというフォルダが出来ます。
この中にAComponentというフォルダを作成します。
タイマーを作ってみよう
前と同じやり方でTimerというActorComponentを
AComponentというフォルダ内に作りましょう。
C++内で出てくるマクロの機能表です。
マクロ名 | 内容 |
---|---|
UFUNCTION(BlueprintCallable, Category = "Timer") | BPVSへ関数が公開されます。 |
UPROPERTY(BlueprintReadWrite, EditAnywhere) | 変数がBPVS,BPEへ公開されます。 |
UPROPERTY(BlueprintReadWrite) | 変数がBPVSから読み書きできる |
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FNoArg) | デリゲートを使う前の呪文 |
UPROPERTY(BlueprintAssignable) | デリゲートにBPEでBPVSを入れられるようにします。 |
デリゲートを作るとこんな感じのが出てきます。
中にBPVisualScriptを入れられるのでBPVisualScriptとの連携を
前提にしてる場合は必須アイテムになります。
UPROPERTYの引数にBlueprintReadWriteが入っているとBPVisualScriptでアクセス出来るようになります。
UPROPERTYの引数にEditAnywhereが入っているとBPEditor上で設定できるようになります。
クラス作成を行ったらコードは下記のようにしてください。
名前がTimerで一致してればコピペで大丈夫です。
中身については上のマクロ機能表を参考に読んで頂ければと思います。
機能としては下記のようになっています。
・一定時間ごとに所定のBlueprintVisualScriptを実行する。
・Start(bool)でスタートさせたり停止させたりする。
・スタートしたらとりあえず一発実行しておく(実行するかの切り替え有り)
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "Components/ActorComponent.h"
//追加ヘッダを書く場合はここに書きます。
//今回は使いません。
#include "Timer.generated.h"
//デリゲートを使う場合の儀式です。
//通常はどこか適当なヘッダに呼び出す用に書いておくのですが今回はヘッダ内に書きます。
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FNoArg);
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class FIRST_API UTimer : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UTimer();
// Called when the game starts
virtual void BeginPlay() override;
// Called every frame
virtual void TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction ) override;
//停止中でもこれを実行するとスタートします。
//引数次第では停止ボタンにもなります。
//動作中にもう一回実行するとタイマーがリセットされます。
UFUNCTION(BlueprintCallable, Category = "Timer")
void Start(bool enable);
//この変数の感覚でデリゲートの関数を実行します。
UPROPERTY(BlueprintReadWrite, EditAnywhere)
float m_TimeSpan = 1.0f;
//現在アクティブか保存しておきます。
//UE4標準のやつは動作を把握してないのであえて使いません。
UPROPERTY(BlueprintReadWrite, EditAnywhere)
bool m_ActiveNow = false;
//スタートした時に一回実行する設定
UPROPERTY(BlueprintReadWrite, EditAnywhere)
bool m_StartFile = true;
//現在の時間です。
UPROPERTY(BlueprintReadWrite)
float m_TimeNow = 0.0f;
//デリゲートになります。
//こう書いておくと、BP側から好きな関数を入れたりできます。
UPROPERTY(BlueprintAssignable)
FNoArg m_TimerFire;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "first.h"
#include "Timer.h"
// Sets default values for this component's properties
UTimer::UTimer()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
bWantsBeginPlay = true;
PrimaryComponentTick.bCanEverTick = true;
// ...
}
// Called when the game starts
void UTimer::BeginPlay()
{
Super::BeginPlay();
if (m_ActiveNow)
{
//スタート直後に一回実行
m_TimerFire.Broadcast();
}
// ...
}
// Called every frame
void UTimer::TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction )
{
Super::TickComponent( DeltaTime, TickType, ThisTickFunction );
//アクティブ状態だったら時間を加算する。
if (m_ActiveNow)
{
m_TimeNow += DeltaTime;
//時間積算が一定以上になったらデリゲート関数を実行
if (m_TimeNow > m_TimeSpan )
{
m_TimeNow -= m_TimeSpan;
m_TimerFire.Broadcast();
}
}
else
{
// 時間計算中じゃないのにアクティブだった場合は非アクティブにする。
if ( this->IsActive() )
{
this->Activate( false );
}
}
// ...
}
void UTimer::Start(bool enable)
{
this->Activate(enable);
m_ActiveNow = enable;
m_TimeNow = 0.0f;
if(m_ActiveNow)
{
//スタート時に一回デリゲート関数を実行
m_TimerFire.Broadcast();
}
}
連射ショットを作ってみよう
5、先ほど作ったActorComponentのTimerを追加します。
7、こんな感じのBPVisualScriptを作ります。
m_TimerFileは以下をクリックすると出てきます。
8、完成
以上で完成します。
Playすると「完成品」の動きになります。
操作方法:
A 左へ歩く
S 下へ歩く
D 右へ歩く
W 上へ歩く
Space ジャンプ
左クリック ショット
完成品
https://bowlroll.net/file/114338
おまけ、今回使用したBlueprintClass(Character)の構造
前回の図で「Actor自体が機能を持っている」と書いていましたが
Actorの追加機能版であるCharacterでは多くの標準機能を持っています。
全て書くと大変になるので端折っていますが代表格は下記の通り。
・Ai機能
・アニメーション機能
・キャラクターコントローラ
特にAi機能、アニメーション機能についてはCharacter自体に組み込まれた機能で
コンポーネントにはなってません。
これらはUnityには無い機能で作られています。
次回予告
次の投稿では今回の内容をもう少し詳しくいきます。
具体的にはまだ書いてませんが、下記みたいな感じになると思います。
・何故UE4では迷ってしまうのか?の正体
・Actor継承も出来るけど、触れるべからず