背景
Verse書き始めた時に毎回creative_device
クラスを宣言してワールド常にいつものモニターが大量に存在してしまう状況があった。そこでふと思い出したのがUnityを使っている時にMonobehavior
を継承したクラスを作りすぎず必要なければピュアC#を使っていこうというお話だった。
creative_device ≒ Monobehavior
今回は設計について話すことはなく単純に純粋なクラスを使ってみるという記事になっています。
まず純粋なVerceクラスとは
いつものVerceコード
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
hello_world_device := class(creative_device):
var count : int = 0
OnBegin<override>()<suspends>:void=
loop:
Sleep(1.0)
set count += 1
Print("Hello World! Count: {count}")
このようにクラスの宣言時に(creative_device)
と宣言していますよね。このようにすることでワールド上に配置しなければならなくなります。
ピュアVerceコード
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
hello_world2_device := class:
var count : int = 0
OnInitial<public>()<suspends>:void=
loop:
Sleep(1.0)
set count += 1
Print("Hello World2! Count: {count}")
このように宣言することでデバイスを配置することなくクラスを作れます。
ピュアVerceコードはこれだけでは動きません。
純粋なVerceクラスの懸念点
- エントリーポイントがない
- @editable
がないためクラス内で直接別のVerceデバイスをいじれない
懸念点の解決方法
エントリーポイントがない件
OnBegin
メソッドのようにゲーム開始時に呼ばれるデバイスがないため別のcreative_device
でインスタンスを立ててそこで呼ぶことで解決できる。
以下がサンプルコード
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
call_hello_world2_device := class(creative_device):
hello_world2:hello_world2_device = hello_world2_device {}
OnBegin<override>()<suspends>:void=
hello_world2.OnInitial()
@editable
がないためクラス内で直接別のVerceデバイスをいじれない件
コンストラクタや通常のメソッドを立てて依存性の注入を行うことで解決ができます。
以下がサンプルコード
ピュアVerceコード
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
hello_world2_device := class:
OnInitial<public>(Trigger : trigger_device)<suspends>:void=
Trigger.TriggeredEvent.Subscribe(CallTrigger)
CallTrigger(QAgent : ?agent):void=
Print("Triggered!")
ピュアVerceコードに依存性を注入するクラス
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
call_hello_world2_device := class(creative_device):
@editable
Trigger:trigger_device = trigger_device {}
hello_world2:hello_world2_device = hello_world2_device {}
OnBegin<override>()<suspends>:void=
hello_world2.OnInitial(Trigger)
純粋なVerseクラスを利用することによるメリット
- パフォーマンスが上がる可能性がある?
- Verceのクラスを綺麗に分けることができ視認性が上がる
- 効率の良いコードが書ける
- より柔軟なコードが書ける
あとがき注意点
以下のようにcount
変数で何も初期値を指定しなかったらクラス宣言時にその値を指定して宣言する必要があります。
hello_world2_device := class:
var count : int
呼び出し側はこのようにする
call_hello_world2_device := class(creative_device):
# 初期化時に指定する変数名に値を代入する
hello_world2:hello_world2_device = hello_world2_device { count := 0 }
まとめ
Verceは最近できたプログラミング言語になるので誰かがこのような設計で書くべきだという提言が少ないのでその辺りをふかぼって自分なりの正解を探していきたいと思う。
余談
この度UEFN/Verseに関するオープンコミュニティサーバーを建ち上げました。ちょっとでも興味があれば奮ってご参加くださいませ。