【Pythonライブラリ】「unreal」のサンプルコード(Unreal Engine PythonAPI)

Python

こちらは「Unreal Engine」のPythonAPIである「unreal」(Pythonライブラリ)のサンプルコードについての記事となっております。

「unreal」を使用する上で基礎的な情報は下記の記事で紹介しております。
他の「unreal」のクラスや関数について気になる方はこちらの記事をご覧ください。

その他、3Dモデルの処理方法についての情報は下記の記事で紹介しております。
open3d/plotly/trimesh/pyvista/vedo/pytorch3d/matplotlibといったPythonライブラリや3DツールのPythonAPIであるbpy(Blender)/unreal(Unreal Engine)といったPythonライブラリについて気になる方はこちらの記事をご覧ください。

基本情報 … Basic Information

「unreal」(Unreal Engine Python API)は、Unreal EngineのPythonライブラリです。このAPIを使用することで、Unreal Engineをより簡単にカスタマイズすることができます。Pythonは、様々なプログラミング言語で使用される汎用的なスクリプト言語であり、Unreal Engine Python APIはPythonを使用して構築されています。

Unreal Engine Python APIを使用することで、Unreal Engineの機能をより簡単に使用できるようになります。例えば、Unreal Engine Python APIを使用して、ゲーム内のオブジェクトの位置を変更することができます。また、Unreal Engine Python APIを使用して、ゲーム内のアセットを自動的に生成することもできます。

サンプルコード … Sample Code

001 簡単なデータの表示

import unreal

print("Hello Unreal")
unreal.log("Hello Unreal")
unreal.log_warning("Hello Unreal")
unreal.log_error("Hello Unreal")
LogPython: Hello Unreal
LogPython: Hello Unreal
LogPython: Warning: Hello Unreal
LogPython: Error: Hello Unreal

002 コンテンツ内のアセットの読み込み、オブジェクトデータの表示(SM_Chair)

import unreal

chair_asset = unreal.load_asset('/Game/StarterContent/Props/SM_Chair.SM_Chair')

### Attribute of "chair_asset"
for attribute in dir(chair_asset): print(attribute)

### Help of "chair_asset"
help(chair_asset)

### Information of "chair_asset"
print(chair_asset.get_class())
print(chair_asset.get_fname())
print(chair_asset.get_path_name())
LogPython: __class__
LogPython: __delattr__
LogPython: __dir__
...
LogPython: set_num_source_models
LogPython: static_class
LogPython: static_materials
LogPython: Help on StaticMesh object:
class StaticMesh(StreamableRenderAsset)
 |  A StaticMesh is a piece of geometry that consists of a static set of polygons.
 |  Static Meshes can be translated, rotated, and scaled, but they cannot have their vertices animated in any way. As such, they are more efficient
 |  to render than other types of geometry such as USkeletalMesh, and they are often the basic building block of levels created in the engine.
 |  see: https://docs.unrealengine.com/latest/INT/Engine/Content/Types/StaticMeshes/
 |  see: AStaticMeshActor, UStaticMeshComponent
...
 |  Static methods inherited from _ObjectBase:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
LogPython: <Object '/Script/Engine.StaticMesh' (0x00000B0A93F40300) Class 'Class'>
LogPython: SM_Chair
LogPython: /Game/StarterContent/Props/SM_Chair.SM_Chair

003 コンテンツ内のアセットの読み込み、オブジェクトデータの表示(SM_Cube)

import unreal

cube_asset = unreal.load_asset('/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube')

### Attribute of "cube_asset"
for attribute in dir(cube_asset): print(attribute)

### Help of "cube_asset"
help(cube_asset)

### Information of "cube_asset"
print(cube_asset.get_class())
print(cube_asset.get_fname())
print(cube_asset.get_path_name())

cube_material = cube_asset.get_material(0)
print(cube_material)
print(cube_material.get_class())
print(type(cube_material))

cube_lod_for_collision = cube_asset.get_editor_property("lod_for_collision")
print(cube_lod_for_collision)
print(type(cube_lod_for_collision))
LogPython: __class__
LogPython: __delattr__
LogPython: __dir__
...
LogPython: set_num_source_models
LogPython: static_class
LogPython: static_materials
LogPython: Help on StaticMesh object:
class StaticMesh(StreamableRenderAsset)
 |  A StaticMesh is a piece of geometry that consists of a static set of polygons.
 |  Static Meshes can be translated, rotated, and scaled, but they cannot have their vertices animated in any way. As such, they are more efficient
 |  to render than other types of geometry such as USkeletalMesh, and they are often the basic building block of levels created in the engine.
 |  see: https://docs.unrealengine.com/latest/INT/Engine/Content/Types/StaticMeshes/
 |  see: AStaticMeshActor, UStaticMeshComponent
