とあるゲームプログラマの挑戦と敗北の歴史

UE4とプログラミングとmayaとpythonとhtmlとマラソンを中心に情報を発信する元「技術ブログを目指すブログ」から再始動した毎日の日々を発信するブログです。

UE4:俺流モーションのリターゲットの手法

モーションのリターゲット方法、
つまり、とあるスケルトン向けに作られたモーションから
別のスケルトンで使用可能なモーションで使用できるようにする方法を明記します。

ただし、俺調べです。正確かどうかはしりません。


・EpicGamesLauncherからモーションの適応先のモデルをプロジェクトに追加します。
f:id:toncrimentan_w:20211213020022p:plain


・EpicGamesLauncherからモーションの適応元のモーションをプロジェクトに追加します。
f:id:toncrimentan_w:20211213020059p:plain


・無事2つのアセットが追加されました。
f:id:toncrimentan_w:20211213020132p:plain


・リターゲット元のスケルトンを開く
f:id:toncrimentan_w:20211213020404p:plain


・リターゲットマネージャータブがない場合は
 メニューバーからリターゲットマネージャーを選択し、
 リターゲットマネージャータブを開く。
f:id:toncrimentan_w:20211213020820p:plain


・リグを設定のコンボボックスから、適応先スケルトンのリグを選択します。
f:id:toncrimentan_w:20211213021005p:plain


・保存ボタンをクリックし、適当な名前をつけて、
 適応元のスケルトンから適応先のスケルトンへのマッピングを作成する
f:id:toncrimentan_w:20211213021441p:plain


・適応元モーションアセットを右クリック
 Animアセットをリターゲットする>Animアセットとリターゲットを複製する
 を選択
f:id:toncrimentan_w:20211213022048p:plain


・リターゲット先のスケルトンを選択し、リターゲットボタンを押す。
f:id:toncrimentan_w:20211213022233p:plain


・適応先スケルトン用のモーションアセットを制作することができました。
f:id:toncrimentan_w:20211213022427p:plain


・適応元スケルトンのモーションと
 適応先スケルトンのモーションを並べるとこの通り!
 無事、異なるスケルトンでモーションアセットを利用することができました。
f:id:toncrimentan_w:20211213022608p:plain


以下実際の動作した映像です。
youtu.be

UE4:アンリアルクエスト2に参加しました

先日、UnrealFestとヒストリアさんのコラボコンテストとして開催された
アンリアルクエスト2に参加しました。

URLはこちら
https://www.unrealengine.com/ja/events/how-to-join-unrealquest2


でできた作品はこちら
youtu.be


6日間で1日1回お題が発表され、
初級、中級、上級に分けられたクエストをクリアーしていけば
一本のゲームが完成します。



お題は以下のとおり、
達成したのも、未達成のものもありますね!

1日目
初級:好きなアセットを配置しよう (達成)
中級:揺らめく旗を立てよう (達成)
上級:スプラインに沿ってモノを効率よく配置しよう (達成)

2日目
初級:ライティングを全種置こう (達成)
中級:時間を変化させよう (達成)
上級:ライトシャフトを作ろう (未達成)

3日目
初級:松明を作ろう (達成)
中級:歩くと煙が立つ (達成)
上級:ゴール演出を作ろう (未達成)

4日目
初級:松明に音を付けよう (達成)
中級:歩くと足音が鳴る (達成)
上級:歩く地面に寄って足音を変えよう (未達成)

5日目
初級:温かみか冷たさを感じる色味をつくろう (達成)
中級:ダメージを受けた時の表現をつくろう (達成)
上級:物陰に隠れるとシルエットになる (未達成)



昼と夜が交互に訪れる世界で、
昼は、フィールド上のパンを集め、
夜は、フィールド上のエネミーから身を守るメリハリのあるゲームになっています!
f:id:toncrimentan_w:20211114160838p:plain

f:id:toncrimentan_w:20211114162524p:plain

夜はこんな感じに幽霊が登場、
星空が広がってカラーバランスも変更し冷たい雰囲気になるのも特徴ですね
f:id:toncrimentan_w:20211114162726p:plain



前回のアンリアルクエストは、
仕事が忙しい!とかいうよくある話により最後まで走り切れなかったわけですが、
今回のアンリアルクエストはきちんと納期を守り完成させることができました。

最終日は、朝5時までおきてましたね!



実は、このアンリアルクエスト、向いてる点向いていない点わかっていました。
実は私はちょっとずつお題が発表されてくるのは実は向いてない方のようです
できれば、最終形を一度に発表していただき、
仕事の優先順とかはこちらで作っていくというのが私のスタイルっぽいです。

細かい部品から作っていくのではなく、全体から作っていくという方法が
どうやら向いてるっぽいですね。

UE4:オンラインラーニング(Paper 2D プロジェクトを始めよう)

UE4オンラインラーニング
Paper 2D プロジェクトを始めよう
を受講した際のおぼえ書きです。

https://learn.unrealengine.com/course/3770296


なんと、今月配信の新しいコースです!



プロジェクトの作成)
2Dサイドスクロールのテンプレートから作成し、
事前に Paper2dプラグイン を有効にしておく必要があります。
f:id:toncrimentan_w:20211011224429p:plain

f:id:toncrimentan_w:20211011224553p:plain



テクスチャのインポート方法)
まず、マップ用、キャラ用のtgaデータをuassetとして
インポートする必要があります。

・tgaをドロップすることでインポートします。
f:id:toncrimentan_w:20211011224743p:plain
・圧縮>圧縮設定
 をUserInterface2Dに変更
