LoginSignup
5
6

More than 1 year has passed since last update.

[UE4] PythonからプロジェクトのC++クラスへアクセスする方法

Posted at

検証バージョン:UE4.26.2, UE4.27.2

1. 概要

 Pythonを利用してEngineクラスにアクセスする方法は以下のドキュメントにあります。
https://docs.unrealengine.com/4.27/ja/ProductionPipelines/ScriptingAndAutomation/Python/

 本記事ではプロジェクトに作成したC++クラスの変数や関数にアクセスする例を示します。

2. 目標

 最終的にやりたいことは「コンテンツブラウザから選択した"C++クラス (AMyActor) を継承したBlueprintクラス (BP_MyActor) "に対してPython経由で変数をセットしたりネイティブ関数の呼び出しを行う」です。

【コンテンツブラウザ上の表示】
2021-12-21_03h25_23.png

【BP_MyActorの親クラスの内容】

MyActor.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

USTRUCT(BlueprintType)
struct FMyStruct
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    TArray<FVector> VecArray;
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    bool BoolValue;
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    float FloatValue;
};

UCLASS()
class MYPROJECT_API AMyActor : public AActor
{
    GENERATED_BODY()

public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    UStaticMesh* MyStaticMesh;
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    FMyStruct MyStruct;
    UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
    void TestFunction();
};
MyActor.cpp
#include "MyActor.h"

void AMyActor::TestFunction_Implementation()
{
    UE_LOG(LogTemp, Warning, TEXT("Call TestFunction"));
}

 最終的にBlueprintの変数は以下のようになることを期待するとします。

【設定前】
2021-12-21_02h56_22.png
【設定後】
2021-12-21_03h05_59.png

3. Python実装

 Pythonの実装は以下のようになります。

【前提】
・Plugin: Python Editor Script Pluginを有効にする
・Plugin: Editor Scripting Utilitiesを有効にする

Test.py
import unreal
import sys
import os

@unreal.uclass()
class MyEditorUtility(unreal.EditorUtilityLibrary):
    pass

# Content Browserで選択したアセットを検索
selected_assets = MyEditorUtility().get_selected_assets()
for i, selected_asset in enumerate(selected_assets):

    # アセットパス取得 (target_path="/Game/BP_MyActor.BP_MyActor")
    target_path = selected_asset.get_path_name() 
    # アセットのロード
    load_asset = unreal.EditorAssetLibrary.load_asset(target_path)
    # Blueprint GC(generated class)取得 
    # (Blueprintの場合は"_C"を付与 path="/Game/BP_MyActor.BP_MyActor_C")
    bp_gc = unreal.load_object(None, target_path + "_C")
    # Blueprint CDO(class default object)取得
    bp_cdo = unreal.get_default_object(bp_gc)

    # 元の構造体を取得
    my_struct = bp_cdo.get_editor_property("MyStruct")

    # 構造体のbool型変数に設定
    my_struct.set_editor_property("BoolValue", True)

    # 構造体のfloat型変数に設定
    my_struct.set_editor_property("FloatValue", 100.0)

    # 構造体のVector配列に要素1追加
    points = my_struct.get_editor_property("VecArray")
    point = unreal.Vector(1.0,1.0,1.0)
    points.append(point)

    # StaticMeshにアセット/Game/Coneを設定
    static_mesh_path = "/Game/Cone"
    # Coneをロード
    static_mesh = unreal.EditorAssetLibrary.load_asset(static_mesh_path)
    # StaticMeshの変数にアセットを設定
    bp_cdo.set_editor_property("MyStaticMesh", static_mesh)

    # TestFunction関数の呼び出し
    bp_cdo.test_function()

    # 構造体をCDOに設定
    bp_cdo.set_editor_property("MyStruct", my_struct)

    # アセットを保存
    unreal.EditorAssetLibrary.save_loaded_asset(load_asset)

 ポイントはBlueprintアセットを扱う場合"_C"を付与することや、構造体や関数にアクセスする場合はGC/CDOを経由する必要があるということです。これらに注意しておけばEngineクラスと同様に容易にアクセスすることが可能です。

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6