...
 |  Static methods inherited from _ObjectBase:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
LogPython: <Object '/Script/Engine.StaticMesh' (0x00000B0A93F40300) Class 'Class'>
LogPython: Shape_Cube
LogPython: /Game/StarterContent/Shapes/Shape_Cube.Shape_Cube

LogPython: <Object '/Game/StarterContent/Materials/M_Basic_Wall.M_Basic_Wall' (0x00000B0B50CD3C00) Class 'Material'>
LogPython: <Object '/Script/Engine.Material' (0x00000B0A93EB1B00) Class 'Class'>
LogPython: <class 'Material'>

LogPython: 0
LogPython: <class 'int'>
### Change Information
new_material = unreal.load_asset('/Game/StarterContent/Materials/M_Basic_Floor.M_Basic_Floor')
cube_asset.set_material(0, new_material)

new_lod_for_collision = 1
cube_asset.set_editor_property("lod_for_collision", new_lod_for_collision)

### Information of "cube_asset"

print(new_material.get_class())
print(type(new_material))
print(cube_asset.get_material(0))

print(cube_asset.get_editor_property("lod_for_collision"))
LogPython: <Object '/Script/Engine.Material' (0x00000B0A93EB1B00) Class 'Class'>
LogPython: <class 'Material'>
LogPython: <Object '/Game/StarterContent/Materials/M_Basic_Floor.M_Basic_Floor' (0x00000B0B5AEB6C00) Class 'Material'>

LogPython: 1

004 コンテンツ内のアセットの読み込み、レベル上にオブジェクトを表示

import unreal

### Read Object
### class unreal.EditorAssetLibrary(outer=None, name='None')
### classmethod load_asset(asset_path) 
### → Object
chair_asset = unreal.EditorAssetLibrary().load_asset('/Game/StarterContent/Props/SM_Chair.SM_Chair')

### Setup Location Parameter
### class unreal.Vector(x=0.0, y=0.0, z=0.0)
location = unreal.Vector(0.0, 0.0, 20.0)

### Setup Rotation Parameter
### class unreal.Rotator(roll=0.0, pitch=0.0, yaw=0.0)
rotation = unreal.Rotator(0, 0, 180.0)

### Import Object in Level
### classmethod spawn_actor_from_object
### (object_to_use, location, rotation=[0.0, 0.0, 0.0], transient=False)
### → Actor
actor = unreal.EditorLevelLibrary.spawn_actor_from_object(chair_asset, location, rotation)

### Rename the Object
### class unreal.Actor(outer=None, name='None')
### set_actor_label(new_actor_label, mark_dirty=True) 
### → None
actor.set_actor_label("SM_SampleChair")

005 コンテンツ内のアセットを全て取得

import unreal

### Read Objects
### class unreal.EditorAssetLibrary(outer=None, name='None')
### classmethod list_assets(directory_path, recursive=True, include_folder=False)
### → Array(str)

directory_path = "/Game" ### Under "Content" Folder
allAssets = unreal.EditorAssetLibrary().list_assets(directory_path)

for asset in allAssets: print(asset)

"""
LogPython: /Game/StarterContent/Architecture/Floor_400x400.Floor_400x400
LogPython: /Game/StarterContent/Architecture/Pillar_50x500.Pillar_50x500
LogPython: /Game/StarterContent/Architecture/SM_AssetPlatform.SM_AssetPlatform
...
LogPython: /Game/StarterContent/Textures/T_Wood_Pine_N.T_Wood_Pine_N
LogPython: /Game/StarterContent/Textures/T_Wood_Walnut_D.T_Wood_Walnut_D
LogPython: /Game/StarterContent/Textures/T_Wood_Walnut_N.T_Wood_Walnut_N
"""

006 コンテンツ内の選択されているアセットを全て取得

import unreal

### Read Objects
### unreal.EditorUtilityLibrary
### classmethod get_selected_assets() 
### → Array[Object]