f:id:toncrimentan_w:20211011224807p:plain
・レベルオブディテール>ミップマップ全般設定
 をミップマップなしに変更
f:id:toncrimentan_w:20211011224818p:plain
・アジャストメント>ChromaKeyTexture
 を有効に変更
f:id:toncrimentan_w:20211011224905p:plain
・アジャストメント>ChromaKeyColor
 をクリックし、スポイトを利用しテクスチャ画像の背景部分を選択することで
 テクスチャの背景の部分を抜きとして扱うように指定します。
f:id:toncrimentan_w:20211011224929p:plain
 すると、このように
f:id:toncrimentan_w:20211011225231p:plain
・1つ設定すればあとは
 アセットを右クリック>スプライトアクション>Paper2Dテクスチャ設定を適用
 で一括抜き設定ができるらしい(要確認)
 すると、無事ほかのスプライトも抜き設定が完了する
f:id:toncrimentan_w:20211011225518p:plain



スプライトの作成方法)
1つのテクスチャには複数枚のキャラクターのパラパラ漫画画像が含まれています。
複数枚の画像を一枚ずつ抽出してモノがスプライトです。

・テクスチャを右クリック>スプライトアクション>スプライトを抽出
 をクリックすることで、スプライトを自動で抽出することができます。
f:id:toncrimentan_w:20211012002944p:plain
・開いてみるとわかる通り、
 これではスプライトごとに異なるサイズと認識されてしまいます。
f:id:toncrimentan_w:20211011225917p:plain
・設定>スプライト抽出モード
 をグリッドに変更
 グリッド>セルの幅、セルの高さ
 を64x64に変更することで無事、用意したときのサイズに認識できました。
f:id:toncrimentan_w:20211011230114p:plain
・抽出をクリックすることで
 ナンバリングされたスプライトの抽出に成功します(0~)
f:id:toncrimentan_w:20211011230244p:plain
・抽出したスプライトは、ひとつのフォルダにまとめておきます。
f:id:toncrimentan_w:20211011230306p:plain


フリップブックの作成方法)
フリップブックとは、
抽出したスプライトから生成される、一連のパラパラ漫画アセットです。

・抽出したスプライトをすべて選択、
 右クリック>フリップブックを作成
 をクリックすることで。
f:id:toncrimentan_w:20211012003029p:plain
・フリップブックという動画アセットが作成できます。
(画像は動いています。)
f:id:toncrimentan_w:20211011230558p:plain
・フリップブックは別フォルダにまとめておきます。
f:id:toncrimentan_w:20211011230612p:plain
・フリップブックを開くと
 以下のようにタイムラインで制御可能なエディタが表示されます。
 これは便利そう!
f:id:toncrimentan_w:20211011230707p:plain


タイルセットの作成方法)
こちらはマップに関するアセットです。
複数の床から構成されたタイル画像から、
マップ作成時に利用するアセットを作成します。

・テクスチャを
 右クリック>スプライトアクション>タイルセットを作成
 を選択するとタイルセットが作成される
f:id:toncrimentan_w:20211011231708p:plain
・作成したタイルセットは別フォルダにまとめておきます。
f:id:toncrimentan_w:20211011231738p:plain
・タイルセットを開くと
 以下のようなタイルセットエディタが出現する
f:id:toncrimentan_w:20211011231802p:plain
・タイルセット>BorderMarginを
 4 4 4 4に変更
 タイルセット>Per-Tile Spacingを
 8 8 に変更でいい感じのタイル間隔に変更します。
f:id:toncrimentan_w:20211011231935p:plain



タイルのコリジョン設定)
・タイルの衝突を選択しておきます。
f:id:toncrimentan_w:20211011232018p:plain

・ボックスの追加
 をクリックすることでボックスコリジョンを作成できます。
f:id:toncrimentan_w:20211011232033p:plain
・さらに、頂点を選択し形を変えることができる。
f:id:toncrimentan_w:20211011232133p:plain
 TIPS:
 グリッドを細かく表示して完璧につくるのがオススメ
f:id:toncrimentan_w:20211011232225p:plain

・ポリゴンを追加
 をクリックすることで頂点を指定してポリゴンコリジョンを作成できます。
 四角以外の形状はこれで対応します。
 (時計回りに選択し→Enter)
f:id:toncrimentan_w:20211011232402p:plain
・Shiftを押しながらクリックで頂点の追加
 Deleteで頂点を削除できます。
f:id:toncrimentan_w:20211011232458p:plain

同様の手順ですべてのタイルにコリジョンを設定していきます。
f:id:toncrimentan_w:20211011232522p:plain



タイルマップの作成)
タイルマップとはタイルセットから作られた実際のマップです。
(タイルマップを並べて使うこともできますが、実質タイルマップがマップです)

・タイルセットを右クリック>タイルマップを作成
 をクリックすることでタイルマップを作成します。
f:id:toncrimentan_w:20211011233110p:plain
・別のフォルダに移動しておきます。
f:id:toncrimentan_w:20211011233136p:plain
・タイルマップを開くと
 タイルマップエディタが表示されます。
 (作成元のタイルセットから生成したタイルマップを作成できます。)
f:id:toncrimentan_w:20211011233159p:plain
・セットアップ>MapWidth、MapHeight
 を24x24に変更することでマップを大きくできます。
f:id:toncrimentan_w:20211011233246p:plain
 TIPS:
 グリッドを表示しておくのがオススメ
f:id:toncrimentan_w:20211011233337p:plain



レイアの作成)
・マップを構成する3つのレイアを作成します。

