
UE5でTypeScriptを用いてキャラクターを動かす
はじめに
こんにちは、Santa Sunrise Inc.でもUnrealEngineのエンジニア?をしているみずあめです。(この記事はPowerd By Santa Sunrise Inc.です ) 今回はBlueprintでなく、C++でもなく、TypeScriptでキャラクターを動かしてみたいと思います。
現在LLMが発達しており、UnityC#であればゴリゴリに支援を受けられます。 ですがUEのBlueprintはGUIベースであり、いくらマルチモーダルなLLMであろうと、これでコーディングさせるのは無理があります。 しかし、RustやC++などの低級な言語を書かせた感想としては、まだ厳しいものを感じます。
そう、つまりスクリプト言語、かつコードベースの言語がUEに求められているわけです(?)
ここで今回ご紹介するTypeScriptで動かそうと言う話になります。
PureTSを使用
https://github.com/Tencent/puerts
あのテンセントが開発している、Unity/UnrealをTypeScriptで書けるようにしてくれるプラグインです。
頻繁に更新されており、UE4.22辺りから最新の5.5までサポートされています。
何が起きているのか?
以下は自分も理解が出来てない部分が多々あります。間違ってたらごめんなさい。
まずC++自体にリフレクションというシステムは無いはずなのですが、UnrealEngineは
UCLASS() USTRUCT() UENUM()
のメタ情報を付与することにより、リフレクションを生成できるようにしているみたいです。
UObject::ProcessEvent
そして任意の関数を呼び出せます。
https://qiita.com/unknown_ds/items/30ea13c9d50f2c2de6ff
PureTSではtsの型定義を生成してくれるのと、V8/QuickJS/Node.jsとのバインディングレイヤーを提供してくれます。
リフレクションを元にバインディングする場合、パフォーマンスが疑問になりますが、
https://github.com/Tencent/puerts/tree/master/unreal
十分実用的な感じらしいです。
使っていく
リリースから適切なバージョンを選んでください。
UE5.2の場合はUnreal_v1.0.5が動きました。 https://github.com/Tencent/puerts/releases/tag/Unreal_v1.0.5
通常のPluginのように配置します。 プロジェクトのC++化が必要です。
型定義ファイルを作成
Puerts.Gen
をコマンドで実行するか、
エディターのボタンを押すと、
Plugins\Puerts\Typing\ue
に
"ue.d.ts"
"puerts.d.ts"
この2つの型定義ファイルがエクスポートされていると思います。
ファイルを設置
MyProject/
├── Config/
├── Content/
├── Source/
├── TypeScript/
└── MyProject.uproject
プロジェクトのルートにTypeScriptファイルを作り、上記2つのファイルを配置します。 任意のコードエディターで型が認識されているか確認します。
モード変更
Plugins\Puerts
で
node enable_puerts_module.js
コマンドを実行します。
ルートに
tsconfig.json
jsonファイルが生成されているか確認します。
設定変更
"skipLibCheck": true,
をtsconfig.jsonに加筆します。
コードを書く
先ほど作ったTypingフォルダーに実際に書いていきます。 かけたらtscコマンドでtsをjsにトランスパイルします。 この際、jsは
Content\JavaScript
に同じ名前で配置されます。 この時、
- import * as UE from ‘ue’; で始まってる
- ファイル名とクラス名が一致してる
- export default クラス名;で終わってる
この3つを満たさないと、エディター上では認識されません。
import * as UE from 'ue';
class TS_Character extends UE.Character {
SpringArm: UE.SpringArmComponent;
Camera: UE.CameraComponent;
WalkSpeed: number = 600.0;
MouseSensitivity: number = 1.0;
Constructor() {
// キャラクターの移動設定
this.bUseControllerRotationPitch = false;
this.bUseControllerRotationYaw = false;
this.bUseControllerRotationRoll = false;
this.CharacterMovement.bOrientRotationToMovement = true;
this.CharacterMovement.RotationRate = new UE.Rotator(0.0, 540.0, 0.0);
this.CharacterMovement.MaxWalkSpeed = this.WalkSpeed;
this.SpringArm = this.CreateDefaultSubobject(
"SpringArm",
UE.SpringArmComponent.StaticClass(),
UE.SpringArmComponent.StaticClass(),
true,
false
) as UE.SpringArmComponent;
this.SpringArm.SetupAttachment(this.RootComponent, "");
this.SpringArm.TargetArmLength = 300.0;
this.SpringArm.bUsePawnControlRotation = true;
// カメラのセットアップ
this.Camera = this.CreateDefaultSubobject(
"Camera",
UE.CameraComponent.StaticClass(),
UE.CameraComponent.StaticClass(),
true,
false
) as UE.CameraComponent;
this.Camera.SetupAttachment(this.SpringArm, "");
this.Camera.bUsePawnControlRotation = false;
}
// ゲーム開始時に呼ばれる
ReceiveBeginPlay(): void {
super.ReceiveBeginPlay();
}
MoveForward(Value: number): void {
if (Value != 0.0 && this.Controller) {
const Rotation = this.Controller.GetControlRotation();
const YawRotation = new UE.Rotator(0, Rotation.Yaw, 0);
const Direction = UE.KismetMathLibrary.GetForwardVector(YawRotation);
this.AddMovementInput(Direction, Value);
}
}
MoveRight(Value: number): void {
if (Value != 0.0 && this.Controller) {
const Rotation = this.Controller.GetControlRotation();
const YawRotation = new UE.Rotator(0, Rotation.Yaw, 0);
const Direction = UE.KismetMathLibrary.GetRightVector(YawRotation);
this.AddMovementInput(Direction, Value);
}
}
}
export default TS_Character;
使えるメソッド名や書き方はシンタックスハイライトやLSPを元に気合を入れて書きます。
LLMもある程度は当てになりますが、全然嘘を言うので、直す必要があります。
実行
tscでトランスパイルをしたら、エディターで認識されるか見てみましょう。
上手くいけば認識されているはずです。
結果
https://x.com/mizuameisgod/status/1907809617851343291
まとめ
いかがだったでしょうか?
UnrealC++をLLMで書かせるのはちょっと厳しいしなーと思っていた中、TypeScriptなら割と書いてくれるので、あとはドメイン知識を何らかの方法(ex.コンテキストウィンドウ、ファインチューニング)で突っ込んであげれば、割と実用的な可能性も感じています。
ですが現在はまだ、ユーザーにもtsとUnrealと一部C++の知識が求められる状態と言えそうです。