slectedAssets = unreal.EditorUtilityLibrary.get_selected_assets()
for assetObject in slectedAssets: print(assetObject)

"""
LogPython: <Object '/Game/StarterContent/Architecture/Floor_400x400.Floor_400x400' (0x000009ACEDE7E000) Class 'StaticMesh'>
LogPython: <Object '/Game/StarterContent/Props/MaterialSphere.MaterialSphere' (0x000009ACEDE70700) Class 'StaticMesh'>
LogPython: <Object '/Game/StarterContent/Architecture/Pillar_50x500.Pillar_50x500' (0x000009AD154B3800) Class 'StaticMesh'>
...
LogPython: <Object '/Game/StarterContent/Architecture/Wall_Door_400x400.Wall_Door_400x400' (0x000009AD152A7000) Class 'StaticMesh'>
LogPython: <Object '/Game/StarterContent/Architecture/Wall_Window_400x300.Wall_Window_400x300' (0x000009AD152A7E00) Class 'StaticMesh'>
LogPython: <Object '/Game/StarterContent/Architecture/Wall_Window_400x400.Wall_Window_400x400' (0x000009AD152A8C00) Class 'StaticMesh'>
"""

### Read Asset Data
### unreal.EditorUtilityLibrary
### classmethod get_selected_asset_data()
### → Array[AssetData]

slectedAssets = unreal.EditorUtilityLibrary.get_selected_asset_data()
for assetData in slectedAssets: print(assetData)

"""
LogPython: <Struct 'AssetData' (0x000009ACBDD747E0) {package_name: "/Game/StarterContent/Architecture/Floor_400x400", package_path: "/Game/StarterContent/Architecture", asset_name: "Floor_400x400", asset_class_path: {package_name: "/Script/Engine", asset_name: "StaticMesh"}}>
LogPython: <Struct 'AssetData' (0x000009ACBDD73020) {package_name: "/Game/StarterContent/Props/MaterialSphere", package_path: "/Game/StarterContent/Props", asset_name: "MaterialSphere", asset_class_path: {package_name: "/Script/Engine", asset_name: "StaticMesh"}}>
LogPython: <Struct 'AssetData' (0x000009ACBDD75780) {package_name: "/Game/StarterContent/Architecture/Pillar_50x500", package_path: "/Game/StarterContent/Architecture", asset_name: "Pillar_50x500", asset_class_path: {package_name: "/Script/Engine", asset_name: "StaticMesh"}}>
...
LogPython: <Struct 'AssetData' (0x000009ACBDD74380) {package_name: "/Game/StarterContent/Architecture/Wall_Door_400x400", package_path: "/Game/StarterContent/Architecture", asset_name: "Wall_Door_400x400", asset_class_path: {package_name: "/Script/Engine", asset_name: "StaticMesh"}}>
LogPython: <Struct 'AssetData' (0x000009ACBDD75280) {package_name: "/Game/StarterContent/Architecture/Wall_Window_400x300", package_path: "/Game/StarterContent/Architecture", asset_name: "Wall_Window_400x300", asset_class_path: {package_name: "/Script/Engine", asset_name: "StaticMesh"}}>
LogPython: <Struct 'AssetData' (0x000009ACBDD72760) {package_name: "/Game/StarterContent/Architecture/Wall_Window_400x400", package_path: "/Game/StarterContent/Architecture", asset_name: "Wall_Window_400x400", asset_class_path: {package_name: "/Script/Engine", asset_name: "StaticMesh"}}>
"""

007 レベル上のアクターを全て取得

import unreal

### Read Actors
### class unreal.EditorActorSubsystem
### get_all_level_actors() 
### → Array[Actor]

allActors = unreal.EditorActorSubsystem().get_selected_level_actors()
for actor in allActors: print(actor)

### Read Actors Components
### class unreal.EditorActorSubsystem
### get_all_level_actors_components() 
### → Array[ActorComponent]

allActorsComponents = unreal.EditorActorSubsystem().get_all_level_actors_components()
for actorsComponents in allActorsComponents: print(actorsComponents)

008 レベル上の選択されているアクターを全て取得

import unreal

### Read Actors
### class unreal.EditorActorSubsystem
### get_selected_level_actors() 
### → Array[Actor]

slectedActors = unreal.EditorActorSubsystem().get_selected_level_actors()
for actor in slectedActors: print(actor)