f:id:toncrimentan_w:20211011233549p:plain
 Backgroundレイアは
 LayerCollidesのチェックを外し、単なる背景として作成します。

 Middleレイアは
 LayerCollidesのチェックはそのまま

 Foregroundレイアは
 LayerCollidesのチェックを外し、単なる前景として作成します。

 並びもForeground、Middle、Backgroundの順

・タイルを選択すると、グリッドの方に絵を描くように配置することができます。
f:id:toncrimentan_w:20211011233810p:plain
・消しゴムで消すこともできる。
f:id:toncrimentan_w:20211011233822p:plain
・Shiftを押しながら複数のグリッド選択で複数のタイルを複製し
 配置することができます。
f:id:toncrimentan_w:20211011233846p:plain
・複数のタイルを選択して一度に配置することもできる。
f:id:toncrimentan_w:20211011233926p:plain
 タイルを左右反転、上下反転して配置することもできてしまう!!
f:id:toncrimentan_w:20211011233958p:plain
・塗りつぶし
 フィル>タイル選択>塗りたい箇所を選択
 で塗りつぶすこともできます。
f:id:toncrimentan_w:20211011234035p:plain

Foreground、Middle、Background それぞれのマップができました。
f:id:toncrimentan_w:20211011234142p:plain



レベルの作成)
いよいよ、作成したタイルマップをレベルに配置します。

・タイルマップをレベルに配置
f:id:toncrimentan_w:20211011234540p:plain
・カメラを右、ライティングをなしに変更するとよい。
f:id:toncrimentan_w:20211011234622p:plain
 TIPS:
 エディタの環境設定で
 レベルエディタ>グリッドのスナップ>2の累乗スナップサイズを使用
 にチェックをれることで移動間隔を2の累乗から設定できるようになります。
f:id:toncrimentan_w:20211011234758p:plain

プレイヤースタートを配置し実行すればこの通り
f:id:toncrimentan_w:20211011234825p:plain



プレイヤーの作成)

・キャラクターは、
 PaperCharacterクラスを親として作成します。
f:id:toncrimentan_w:20211011234909p:plain
・Spriteコンポーネント
 SourceFlipbookを作成したアイドリングのフリップブックに変更することで
 アイドリングの画像を変更できます。
 (グレイマン、カワイイですね)
f:id:toncrimentan_w:20211011234951p:plain
CapsuleコンポーネントのCapsuleHalfHeight CapsuleRadiusを変更し
 コリジョンの大きさを整える
f:id:toncrimentan_w:20211011235007p:plain



カメラの作成)
・SpringArmコンポーネントを作成し、-90度回転
 UsePawnControlRatationのチェックを入れ、InheritYawのチェックを外し、
 キャラクタのYaw回転の影響を受けないようにする
f:id:toncrimentan_w:20211011235146p:plain
・あとは、SpringArmにカメラコンポーネントをつける
f:id:toncrimentan_w:20211011235217p:plain



選択ノード)
ひし形のピンはワイルドカードです。
右クリック>ピンの種類を変更
から入力をかえることができます。このように。
f:id:toncrimentan_w:20211011235649p:plain



キャラの移動)
・SpriteコンポーネントのSetFlipbookノードを利用し、
 キャラクターの画像を切り替えることができます。
f:id:toncrimentan_w:20211011235950p:plain
・実際に出来上がった、歩きBPです。
f:id:toncrimentan_w:20211011235751p:plain



キャラの走り)

・プロジェクト設定>インプット>アクションバインディング
 から走りボタンを指定します。

 簡単な指定方法は、キーボードボタンをクリックすることで、
 直接キーボードから設定することです。
f:id:toncrimentan_w:20211012000304p:plain
・実際に出来上がった走りBPです。
 走り中かどうかにより、移動画像を変えています。
f:id:toncrimentan_w:20211012000516p:plain



キャラのジャンプ)

2Dのフリップブックを利用した開発では、
通常のアニメーションBPを利用した開発とちがい、
モーションのながれをBPで実装しなくてはなりません。

そのため今まで知らずとも製作してこれた、
OnJumpedイベント、OnReachedJumpApex、OnWalkingOffLedgeイベントなど
に関しても理解する必要があります。

・OnJumpedイベント
 このイベントはJumpをした直後に実行されるイベントです。
f:id:toncrimentan_w:20211012000833p:plain

・以下がジャンプのBPです。

 あらかじめBeginPlayで
 ジャンプ最高点イベント(OnReachedJumpApex)にバインド、
 スプライト再生完了イベント(OnFinishedPlaying)にバインドしておきます。

 ジャンプ開始イベント(OnJump)
 が呼ばれた時に、ジャンプ開始画像に変更

 ジャンプ最高点イベント(OnReachedJumpApex)
 が呼ばれた時に、ジャンプ開始から落下に変わる画像に変更

 スプライト再生完了イベント(OnFinishedPlaying)
 が呼ばれたときに、開始から落下に変わる画像かを判別し
 ジャンプ落下画像に変更

 以上がジャンプの遷移です。
f:id:toncrimentan_w:20211012001257p:plain


・落下イベント(OnWalkingOffLedge)は
 ジャンプしてないが、落下した場合を検知し呼び出されるイベントです。
 ここで落下時の画像に変更することができます。
f:id:toncrimentan_w:20211012001414p:plain


長いですが、以上が、
epic標準のパラパラ漫画タイプの2Dゲームの作成環境です。

動画では、トップビュータイプのゲーム制作に関してもレクチャーしています。



実際に出来上がったもの
youtu.be



こちらのコースを受講することで、
epic標準のパラパラ漫画タイプの、
ゲーム制作環境について理解できました。

