![見出し画像](https://assets.st-note.com/production/uploads/images/118749899/rectangle_large_type_2_3454489b0be1e405c2c3b41ec9b2e45f.png?width=1200)
[UEFN&Verse]オリジナルの敵を出す
今回はオリジナルの敵キャラクターを作ってみる
近づくと寄ってきて攻撃してくるモンスターだ
プロジェクトの準備
UEFNを起動してプロジェクトを作成する
テンプレートは何でも良いし、新規に作らなくても既にあるプロジェクト上でも良い
今回はTestProject003という名前で島テンプレートのBlankを指定している
![](https://assets.st-note.com/img/1697106306026-GCOW8vUoOc.png?width=1200)
モデルを登録する
まずは敵のデータを用意する必要がある
大したものではないが今回使うデータを用意した
内訳はこのようになっている
slime.fbx 敵モデル
slime.png 敵モデルテクスチャ
idle.fbx アイドル時のアニメーション
walk.fbx 移動時のアニメーション
コンテンツブラウザを開き All > TestProject003コンテンツ の下にslimeというフォルダ作成、その中に解凍したslime.fbxをドラッグする
![](https://assets.st-note.com/img/1697106478768-o6jNgPstPm.png?width=1200)
こんな画面が開くので
![](https://assets.st-note.com/img/1697107707592-voEpS8ahss.png)
Import Animatinsのチェックだけ外して[インポート]する
![](https://assets.st-note.com/img/1697107738651-AdS6zxAVc8.png)
こんな感じでいろいろインポートされる
マテリアル、ボーン、テクスチャ、物理?、スケルタルメッシュだ
![](https://assets.st-note.com/img/1697107773231-yvkoEsDntK.png)
引き続きアニメーションデータのidle.fbx walk.fbxも[インポート]する
![](https://assets.st-note.com/img/1697107821333-7nWVKIH2OB.png?width=1200)
ブループリントを作成する
Slimeのブループリントを作成する
ブループリントとはモデルやコリジョンやライティングなどを組み合わせて一つの構造として扱うための仕組みだ
ブループリントを構築してシーンに配置しVerseで制御することでいろいろな挙動をさせることができる
コンテンツブラウザから All>TestProject003コンテンツ>slimeを右クリックしてブループリントクラスを選択する
![](https://assets.st-note.com/img/1697107900230-nnAILO1lwb.png?width=1200)
生成されたブループリントはslimeBPとリネームしておく
![](https://assets.st-note.com/img/1697107952116-z8i1di22Lb.png)
ダブルクリックするとこんなエディタが開く
![](https://assets.st-note.com/img/1697108155804-tWHpEj4FSx.png?width=1200)
まずはslimeのスケルタルメッシュをブループリントに登録する
コンポーネントタブにある[+追加]を押してSkeltal Meshを追加
![](https://assets.st-note.com/img/1697108203466-xRCsv6VMo3.png)
スケルタルメッシュはSlimeとリネームしておく
![](https://assets.st-note.com/img/1697108270759-fkynX7z4CX.png)
詳細タブの Skeltal MeshにSlimeスケルタルメッシュをセットする
ちなみにスケルタルメッシュとは内部に含まれたジョイントを使ってアニメーションをさせることができるメッシュのことだ
![](https://assets.st-note.com/img/1697108311912-KHuk3yIcmd.png)
次に Anim to Playにidleのアニメーションシーケンスをセットする
![](https://assets.st-note.com/img/1697108486547-Y5i9BI7KXI.png)
これでアイドリングするスライムのブループリントができる
![](https://assets.st-note.com/img/1697108517169-oDjgQ9mak7.png)
今のままでもslimeBPはシーンに配置することができるがまだコリジョンがないので素通りする
![](https://assets.st-note.com/img/1697109148159-BVFejyUk3x.png?width=1200)
コリジョンを設定する
次にSlimeBPにコリジョンを設定する
スケルタルメッシュにはコリジョン情報は含まれないのでコリジョン情報を持ったスタティックメッシュをSlimeBPに追加する必要がある
スタティックメッシュとはジョイントを含まないポリゴン情報だけのメッシュだ
スタティックメッシュはスケルタルメッシュから生成できる
slimeのスケルタルメッシュをダブルクリック
![](https://assets.st-note.com/img/1697109832007-oKBk31NgIB.png)
エディタが開くのでスタティックメッシュを作成を選択
![](https://assets.st-note.com/img/1697109934846-alCuT5w8Am.png?width=1200)
slimeフォルダを指定して名前はslimeStaticMeshとし[保存]
![](https://assets.st-note.com/img/1697109988263-7UShDCmnyz.png)
今度は生成されたslimeStaticMeshを開く
![](https://assets.st-note.com/img/1697110089537-gtkdhfFeX3.png?width=1200)
コリジョンを選び
![](https://assets.st-note.com/img/1697110204882-crqRco07dQ.png?width=1200)
18DPO単純化コリジョンを追加
URは様々なコリジョン形状を自動生成してくれるのでモデルにあったデータをその都度選択する
今回はシンプルなものを選んだ
![](https://assets.st-note.com/img/1697110249578-gqzr9BgwIP.png)
これでコリジョン情報を含んだスタティックメッシュを作ることができた
ビューポートにある表示から単純なコリジョンをチェックすると生成されたコリジョンを視認できる
![](https://assets.st-note.com/img/1697110360776-LXNUu1ML0x.png?width=1200)
このコリジョン付きのスタティックメッシュをslimeBPに追加することでコリジョンのあるslimeBPを作る
その前にもう一つ用意しておくものがある
コリジョン用のスタティックメッシュを生成したわけだが、必要なのはコリジョン情報だけなので、メッシュ本体を隠す方法が欲しい
そのための透明なマテリアルを作成してメッシュに適応する
コンテンツブラウザ上でAll > TestProject003 > slimeで右クリックしてマテリアルを選択する
![](https://assets.st-note.com/img/1697111365834-hVWk9KUZbD.png)
生成されたマテリアルはTransparentMatとリネームしておく
マテリアルをダブルクリックしてマテリアルエディターを開く
![](https://assets.st-note.com/img/1697111405834-85nU8zGNe2.png?width=1200)
まずは詳細タブのBlend ModeをTranslucentに変更する
![](https://assets.st-note.com/img/1697111469489-BGaNJhW4r6.png)
このあたりを右クリックして
![](https://assets.st-note.com/img/1697111545600-Aevr6IC0I2.png?width=1200)
Constantを追加する
続けてConstant3Vectorも追加する
![](https://assets.st-note.com/img/1697111526192-a50xqFD6Tl.png)
コンスタント3Vectorは白に変更し
コンスタントは0.0のままにして
それぞれをベースカラーとオパシティに接続する
![](https://assets.st-note.com/img/1697111595786-5AiyECmDo7.png)
これで必要なマテリアルは完成したのでマテリアルエディタはクローズする
ではSlimeBPにコリジョンのついたスタティックメッシュを登録する
再びコンテンツブラウザからSlimeBPをダブルクリックしてブループリントエディターを開く
コンポーネントタブでslimeを選択した状態で [+追加]
![](https://assets.st-note.com/img/1697111757700-kOMbiQwgTZ.png)
スタティックメッシュコンポーネントを選択する
![](https://assets.st-note.com/img/1697111789513-hBHC28gEwS.png)
slimeの下にStaticMesh1が追加される
StaticMesh1のスタティックメッシュにコリジョンがついたslimeStaticMeshを指定する
このままだと2体のスライムが重なったような見た目になるのでみにくい、とはいえ最終的に利用する透明のマテリアルを今適応してしまうと見えなくて作業がしにくい、ということでマテリアルには適当にM_Barrier_BoundsSolid_01を指定しておく
![](https://assets.st-note.com/img/1697138176025-NkhpLCw6fB.png?width=1200)
次にスタティックメッシュのすぐ上にある親ソケットを設定する
これでスケルタルメッシュの内部に含まれるジョイントに対して親子関係をつけることができる
![](https://assets.st-note.com/img/1697141567959-qRuXcIjX8u.png)
slimeスケルタルメッシュに含まれているジョイントがリストされるのでjoint1を選択する
![](https://assets.st-note.com/img/1697141645760-g3y2A3yjtD.png)
するとコリジョンモデルの軸がおかしくなるので
![](https://assets.st-note.com/img/1697141735666-R2DMKrxCHo.png)
もとに戻しておく
![](https://assets.st-note.com/img/1697141782566-yzJnlRP02E.png)
joint1にコリジョンをアタッチするとスライムをwalkモーションに切り替えたときよりモデルの動きにコリジョンがフィットしてくれる
アニメーションに合わせてこまかくコリジョンを指定する方法だ
![](https://assets.st-note.com/img/1697141833462-RuRrs2xlIq.png)
これでコリジョンの調整は完了したのでコリジョンモデルのマテリアルを先ほど作ったTransparentMatに変更し見えなくしてしまう
![](https://assets.st-note.com/img/1697142010283-frX2gVW8AJ.png)
動作確認すると上にも乗れるようになっている
![](https://assets.st-note.com/img/1697142288556-hbvlVk6Bhb.png?width=1200)
攻撃できるようにする
次はスライムを攻撃して破壊できるようにしたい
とりあえず何か武器がないと試せないので
All > Fortnite > Deviceの下にあるアイテムスポナーをシーンに配置する
![](https://assets.st-note.com/img/1697142495242-RmQPseIpfb.png?width=1200)
アイテムスポナーを機能させるにはスポーンさせたいアイテムのリストを登録する必要がある
シーンに配置したアイテムスポナーの詳細タブからアイテムリストの右にある+マークを押してリストを1つ追加する
追加したリストに含まれるスポーンするピックアップで武器を適当に選ぶ
![](https://assets.st-note.com/img/1697142719964-oue1wUhP2F.png)
ついでに、最初のスポーンまでの時間を0.0にしておくと良い
![](https://assets.st-note.com/img/1697142905223-fLsDKaI2Md.png)
攻撃能力は手に入れた
まだスライムに弾は当たるが倒せない
![](https://assets.st-note.com/img/1697143179266-2m2cGy9a9R.png?width=1200)
再びslimeBPのブループリントエディター画面を開く
slimeBPを選択した状態で詳細タブの検索欄にattrといれると属性を指定する場所がピックアップされる
この設定でslimeBPの基本ステータスを指定することができる
![](https://assets.st-note.com/img/1697143393667-yKwN2DBAKl.png?width=1200)
とりあえず敵っぽいカテゴリを選ぶ
インデックス[0]の初期化カテゴリをSoldierにセット
![](https://assets.st-note.com/img/1697143676451-82qeppzvsx.png)
初期化サブカテゴリにSoldier_Ability_R_T1を選ぶ
![](https://assets.st-note.com/img/1697143928058-bzh8OZWMjs.png)
インデックス[1]にも全く同じ設定をいれる
![](https://assets.st-note.com/img/1697144014117-pi1V7b9doC.png)
なぜ2つあるのか不明もう少し調べる必要がある
設定するとでSoldier_Ability_R_T1の属性がslimeBPに付与され攻撃が当たるようになる
![](https://assets.st-note.com/img/1697144265699-gZ3BeuShSI.png)
触るとダメージを受けるようにする
All > Fortnite > Deviceの下にある ダメージボリューム を使う
![](https://assets.st-note.com/img/1697144606866-fO9bn0KUXO.png?width=1200)
ダメージボリュームを図のようにスライムの足元に配置し
ユーザーオプションからボリュームの大きさやダメージ量などを調整する
![](https://assets.st-note.com/img/1697144892099-e3pENijviO.png?width=1200)
スライムの移動にあわせてダメージボリュームも移動させる必要があるのでダメージボリュームをSlimeBPの子供にしておく
アウトライナーからダメージボリュームを右クリック→親子付け→slimeBPを選ぶ
![](https://assets.st-note.com/img/1697145014753-x7rqYTg5Ph.png?width=1200)
親子関係ができる
![](https://assets.st-note.com/img/1697145277636-dNtS0Cgdho.png)
触るとダメージを受けるようになる
![](https://assets.st-note.com/img/1697145436235-gQmElY4XSt.png?width=1200)
歩きアニメーションを登録する
敵キャラクターを動かすためには単にモーションを切り替えて座標を変更させればよいわけではなく、タイミング良くSEを鳴らしたりエフェクトを追加したりいろいろ調整が必要になる
それらを各モーションごとに設定するのがレベルシーケンスという機能だ
コンテンツブラウザからAll > TestProject003 > slimeフォルダを右クリックしシネマティックスの下のレベルシーケンスを選択する
![](https://assets.st-note.com/img/1697145555295-kw7mWBt4ZJ.png?width=1200)
slimeフォルダにこんなのが追加されるのでwalkSeqとリネームしておく
![](https://assets.st-note.com/img/1697145580214-GynnUlE5gZ.png)
で、これをダブルクリックするとシーケンサータブが表示される
![](https://assets.st-note.com/img/1697145633685-eJkhrM45Sv.png?width=1200)
シーケンサーにSlimeBPのためのトラックを追加してwalkモーションを登録する
最初にタイムスライダの位置が0になっていることを確認してからシーケンサーの [+トラックを]押してシーケンサへのアクタからslimeBPを見つけて選択する
![](https://assets.st-note.com/img/1697146078603-o4lh5VW1U0.png?width=1200)
シーケンサーにslimeBPトラックが追加される
![](https://assets.st-note.com/img/1697146101858-BkO6mTX0Vl.png?width=1200)
トラックの右にある+ボタンを押してアニメーションからwalkを選択する
![](https://assets.st-note.com/img/1697146240453-TXPMM48u9j.png?width=1200)
ここで左下にある再生ボタンを押すとシーン上でアニメーションを確認することができる
![](https://assets.st-note.com/img/1697146392991-17f4XftrCq.png?width=1200)
Walkモーションはちょうど1秒、30FPSだと30フレームの長さで作られているのでトラックの幅をそれに合わせる必要がある
右側に見える赤い 】を移動させて30に調整する
![](https://assets.st-note.com/img/1697146467828-K1vTCgZU1Z.png?width=1200)
あ、動かすまえにスナップボタンをONにしたほうがよい
![](https://assets.st-note.com/img/1697146491550-pKWXrb3XxA.png)
ほかにも様々な機能があるレベルシーケンスだが今回はこれだけで完成だ
作成したレベルシーケンスは他の仕掛けと同様にシーンに配置して利用するのだが直接シーンには配置できずムービーシーケンスの仕掛けを利用する
All > Fortnite > Deviceから探し出してシーンに配置
SlimeWalkSeqとリネームしておく
![](https://assets.st-note.com/img/1697147071504-RGrxnLVqwO.png?width=1200)
配置したムービーシーケンスの仕掛けのアウトライナー/詳細から
シーケンスにwalkSeqをセットする
![](https://assets.st-note.com/img/1697147285707-Dtndom8SZL.png)
歩かせる
スライムの移動プログラムを組む
まずVerseコードを追加、名前はslime_ai_deviceとする
![](https://assets.st-note.com/img/1697147522801-HNC4yv6Vze.png?width=1200)
Verseデバイスも忘れないうちにシーンに置いておこう
![](https://assets.st-note.com/img/1697151688842-xxPLrA6iyB.png?width=1200)
slime_ai_device.verseファイルを編集する
全コードがこんな感じ
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Fortnite.com/Characters }
using { /UnrealEngine.com/Temporary/SpatialMath}
slime_ai_device := class(creative_device):
@editable WalkCinema : cinematic_sequence_device = cinematic_sequence_device{}
@editable Slime : creative_prop = creative_prop{}
MoveSpeed : float = 0.02
OnBegin<override>()<suspends>:void=
loop:
MoveAnimation()
Sleep(0.1)
MoveAnimation()<suspends>:void=
AllPlayers := GetPlayspace().GetPlayers()
if (Player := AllPlayers[0], Agent := agent[Player], Fort := Agent.GetFortCharacter[]):
PropLocation := Slime.GetTransform().Translation
PlayerLocation := Fort.GetTransform().Translation
var Dist : float := Distance(PlayerLocation , PropLocation)
if (Dist < 1000.0):
WalkCinema.Play()
if (LookDirection := (PlayerLocation - PropLocation).MakeUnitVector[]):
Yaw := RadiansToDegrees(ArcTan(LookDirection.Y, LookDirection.X)) - 90.0
Pitch := 0.0
Roll := 0.0
NewRotation := MakeRotationFromYawPitchRollDegrees(Yaw, Pitch, Roll)
LerpLocation := Lerp(PropLocation, PlayerLocation, MoveSpeed)
FinalLocation := vector3 {X:= LerpLocation.X, Y:= LerpLocation.Y, Z:=0.0}
if:
Slime.TeleportTo[FinalLocation,NewRotation]
#Slime.MoveTo(PlayerLocation, NewRotation, 1.0)
ざっくりとコードを説明
cinematic_sequence_deviceはムービーシーケンスの仕掛け
creative_propはブループリント
シーンに配置したslimeWalkSetとslimeBPにアクセスするものだ
@editable WalkCinema : cinematic_sequence_device = cinematic_sequence_device{}
@editable Slime : creative_prop = creative_prop{}
OnBeginは初期化用のイベントハンドラだ
今回はこのなかに直接スライムの移動ルーチンが組み込んである
この手の初期化ハンドラはどんなシステムにもあるけど必要な処理を終えたら速やかにリターンさせるものだと思っていた
VerseのOnBeginはSleep()さえコールすればリターンしなくても良いらしい
OnBegin<override>()<suspends>:void=
loop:
MoveAnimation()
Sleep(0.1)
プレイヤーキャラのインスタンスを取得している
この処理は失敗する可能性があるのでif文の中で行う
Verseのプログラムで最初に不思議に思う部分だ
if文のくせに条件文が存在しないことがある
条件が成立するかしないか以外に処理が成功するかしないかでも分岐が発生する
AllPlayers := GetPlayspace().GetPlayers()
if (Player := AllPlayers[0], Agent := agent[Player], Fort := Agent.GetFortCharacter[]):
スライムとプレイヤーキャラ両方の位置を取得してその距離を計算している
距離が1000.0以下になると追いかけてくるようにしている
PropLocation := Slime.GetTransform().Translation
PlayerLocation := Fort.GetTransform().Translation
var Dist : float := Distance(PlayerLocation , PropLocation)
if (Dist < 1000.0):
歩きモーションを再生
WalkCinema.Play()
スライムからみたプレイヤーキャラの方向を法線ベクトルを計算しそれをオイラー角に変換しさらにRotationというフォーマットに変換しているRotationはクォータニオンなのかな
if (LookDirection := (PlayerLocation - PropLocation).MakeUnitVector[]):
Yaw := RadiansToDegrees(ArcTan(LookDirection.Y, LookDirection.X)) - 90.0
Pitch := 0.0
Roll := 0.0
NewRotation := MakeRotationFromYawPitchRollDegrees(Yaw, Pitch, Roll)
Leapは線形補間の関数だ
スライムがプレイヤーに方向にちょっとだけ進んだ位置を計算している
で計算した新しい位置と新しい向きをSlimeに設定して移動させている
LerpLocation := Lerp(PropLocation, PlayerLocation, MoveSpeed)
FinalLocation := vector3 {X:= LerpLocation.X, Y:= LerpLocation.Y, Z:=0.0}
if:
Slime.TeleportTo[FinalLocation,NewRotation]
コードをの編集が終わったらVersesコードをビルドする
ビルドが成功すればslime ai deviceに以下のパラメータが追加されるので
WalkCinemaにSlimeWalkSeq、SlimeにslimeBPを設定する
![](https://assets.st-note.com/img/1697153762476-QMo7iNXti2.png)
動作確認すると、スライムが動き出すようになった
![](https://assets.st-note.com/img/1697153795491-DvCUb9Cva4.png)
ひとまずやりたいことはできたが大量の敵をこの方法で出すのは大変だ
クリーチャースポナーも利用できないブループリントをVerseで動的に生成することもできない
今後はもう少し改善されるのだろうか?
この記事が気に入ったらサポートをしてみませんか?