009 アクティブなレベルを取得

import unreal

### unreal.UnrealEditorSubsystem
### get_editor_world() → World
activeWorld = unreal.UnrealEditorSubsystem().get_editor_world()
print(activeWorld)

### Attribute of Active World Object
for attribute in dir(activeWorld): print(attribute)

### Help of Active World Object
help(activeWorld)

### Information of "chair_asset"
print(activeWorld.get_class())
print(activeWorld.get_fname())
print(activeWorld.get_path_name())

010 アクターの生成、フォルダの作成

import unreal

### unreal.EditorLevelLibrary
### classmethod spawn_actor_from_class
### (actor_class, location, rotation=[0.000000, 0.000000, 0.000000], transient=False) 
### → Actor

### New Actor (Class: Actor)
new_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(
    unreal.Actor.static_class(),
    unreal.Vector(0, 0, 0),
    unreal.Rotator(0, 0, 0)
)

new_actor.set_actor_label(f"SampleActor")      ### Edit Label Name
new_actor.set_folder_path(f"SampleFolder")     ### Create New Folder / Set Folder to Actor

### New Actor (Class: StaticMeshActor)
new_actor_StaticMesh = unreal.EditorLevelLibrary.spawn_actor_from_class(
    unreal.StaticMeshActor.static_class(),
    unreal.Vector(0, 0, 0),
    unreal.Rotator(0, 0, 0)
)

new_actor_StaticMesh.set_actor_label(f"SM_SampleActor")   ### Edit Label Name
new_actor_StaticMesh.set_folder_path(f"SampleFolder")     ### Create New Folder / Set Folder to Actor

### New Actor (Class: SkeletalMeshActor)
new_actor_SkeletalMesh = unreal.EditorLevelLibrary.spawn_actor_from_class(
    unreal.SkeletalMeshActor.static_class(),
    unreal.Vector(0, 0, 0),
    unreal.Rotator(0, 0, 0)
)

new_actor_SkeletalMesh.set_actor_label(f"SK_SampleActor")   ### Edit Label Name
new_actor_SkeletalMesh.set_folder_path(f"SampleFolder")     ### Create New Folder / Set Folder to Actor

### New Actor (Class: CameraActor)
new_actor_Camera = unreal.EditorLevelLibrary.spawn_actor_from_class(
    unreal.CameraActor.static_class(),
    unreal.Vector(0, 0, 0),
    unreal.Rotator(0, 0, 0)
)

new_actor_Camera.set_actor_label(f"SampleCamera")     ### Edit Label Name
new_actor_Camera.set_folder_path(f"SampleFolder")     ### Create New Folder / Set Folder to Actor

### New Actor (Class: CineCameraActor)
new_actor_CineCamera = unreal.EditorLevelLibrary.spawn_actor_from_class(
    unreal.CineCameraActor.static_class(),
    unreal.Vector(0, 0, 0),
    unreal.Rotator(0, 0, 0)
)

new_actor_CineCamera.set_actor_label(f"SampleCineCamera") ### Edit Label Name
new_actor_CineCamera.set_folder_path(f"SampleFolder")     ### Create New Folder / Set Folder to Actor

011 アクターの接続

import unreal

### New Actor (Class: Actor)
new_actor_Parent = unreal.EditorLevelLibrary.spawn_actor_from_class(
    unreal.Actor.static_class(),
    unreal.Vector(0, 0, 0),
    unreal.Rotator(0, 0, 0)
)

new_actor_Parent.set_actor_label(f"ParentActor")      ### Edit Label Name

### New Actor (Class: Actor)
chair_asset = unreal.EditorAssetLibrary().load_asset('/Game/StarterContent/Props/SM_Chair.SM_Chair')
new_actor_Child = unreal.EditorLevelLibrary.spawn_actor_from_object(
    chair_asset,
    unreal.Vector(0, 0, 0),
    unreal.Rotator(0, 0, 0)
)

new_actor_Child.set_actor_label(f"ChildActor")      ### Edit Label Name

### Connect Actor (Child) to Actor (Parent)
new_actor_Child.attach_to_actor(new_actor_Parent, "", unreal.AttachmentRule.KEEP_RELATIVE, unreal.AttachmentRule.KEEP_RELATIVE, unreal.AttachmentRule.KEEP_RELATIVE)