SpriteStudio、Spineなどと違い、
スパロボではなく、スーパーマリオ程度か、な~んだ
と侮ってはいけないです。
パラパラ漫画タイプのものを制作するのに便利な機能がついています。

そして、実際にマップを歩かせることになるため、
コリジョン付きタイルを配置するための、
マップ作り機能に関しても理解できます。

ちっちゃいグレイマンの画像が手に入ります。

とても面白かったです。オススメのコースです。

UE4:オンラインラーニング(探偵事務所のゲーム環境を作成する)

UE4オンラインラーニング
探偵事務所のゲーム環境を作成する
を受講した際のおぼえ書きです。

https://learn.unrealengine.com/course/3549094



・UCX_プリフィックス
外部ツールでコリジョンモデル作る場合
UCX_というプリフィックスをつける必要がある。

UCX_〇〇



・テクスチャ名の命名規則
_D:ディフューズ用
_M:マスク用
_N:ノーマル用
と名前を付けるのもよいです。
f:id:toncrimentan_w:20211010130136p:plain



・ポイントライトの処理負荷軽減
ポイントライトは非常に処理負荷の高いライトです。
利用する場合も、Cast Shadows をOFFにすることで軽量化できます。
f:id:toncrimentan_w:20211010130400p:plain



・マップの色からライトを作る方法
Ctrl+Lをおがらビューをクリックすることで
クリックした場所にクリックした場所の色のライトを生成することができます。
これは便利な方法です。
f:id:toncrimentan_w:20211010130519p:plain



・ライトビルド方法
ビルドボタンの右のボタン>ライティングのみビルド
をクリックすることでライトのビルドを行うことができます。

時間がかかる処理なのでオススメは
ライティング品質を中にすることです。
f:id:toncrimentan_w:20211010130740p:plain



・ポストプロセス
レンズ>ChromaticAberration>強度
で幻覚を見せられているかのような演出ができます。
f:id:toncrimentan_w:20211010131030p:plain

レンズ>Exposure>露出補正
で露出補正、明るくできます
f:id:toncrimentan_w:20211010131100p:plain

カラーグレーディング>WhiteBalance>温度
で温かみのある色彩にできます。
下げれば青色です、上げれば黄色です。
f:id:toncrimentan_w:20211010131116p:plain

カラーグレーディング>Global>彩度
で彩度を変更できます。
f:id:toncrimentan_w:20211010131221p:plain

カラーグレーディング>Global>オフセット
でオフセットをかけれます
f:id:toncrimentan_w:20211010131238p:plain



全体を通しMayaからUE4にインポートするまでの、
一連の手順についての解説動画でした。
そのため、Mayaという外部ツールに関する説明も含まれるため、
半分以上は座学、といったコースになっています。

UE4:オンラインラーニング(ゲームプレイのコンポーネントを分解する)

UE4オンラインラーニング
ゲームプレイのコンポーネントを分解する
を受講した際のおぼえ書きです。
https://learn.unrealengine.com/course/3762527



ActorComponentの作り方

・コンテンツブラウザで
 C++フォルダで右クリック>新規C++クラスを選択>ActorComponentを選択
 することで作成することができます。
f:id:toncrimentan_w:20210924010336p:plain

・クラス名を入力して、クラスを作成
f:id:toncrimentan_w:20210924010459p:plain

・エディタから、C++のヘッダとソース作成に成功しました
f:id:toncrimentan_w:20210924010528p:plain

・ソースを記述し、ビルド実行
ヘッダーファイル

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "FloatingComponent.generated.h"

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class COMPONENTSOFGAMEPLAY_API UFloatingComponent : public UActorComponent
{
	GENERATED_BODY()

public:	
	UFloatingComponent();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Floating")
	FVector FloatRange = FVector(0,0,0);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Floating")
	float SpeedMultiplier = 1.0f;

private :
	UPROPERTY()
	AActor* Parent = nullptr;
	FVector StartLocation;
};

ソースファイル

#include "FloatingComponent.h"

UFloatingComponent::UFloatingComponent()
{
	PrimaryComponentTick.bCanEverTick = true;
}

void UFloatingComponent::BeginPlay()
{
	Super::BeginPlay();

	Parent = GetOwner();
	if (Parent)
	{
		StartLocation = Parent->GetActorLocation();
		Parent->GetRootComponent()->SetMobility(EComponentMobility::Movable);
	}
}

void UFloatingComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	const float Time = GetWorld()->GetRealTimeSeconds();
	const float Sine = FMath::Sin(Time * SpeedMultiplier);

	if (Parent)
	{
		Parent->SetActorLocation(StartLocation + (FloatRange * Sine));
	}
}

・制作したFloatingComponentをアクタに追加し、
 プロパティを入力します。
f:id:toncrimentan_w:20210924010719p:plain

・無事、上下運動をする
 FloatingComponentを持つアクタを配置することに成功しました。
youtu.be



SceneComponentの作り方
SceneComponentは、ActorComponentと違いTransformを含みます。
位置情報を含みます。

・コンテンツブラウザで
 C++フォルダで右クリック>新規C++クラスを選択>SceneComponentを選択
 することで作成することができます。
f:id:toncrimentan_w:20210924011026p:plain

・クラス名を入力して、クラスを作成
f:id:toncrimentan_w:20210924015949p:plain

・エディタから、C++のヘッダとソース作成に成功しました
f:id:toncrimentan_w:20210924015607p:plain

・ソースを記述し、ビルド実行
ヘッダーファイル

#pragma once

