技術書典4で頒布したUE4 C++ 同人誌の電子版を販売開始しました
Twitterのみでしか宣伝しておりませんでしたので、こちらでも宣伝します。 技術書典4にて物理本で頒布したUnreal C++本のPDF電子版の販売をBoothにて行っております。 本文132ページ、1200円です。
(紹介文より抜粋) UE4でゲーム開発をしようとするときに、どうやってUnreal C++メインで実装していくのかをステップバイステップで解説します。UE4のバージョンは4.19で動作確認しております。(物理本を初頒布時の最新版です)
コンポーネントの追加、アクター生成、当たり判定、デリゲート、入力、UI(UMG)などゲーム制作における基本を作る方法を、簡単なシューティングゲームを題材に詰め込みました。 ※必要な機能を可能な限りUnrealC++で実装してみるという内容であり、ゲームは完成しませんのでご注意ください。
ObjectInitializer.CreateDefaultSubobject、ConstructorHelpers::FObjectFinder、ConstructorHelpers::FClassFinder、TSubclassOf、CODなど気になる単語がありましたら読んでみると役に立つかもしれません。 タイトルが悪かったのか、『UnrealC++ 本』だったり、『UE4 C++ 本』とかで検索しても出てこなかったので、これで少しググラビリティ上がるといいなと思いつつ宣伝エントリを書きました。 もしご興味があればご購入していただけると増補改訂版や続編とか、UE4関連同人誌が今後出るかもしれません。
よろしくお願いしますー。
UE4 Outerについて調査してみた
この記事はUnreal Engine 4 (UE4) Advent Calendar 2018の12日目の記事です。
Outer?
Unreal C++を書いていると、Outerというキーワードに遭遇します。これは NewObject
の引数に存在したり、かなりクラス基底部分の UObjectBase::GetOuter
関数にも存在します。
今回、このOuterについて調べてみました。
まずはコードのコメントを読んでみる
Outerのコメントを見ると、『Object thier object resides in.(このオブジェクトが存在するオブジェクト)』と説明されております。 つまりOuterは、俗にいうOwner、そのオブジェクトの親を示している……?でもActorにはOwnerというのが別に存在しているけど……?
では実際はどうなのか、例から実際の動作を見ていきましょう。
ActorのOuter
テストコードは次のような単純なものです。
void AMyActor::BeginPlay() { Super::BeginPlay(); UObject* CurrentOuter = GetOuter(); while (CurrentOuter != nullptr) { UE_LOG(LogTemp, Warning, TEXT("Outer:%s"), *CurrentOuter->GetName()) CurrentOuter = CurrentOuter->GetOuter(); } }
ThirdPersonExampleに自分で作ったActorを継承したBlueprintをレベルに置き、実行してみます。 結果、そのActorのOuterを辿っていくと次のようになります。
MyActor AActor
┗PersistentLevel(MyActor->GetOuter) == ULevel
┗ThirdPersonExampleMap(PersistentLevel->GetOuter) == UWorld
┗/Game/ThirdPersonBP/Maps/ThirdPersonExampleMap(PIEだと名前変わります) == UPackage
MyActorはPersistentLevelに作られ、PersistentLevelはThirdPersonExampleMapに作られ……といった流れになっています。 しかし、ThirdPersonExampleMapが/Game/ThirdPersonBP/Maps/ThirdPersonExampleMapに作られたと考えるのは少し違和感を感じます。 /Game/ThirdPersonBP/Maps/ThirdPersonExampleMapはUPackageなのでアセット(ファイル)なのだから、ファイル自体から作られるのではなく、他の関数から読み込まれて作られそうなイメージがあります。
なので、Outerは誰に作られたかというよりも、何によって作られたかと考えるのがしっくりくるかもしれません。
また、UObjectBaseUtilityには GetOutermost
という関数もありますが、これは存在する一番上の親を取得する関数です。
つまり、さきほどのMyActorで GetOutermost
関数を呼ぶと、/Game/ThirdPersonBP/Maps/ThirdPersonExampleMapのUPackageが取得できます。
LoadObjectのOuter
次に、 LoadObject<USkeletalMesh>(this, TEXT("/Game/Mannequin/Character/Mesh/SK_Mannequin.SK_Mannequin"))
したUObjectのOuterを辿った場合は以下のとおりです。
/Game/Mannequin/Character/Mesh/SK_Mannequin UPackage
というように、 LoadObject
したオブジェクトのOuterはUPackageのみでした。さきほどとは違って、 LoadObject
を呼んだときに引数に渡したUObjectのポインタ this
がOuterに含まれておりませんでした。
ソースコードを読んでみると、どうやら LoadObject
関数の引数のOuterは、オブジェクトの読み込み・既に読み込まれているかどうかの検索先の絞り込みの判断に使われるようです。
他にも、ActorとActorComponentは乗っているLevelのアセット、 LoadObject
したUObjectではそれの元となるアセットがOuterの終点になるようです。
NewObjectのOuter
では通常の NewObject
したUObjectの場合にはどうなるでしょうか。
NewObject
テンプレート関数は、最初の引数でOuterオブジェクトを指定します。
こちらにNULLを渡した場合、TransientPackageと呼ばれるものがOuterに設定されるようです。そして、オーバーロードされている実装には、デフォルト引数で GetTransientPackage
関数が指定されているものが存在します。
これによりグローバル変数で持っている静的なUPackageとして存在しているTransientPackageがOuterとしてデフォルト引数で渡されます。
実際に NewObject<UObject>()
として関数を呼び出したときのOuterは、/Engine/Transient(UPackage)が表示されます。
Transientとは一時的という意味で、プログラム内で一時的なものとして作られたという意味で指定されているものだと思われます。UPROPERTYにもオプションでありますね。
ちなみに、 NewObject
のOuter引数にNULLではなく、MyActorの this
を渡した場合には次のようになりました。
Object_0
┗MyActor(BuleprintでWorldに置いた場合には、Blueprint名になる)
┗PersistentLevel(MyActor->GetOuter)
┗ThirdPersonExampleMap(PersistentLevel->GetOuter)
┗/Game/ThirdPersonBP/Maps/ThirdPersonExampleMap(PIEだと名前変わります)
Outerのまとめ
Outerは派生クラスによって取得できるものが変わることがわかりました。
では最後にまとめてみると、Outerの終点(Outermost)は次のようになるようです。
- ActorとActorComponentはSpawnした先のLevelのアセット
- LoadObjectしたUObjectではロード先のデータアセット
- NewObject関数経由の場合は、引数Outerに渡したものにより変化します
- 実行中にしか作成されない一時的なものはTransientPackageがOuterに指定されます
Outerを理解して、さらにUnreal C++を便利に使っていきましょう。
・宣伝
最近はVTuberが熱い、ということでバ美肉しました。セルフ受肉です。
UE4の動画もやるかもしれませんので、よろしければよろしくお願いします。
というわけで、明日はVTuber繋がり(?)の水瀬ツバキちゃんおかずさんの『UE4 & iOS開発時のデバッグ・プロファイリング方法 まとめ 2018』です。
いつもお世話になっております。
UnitychanToonShader2.0かわいい
ユニティちゃんトゥーンシェーダーVer.2.0が発表されました。
シェーダーのダウンロードはこちらから。 unity-chan.com
この記事は、そのUnitychanToonShader2.0について解説していただいた、ntnyさんの配信の個人的メモです。 動画を観るとUnitychanToonShader2.0の使い方がわかります。
間違って書いてしまっている部分とかもあるかもしれませんが、そこはご了承ください。 また、何か問題があればTwitterなどで連絡ください。
こちらもどうぞ。
アウトラインなしシェーダー
アウトラインなしにしたい場合は、UnityChanToonShader->NoOutlineの中に同様のフォルダがあるのでその中のシェーダーを選択する。
天使の輪っかが欲しい(AngelRing)
アウトライン有りはUnityChanToonShader->AngelRing。 動画ではアウトラインなしの、UnityChanToonShader->NoOutline->AngelRing->ToonShadingGradeMapを使用。 目に髪の毛や眉毛を透過させたいといった場合には、ToonShadingGradeMap_StencilMaskとToonShadingGradeMap_StencilOutを使うことで対応できる。
HighColor_Powerが従来のハイライトの値。 これだと描いている感じがしない場合、AngelRingの機能を使用する。
AngelRingのチェックを付ける。 このままだと何もおきない。 AngelRingを使うには、uv2というものを作る必要がある。
通常のモデルに貼り付けるテクスチャがuv1。 ハイライトを制御するのがuv2である。
uv2の作り方
今回はメタセコイヤでuvの値が入った髪の毛モデルを残して、FBXで出力。
メタセコイヤでは法線が調整できないので、他のDCCツールを使って、uv2を作る。
- ntnyさん「メタセコの水野さん(?)見てくれないかな~どれだけ法線調整が大切か知ってくれないかな~(チラチラ)」
今回は3DSMAXを使って法線を調整する。 AngelRingは法線の影響が大きいので、まずは法線を調整する。
UVは平面投影でやる。 描いたハイライトが、そのまま平面投影される形になる。 テクスチャに描いた色も反映されるけど、シェーダー側で設定できる。
次にMaya。 FBX吐き出すだけ。Unity上で合うnamespaceになるからいいらしい。 Mayaで法線調整できる人はMayaでもいい。
UnityでUnityちゃんの髪の毛を消す。 先程吐き出した髪の毛をアタッチする。
シェーダーをいじる
BaseColor、1st_ShadeColorで色のみをつけられる。 2nd_ShadeColor(2影)制御が難しいので、もう一声欲しい人が使うといい。(最初はおすすめしない) 基本は2nd_ShadeColor_Stepを0にして切っておいて、1陰のみで調整したほうが後で2陰が役に立つ。 まず2陰は背景照り返し用に使うといった運用がいいらしい。
ハイライトを当てる
AngelRingを有効にして、 AngelRing_Samplerにテクスチャを適用すると、AngelRingが出る。 AR_OffsetUとAR_OffsetVのARはAngelRingの略。 AR_OffsetVの値が入ると、縦方向に動かしてもベタ貼りっぽくなく見せられる。
AR_OffsetV値が0の時。
AR_OffsetV値が0以上の時。
注意点。uv2は光源に追従しない。
質問コーナー
Q:水で濡れたような表現も可能ですか?
テカテカにしたいんだったら、通常のシェーダー使った方がいいのでは?
Q:凸凹関係なく輪っかがすっと入れることができるということですか?
概ね合っているのですが、法線に影響は受けてしまうので、調整しないと陰がバキバキになってしまう。 法線は調整しましょう。 左が法線調整済み。右が調整前。濃い陰に注目。
アウトライン
法線押出でやっていると、目の凹んでいる部分が鬱陶しい。
Outline_Samplerを使うとモノクロマップでアウトラインを消せる。 黒いところが消える。Ver1でも使える。 (動画では白目部分を黒くのを忘れて苦戦していた)
Farthest_DistanceとNearest_Distanceは、カメラの距離に応じて線の太さが変わるオプション。
GradeMap
NormalMapを使わずに、いい感じに影を落とせるようになる。 NormalMapよりもアバウトに作れるので、描いた絵っぽくなる。 髪の毛とか、服のしわとか。
Cull Mode
カリングモード。 OFFにすると両面。FRONTで前が見えなくなる。BACKは後ろが見えなくなる。
Tweak_SystemShade
落影の強さを調整できる。 1st_ShadeColor_Stepとセットで調整する。 凄い表現力が変わるのでおすすめとのこと。
ブラシっぽい表現をする
1st_ShadeColor_Featherの値をいじると可能。
2陰を使うと、色の違う陰を使う表現ができる
紫を陰に使うような表現ができる。
トゥーン表現小技
凹凸を無視して影を落としたいとき、影専用の見えない板を用意する。 3DObjectのPlaneをアタッチする。Shadow Onlyにし、Layerを適用にしたいものにすればOK。 CullingMaskをNothingにしてから、適用したいものだけにすれば、専用の光源になる。
カメラ近づけると歪んじゃうときに便利なスクリプト
UnityはSceneのFov値を調整できない。
それを調整できるようにしたのが、Matsuokaさんが作ってくれた、Release Experimental Release (0.1.9) · t-mat/UnitySceneViewFovControl · GitHubが便利。
先ほどの配信で使ったSceneViewでFovを調整出来る松岡氏によるスーパースクリプトはコチラです!(・ω・)/Assets/Editor/に入れてAlt+Ctrl(+Shift)ホイールで動作しますよ!#unity3d https://t.co/JN3ys4fPlM
— ntny (@nD_ntny) 2017年5月12日