
こんにちは私の名前はドミトリーです。 私は趣味としてアンリアルエンジンでコンピューターゲームを作っています。 私のゲームには手続き的に生成された世界がありますが、より興味深いレベルを作成するために、レベルの定義済みセクションを使用することにしました。 しかし、レベルが生成される領域と生成されない領域を設定する方法が問題になります。 これを行うために、独自の編集モードを作成しました。その作成について説明する猫の下に、記事の最後にあるソースコードを作成します。
それでは、新しい編集モードを作成することから始めましょう。
class FEdModeCustom : public FEdMode { public: FEdModeCustom(); ~FEdModeCustom(); virtual void Tick(FEditorViewportClient* ViewportClient,float DeltaTime) override;
EnterおよびExit-編集モードを開始および終了するときに呼び出されます。 編集モードに入ると、タブに表示されるモードインターフェイス要素を作成します。 これらの要素はファイルSCustomEdit.hで説明されていますが、ここでは引用しません。
InputKey-イベントが入力デバイスから受信されたときに呼び出されます。つまり、ボタンがクリックされ、IE_Pressedイベントを受信し、リリースされ、IE_Releasedを受信しました。
レンダリング-シーンを描画します。
IsSelectionAllowed-オブジェクトを選択できるかどうかを決定します。
ActorSelectionChangeNotify-選択がまだ発生した場合に呼び出されます
ShouldDrawWidget-ウィジェットをオブジェクトに描画するかどうかを決定します(ウィジェットは、選択したオブジェクトを移動すると表示される3つのカラフルな矢印のようなものです)。
InputDelta-マウスボタンの1つが押された場合、カメラが移動しないようにします。
利便性を高めるために、2つのツールを作成しました。 最初のツールはペイントです。これを使用して、レベルを生成する必要のないセルを選択します(Shiftはツールを反転します)。 2番目のツールは選択で、選択したセルにアイテムを配置できます。 各ツールには独自のRender()およびInputKey()メソッドがあり、対応する編集モードメソッドから呼び出します。
しかし、そのように、新しい編集モードは表示されません。 表示するには、StartupModule()メソッドに登録する必要があります。
void FLevelDrawEditorModule::StartupModule() { FCustomCommands::Register(); FEditorModeRegistry::Get().RegisterMode<FEdModeCustom> ( FEdModeCustom::EM_EdModeCustom, FText::FromString("Level Draw"), FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.ViewOptions", "LevelEditor.ViewOptions.Small"), true, 400 );
その後、ここにそのようなメニューがあります:

今最も重要なことは、受信した情報をどこかに保存することです。 情報はTestActオブジェクトに保存されます。 複数のTestActsがステージに配置されている場合は、ステージ上に配置する必要があります。アイコンをクリックすると、それらを切り替えることができます。
UCLASS() class LEVELDRAW_API ATestAct : public AActor { GENERATED_BODY() public: ATestAct(); UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gird) FVector GridCellSize; UPROPERTY(Transient) UModeSettings* ModeSettings; UPROPERTY() FLevelMap LevelMap; private_subobject: #if WITH_EDITORONLY_DATA UPROPERTY() UBillboardComponent* SpriteComponent; #endif
だから私たちが持っているもの:
GridCellSize-このパラメーターは、表示されるセルのサイズを決定します。
ModeSettings-このオブジェクトのパラメーターは、編集モードのプロパティパネルに表示されます。 グリッドを強調表示できる2つのポイントを設定し、特定のTestActの名前とデータを消去するボタンも表示します。
なぜ、このオブジェクトを編集モード自体ではなくTestActにアタッチしたのでしょうか? 実際には、編集モードは、切り替えたときにのみ「有効」になります。 そして、このオブジェクトを編集モードにアタッチする場合のみ。 その設定は、別のモードに切り替えるたびにリセットされます。
さらに、UModeSettingsオブジェクトへのポインターがUPROPERTY(一時的)として示されていることに気付くかもしれません。 Transientパラメーターは、保存ボタンがクリックされたときにエディターがUModeSettingsオブジェクトを保存できないようにします。 しかし、UPROPERTYの目的は何ですか?
重要: Unreal Egineには、このオブジェクトを指すUPROPERTYとして定義された単一のポインタがない場合、すべてのオブジェクトを削除するガベージコレクタがあります。 また、RF_RootSetフラグを使用してオブジェクトを保護できます。
YourObjectInstance->SetFlags(RF_RootSet);
もちろん、上記のすべてはUObjectから派生したオブジェクトにのみ適用されます。 オブジェクトがUObjectの子孫でない場合、ガベージコレクターはそれを脅かしません。
LevelMap-実際、このオブジェクトにはセルに関する情報が保存されます。 このオブジェクトは、平面の4分の1に1つずつ、4つの2次元配列で構成されています。 ここでは、マップを保存するためにボタンをクリックすると、FLevelMapオブジェクトが保存されるように、UPROPERTYパラメーターが既に必要です。
SpriteComponent-ATestActオブジェクトがマップ上に配置された場合にエディター画面に表示されるアイコンへの単なるリンク。
実際には、ソースを確認することをお勧めします。
ソースコードプロジェクトは こちらです。