#include "CoreMinimal.h"
#include "Components/SceneComponent.h"
#include "HoverComponent.generated.h"

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class COMPONENTSOFGAMEPLAY_API UHoverComponent : public USceneComponent
{
	GENERATED_BODY()

public:	
	UHoverComponent();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

private:

	UPROPERTY()
	UPrimitiveComponent* ParentRoot;

	UPROPERTY(EditAnywhere, Category="Hover Variables")
	float MaxHoverForce = 100.0f;

	UPROPERTY(EditAnywhere, Category="Hover Variables")
	float HoverForceDistance = 100.0f;

	UPROPERTY(EditAnywhere, Category="Debug")
	bool bDrawDebug = false;
};

ソースファイル

#include "HoverComponent.h"

#include "DrawDebugHelpers.h"

UHoverComponent::UHoverComponent()
{
	PrimaryComponentTick.bCanEverTick = true;
}

void UHoverComponent::BeginPlay()
{
	Super::BeginPlay();

	ParentRoot = GetOwner()->FindComponentByClass<UPrimitiveComponent>();
	if(ParentRoot)
	{
		ParentRoot->SetMobility(EComponentMobility::Movable);
		ParentRoot->SetSimulatePhysics(true);
		ParentRoot->SetLinearDamping(2.0f);
		ParentRoot->SetAngularDamping(2.0f);

		MaxHoverForce = MaxHoverForce * ParentRoot->GetMass();
	}
}

void UHoverComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	FHitResult Hit;
	GetWorld()->LineTraceSingleByChannel(Hit, GetComponentLocation(), GetComponentLocation() - FVector(0,0,HoverForceDistance), ECollisionChannel::ECC_Visibility);
	if(Hit.bBlockingHit)
	{
		const FVector StartLocation = GetComponentLocation();
		const float Distance = (StartLocation - Hit.Location).Size();
		const float Ratio = FMath::Clamp(Distance / HoverForceDistance, 0.0f, 1.0f);
		const FVector Force = (1.0f - Ratio) * MaxHoverForce * Hit.ImpactNormal;

		ParentRoot->AddForce(Force, NAME_None, false);
		if(bDrawDebug)
		{
			DrawDebugLine(GetWorld(), StartLocation, Hit.Location, FColor::White, false, 0.0f);
			DrawDebugPoint(GetWorld(), Hit.Location, 10.0f, FColor::Black, false, 0.0f);
		}
	}
}

・制作したHoverComponentをアクタに追加し、
 プロパティを入力します。
f:id:toncrimentan_w:20210924011208p:plain

・無事、上下運動をする
 HoverComponentを持つアクタを配置することに成功しました。
youtu.be



C++でのコンポーネントの追加方法

C++でのコンポーネントを追加する
ヘッダーファイルでは、以下のように記述しプロパティを作成

UPROPERTY(EditDefaultsOnly, Category="Components")
UStaticMeshComponent* Mesh = nullptr;

ソースファイルでは、以下のように記述しコンポーネントを作成

Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));

さらに、作成したコンポーネントでルートコンポーネントを置き換えることが可能です。

RootComponent = Mesh;

・ビルド実行
無事ADemoActorを継承した、BP_DemoActorは
最初からコンポーネントが追加された状態になることが確認できます。
※ルートコンポーネントがMeshになっているのも注目点です
f:id:toncrimentan_w:20210924011839p:plain

・メッシュのアセットの指定
BP_DemoActorのMeshコンポーネントのStaticMeshをエディタで指定します。

・無事、コンポーネントC++で定義し、
 スタティックメッシュはBPで指定したアクタの作成に成功します。
f:id:toncrimentan_w:20210924012217p:plain



スタティックメッシュの作成方法

・アクタを配置パネルから、キューブをレベルに配置
 右クリック>スタティックメッシュへ変換をクリック
f:id:toncrimentan_w:20210924012704p:plain

・スタティックメッシュ名を入力することで、
 アセットを作成することができます。
f:id:toncrimentan_w:20210924012741p:plain

コリジョンの指定
 作成したスタティックメッシュを開き
 メニューバーから
 コリジョン>ボックス単純化コリジョンを追加
 を選択することでコリジョンを追加することを忘れずに
f:id:toncrimentan_w:20210924012843p:plain



オーバーラップイベント関数の登録方法
HomingComponent.hを確認すれば理解できます。

C++でのコールバック関数を登録する
ヘッダーファイルでは、以下のように自作の関数を記述

UFUNCTION(Category = "Homing")
void OnOverlapEnter(class UPrimitiveComponent* ThisComp, 
	class AActor* OtherActor, class UPrimitiveComponent* OtherComp, 
	int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

UFUNCTION(Category= "Homing")
void OnEndOverlap(class UPrimitiveComponent* ThisComp, 
	class AActor* OtherActor, class UPrimitiveComponent* OtherComp, 
	int32 OtherBodyIndex);

ソースファイルでは、以下のように記述しコールバック関数を登録

MagnetSphere->OnComponentBeginOverlap.AddDynamic(this, &UHomingComponent::OnOverlapEnter);
MagnetSphere->OnComponentEndOverlap.AddDynamic(this, &UHomingComponent::OnEndOverlap);




ダメージ時イベント関数の登録方法

C++でのコールバック関数を登録する
ヘッダーファイルでは、以下のように自作の関数を記述

UFUNCTION()
void TakeDamage(AActor* DamagedActor, float Damage, 
	const class UDamageType* DamageType, class AController* InstigatedBy, 
	AActor* DamageCauser);

ソースファイルでは、以下のように記述しコールバック関数を登録

Owner->OnTakeAnyDamage.AddDynamic(this, &UHealthComponent::TakeDamage);

インターフェイスの呼び出し
TakeDamageでは、アクターのインターフェイスを呼び出すようにしています。
インターフェイスを実装していれば、その処理を行い
インターフェイスを実装していなければ、スルーされるテクニックです。

IHealthInterface* Interface = Cast<IHealthInterface>(Owner);
if(Interface)
{
	Interface->Execute_HealthDepleted(Owner);
}




アクタ破棄時イベント関数の登録方法

ヘッダーファイルでは、以下のように自作の関数を記述

UFUNCTION()
void Destruct(AActor* DestroyedActor);

ソースファイルでは、以下のように記述しコールバック関数を登録

Owner->OnDestroyed.AddDynamic(this, &UDestructionComponent::Destruct);

破壊時のコールバック関数では、
アセットが指定されていた時のみ、爆破エフェクトを再生するようにしています。

if(ParticleSystem)
{
	UNiagaraComponent* Effect = 
		UNiagaraFunctionLibrary::SpawnSystemAtLocation(
			GetWorld(), ParticleSystem, Owner->GetActorLocation());
}

爆破の指定がある場合のみ
周辺のアクタに対してダメージをあたえるようにしてあります

const bool Hit = GetWorld()->SweepMultiByChannel(
	HitResults, Start, End, FQuat::Identity, ECC_Camera, ColShape);
for(FHitResult const HitResult : HitResults)
{
	FPointDamageEvent PointDamage;
	HitResult.GetActor()->TakeDamage(
		100.0f, PointDamage, 
		GetWorld()->GetFirstPlayerController(), GetOwner());
}

そして、エディタで爆破の有無、アセットの指定などを個別に行うようにしてあります
f:id:toncrimentan_w:20210924080347p:plain

実際にできたものはこちら
youtu.be



その他のテクニック
コンポーネントのアクタへのアタッチ方法はこちら

MagnetSphere->SetupAttachment(this);

プロパティの変更によって呼び出される関数はこちら

void UHomingComponent::PostEditChangeProperty(
	FPropertyChangedEvent& PropertyChangedEvent)



※注意点
 UE4.26で検証しているのですが、コース通りに作成してもうまく動かず、
 以下の2点を修正することでビルドが通るようになりました。

DevelopmentEditor Win64 でビルド
f:id:toncrimentan_w:20210924084753p:plain

includeパスが通っていない場合がある
f:id:toncrimentan_w:20210924084807p:plain



エンジニアであれば、必ず受講しておく必要があるすばらしいコースです。
コンポーネントを利用した、再利用可能なクラス設計ができるようになります。
クラス継承による拡張ではなく、
コンポーネントによる拡張ができるようになります。

コールバック関数のC++での登録方法なども理解できます。

UE4:オンラインラーニング(アクション RPG:内部を確認する)

UE4オンラインラーニング
アクション RPG:内部を確認する
を受講した際のおぼえ書きです。
https://learn.unrealengine.com/course/3770389



まず、ActionRPGサンプルの公式ドキュメントはこちらです。
https://docs.unrealengine.com/4.27/ja/Resources/SampleGames/ARPG/


ActionRPGサンプル
こちらのコースはEpicGamesLauncherの
ラーニング>学習用ゲーム>ActionRPG
から作成できます。
f:id:toncrimentan_w:20210923114019p:plain



VisualStudioプロジェクトの作成
メニューバーから
ファイル>VisualStudioプロジェクトを作成
をクリックすることで、
C++のVisualStudioプロジェクトを作成することができます。
f:id:toncrimentan_w:20210923114105p:plain



データアセットの作り方
・コンテンツブラウザで
 右クリック>その他>データアセット、を選択
f:id:toncrimentan_w:20210923114222p:plain

・作成したいクラスを選択して作成
 ※URPGWeaponItemはC++で定義されています。
f:id:toncrimentan_w:20210923114314p:plain

・動画のとおりいろいろ入力します。
f:id:toncrimentan_w:20210923114557p:plain

・プレイ後、スタートボタンでショップを開くと、
 自動的にゲーム中に武器が追加されています!!
 ※お金が足りなくて変えない場合は右上の+ボタンから追加
f:id:toncrimentan_w:20210923114840p:plain

これが・・データアセットの力か・・



ゲームプレイアビリティ
このコースでは徐々に回復する「リジェネポーション(Potion_HealthRegen)」
を作成を通じゲームプレイアビリティについて解説しています。

・まず、プラグインはこちらで有効化済みです。
f:id:toncrimentan_w:20210923115205p:plain

・Potion_Healthデータアセットを複製しPotion_HealthRegenを作成します。
f:id:toncrimentan_w:20210923115536p:plain

・武器と同様、自動的にショップに追加されました
f:id:toncrimentan_w:20210923115650p:plain

・ゲームプレイアビリティ、ゲームプレイアビリティエフェクトを
 をそれぞれ複製し、こちらも中身を変更します
f:id:toncrimentan_w:20210923120131p:plain

・超駆け足な解説ですが、
 それぞれ中身を変更していきます。
 というか詳細は、細かいので動画見たほうが良いです。

 リジェネポーションのデータアセットの修正(Potion_HealthRegen)
f:id:toncrimentan_w:20210923120629p:plain

 ゲームプレイアビリティの修正(GA_PotioinHealthRegen)
f:id:toncrimentan_w:20210923120720p:plain

 ゲームプレイアビリティエフェクトの修正(GE_PotionHealthRegen)
f:id:toncrimentan_w:20210923120905p:plain

・プレイしてみると
 無事、徐々に回復するリジェネポーションを作成することができました。
f:id:toncrimentan_w:20210923121007p:plain



実際にできたもの
youtu.be



こちらのコースでは
データアセット、ゲームプレイアビリティ、
といった中級者向けの機能について学ぶことができます。

そのため紹介程度で、
このコースを受講し、いざ実際に使ってみたい方は自分で調べてね!
といった内容になります。
自力で調べつつも作成することができるプログラマ向けの内容となります。

オンラインラーニングの内容をシェアするときは、
ぜひ #LearnUnreal タグを利用してほしい。とのこと。

UE4:オンラインラーニング(ブループリント ランタイムの保存とロード)

UE4オンラインラーニング
ブループリント ランタイムの保存とロード
を受講した際のおぼえ書きです。

https://learn.unrealengine.com/course/3766083


・セーブ方法
Create Save Game Objectでセーブデータを作成し
Save Game to Slot で保存することができます。
f:id:toncrimentan_w:20210923020116p:plain


・ロード方法
Does Save Game Existでセーブデータの有無を判別し
Load Game from Slot で読み込むことができます。
f:id:toncrimentan_w:20210923020202p:plain


・削除方法
Delete Game in Slotでセーブデータを削除することができます。
f:id:toncrimentan_w:20210923020237p:plain


・GUID
GUIDはユニークなIDになります。

ユニークなIDを利用することで、
コンティニュー時に、入手済みの配置物をポップさせない等の識別することに役立てることができます。
なんて天才的な方法なんだとおもいました!

以下は、コンストラクションスクリプト
ユニークなIDが未設定に場合に、NewGuidノードを利用し、
ユニークなIDを取得している例です。

ユニークIDを利用し、セーブロードをうまいこと作っていきましょう!
f:id:toncrimentan_w:20210923020302p:plain


・クラスのデフォルト値
Get Class Defaults を利用することで
クラスのデフォルト値を取得できます。
f:id:toncrimentan_w:20210923020422p:plain


こちらのコースを受講することで
基本的なセーブ、ロードの手法を理解できるだけでなく、
GUIDというユニークなIDを利用することで、
コンティニュー時に取得済みの配置物をポップさせないなどの処理を作成するテクニックを学ぶことができる、素晴らしいコースです。

UE4:太陽の向きの指定方法

基礎的なことかもしれませんが、
太陽の向きの指定方法のおぼえ書きです。


ディレクショナルライトの向きに応じて
対応の位置を変更することができます。


まず、空のレベルにディレクショナルライトを配置
f:id:toncrimentan_w:20210921023643p:plain


つづいて、スカイ環境を配置
f:id:toncrimentan_w:20210921023746p:plain


ディレクショナルライトのAtmosphere Sun Lightを有効にすると空が表示される
f:id:toncrimentan_w:20210921023847p:plain


あとは、ディレクショナルライトの向きを変えてあげれば
太陽の位置を変更することができます。
f:id:toncrimentan_w:20210921024011p:plain


おしまい。



参考)
UE4オンラインラーニング、初めてのUnrealEngine4
https://learn.unrealengine.com/course/3763910

UE4:第16回UE4ぷちコンに応募しました。

今回もヒストリア様で行われている
UE4ぷちコンに応募しました!
https://historia.co.jp/ue4petitcon16



今回の募集テーマは「みち」ということで、
エンドレスランナー系応募が多い中、ランナー系ゲームを作りました。
f:id:toncrimentan_w:20210920164553j:plain


タイトルは
「真夏のドライビングホリデー -Once Again- 2ndSeason」です。
youtu.be



最初は全く別の作品をつくっていたんです。
たとえばこんな感じの作品。
youtu.be
全く違う作品ですねぇ~


テーマは「みち」なんだから道歩くやつ、
それだけではすぐ飽きて別のをつくりたくなりました。


さて最近は、作品を色々作ろうとしても最後までやり遂げることができず。
途中で辞めちゃうことが多かったです。
でもつまらなくてもいい、納期まで仕上げるんだ!
を目標になんとか無事にやりきることができました。



このゲームの特色は2つ
コース生成 と ダイナミックなカメラワークを実現するためのカメラシステムです。



コース生成について
このように美しいカーブを描いた1本のメッシュデータで構成されています。
f:id:toncrimentan_w:20210920164836p:plain

まず、処理的には、ヒストリアさんのブログ、基本はコレをマネました。
https://historia.co.jp/archives/21842/


そのままやっても美しい曲線にならなかったので
凸凹しないようにもっと細かく割ったりしています。


そして、
道だけではなく壁も作っています。
※実際には透明な壁が存在します。落ちないように
 空洞の中を走っている感じになってるんですねぇ~
f:id:toncrimentan_w:20210920170022p:plain


道については
おわかりいただけるだろうか、
多少お椀型にサイドに膨れ上がっているメッシュをあるくようになっています。
f:id:toncrimentan_w:20210920170333p:plain




カメラシステムについて
こちらがカメラデータ、
サンプリング用のパス、カメラ座標用パス、カメラ注視点用パスを作成し、
キャラクターの位置に一番近いサンプリングパス上の割合を求め、
割合から、カメラ座標用パス上の位置、カメラ注視点用の注視点をもとめ
ダイナミックなカメラワークを実現しています。
f:id:toncrimentan_w:20210920232411p:plain



私が気づいたこと!
下り道ではキャラクターになるべくカメラを近づけ、
地表ギリギリで走ってる感を出すと、疾走感がでます!

下り前、俯瞰カメラ
f:id:toncrimentan_w:20210920170948p:plain

下り中、寝かせてキャラに寄ったカメラ
うぉ~!!
f:id:toncrimentan_w:20210920170906p:plain



時間を入力することで
実行前でも、どのようなカメラが実現されるか確認できる環境を作りました。
(これもUE4のコンストラクションスクリプトのおかげ)
f:id:toncrimentan_w:20210920232625p:plain



これだけ、カメラが動くと操作も難しいので
左スティックではなく、ボタン入力で前進。
レースゲームのような操作方法にしました。
SetControlRotationを利用することで、矢印の向きが前になるようにしました。
これで操作も多少は楽に!
f:id:toncrimentan_w:20210920223739p:plain




エフェクトについて
買ってきた素材の不要な部分を削除して利用してます(笑)
わたしはエフェクトつかえません!
f:id:toncrimentan_w:20210920222740p:plain



以上が、
第16回UE4ぷちコンの振り返りです。
しばらく、最後までやり遂げることが少なかったので、
ひさしぶりに最後まで作ることができて良かった!

面白くなくていい!納期を守ろう!

UE4:オンラインラーニング(ゲームデザイナーのためのブループリントとゲームプレイ)

UE5オンラインラーニング
ゲームデザイナーのためのブループリントとゲームプレイ
を受講した際のおぼえ書きです。

https://learn.unrealengine.com/course/3751483


コンテンツブラウザから検索時のショートカット)
アクタを選択し、Ctrl + B を入力することで
選択中のアクタのブループリントを、コンテンツブラウザから選択できます。
f:id:toncrimentan_w:20210920152133p:plain


変数参照を配置する際のショートカット)
変数の参照をBPにドラッグ配置する際
Ctrl + ドラッグで自動的にGet
Alt + ドラッグで自動的にSetになります。
f:id:toncrimentan_w:20210920152208p:plain


インスタンス編集の許可)
変数の横の目のマークを有効にすると、
レベル上で編集が可能な状態になります。
f:id:toncrimentan_w:20210920152350p:plain


レベル上での変更をブループリントに反映させる方法)
レベルから
ブループリントを編集>インスタンス変更をブループリントに適応
をクリックすることで、
レベル上での指定をブループリントに反映することができます。
(逆にこの機能があると危ないかも・・)
f:id:toncrimentan_w:20210920152620p:plain


インプットの追加方法)
入力を追加したい場合は、
プロジェクト設定>インプット>アクションマッピングの+印から追加
f:id:toncrimentan_w:20210920152714p:plain


タイムライン制御)
タイムラインではポイントを選択>ユーザー
をチェックすることで画像のように
スムーズに保管するよう調整することができます。
f:id:toncrimentan_w:20210920152810p:plain


ポストプロセス)
ポストプロセスコンポーネントをキャラごとにつけることもできます。

彩度をゼロにするポストプロセスを作っておき。
HPが下がることで再度を下げる表現を作成することができます。

・PostProcessコンポーネントを追加
・ポストプロセスボリューム>ColorGrading>Global>彩度
 で彩度を変更できます。
f:id:toncrimentan_w:20210920153346p:plain

たとえば、こんな風になります。
f:id:toncrimentan_w:20210920153151p:plain


MapRamgeClampedノード)
2つの間の値を、別の2つの間の値に変換できる便利関数です。

図は0~100のHPを入力すると
70~20にかけてポストエフェクトのブレンド割合に変換する処理です。
f:id:toncrimentan_w:20210920153503p:plain


オーバーラップイベントの有効化方法)
ボックスのGenerateOverlapEventsを有効にし、
ボックスをスイッチ倒し、扉が開くとかできます。
f:id:toncrimentan_w:20210920154115p:plain

f:id:toncrimentan_w:20210920154254p:plain



オーバーラップ中アクターの取得方法)
GetOverlappingActorsを利用することで、
オーバーラップ中のアクターリストを取得できます。
(これは便利! いままでしりませんでした、自分で配列を作るところでした!!)
f:id:toncrimentan_w:20210920154425p:plain


入力の有効化、無効化)
配置した、ドアBPのEnableInput、DisbleInputを切り替えることで、
ドアBPでのインタラクトイベントを有効にすることができます。
f:id:toncrimentan_w:20210920154828p:plain



インターフェイスでドアを開く方法)
・あらかじめ、ブループリントインターフェイスを作っておく。
 関数名はInteract
f:id:toncrimentan_w:20210920154954p:plain

・ドアのBPではインターフェイスを追加し
 Interactイベントが呼ばれた際の処理を作っておく
f:id:toncrimentan_w:20210920155236p:plain

・キャラクターBPでは
 レイ判定の末、ヒットしたアクタに対して
 Interactインターフェイスを呼び出すようにする。
f:id:toncrimentan_w:20210920155416p:plain

・無事、画像のようにプレイヤーから
 インターフェイスを利用し対象ドアを開く処理を作ることができた。
f:id:toncrimentan_w:20210920155528p:plain


インターフェイスの有無判定)
特定のインターフェイスを持っているかどうかは
DoseImplementInerfaceノードを利用する。
持っているか否かを判別したのち、インターフェイスを呼び出す。
f:id:toncrimentan_w:20210920155641p:plain


コリジョンTIPS)
一人称ゲームの唯一のコリジョンのみ有効にしたい場合は
OverlapOnlyPawnを利用する。
f:id:toncrimentan_w:20210920155748p:plain


成果物)
youtu.be



移動速度の変更など、
最初はかなり簡単すぎる内容からはじまります。
4種のドアの実装方法を通じ、学習する内容は非常に有益です。
近づいたら開くドア、
スイッチを押したら開くドア、
インタラクションしたら開くドア、
キャラからのインターフェイスを通じて開くドア
どれもUE4の基礎的に覚えておかなくてはならない内容です。