Edited at

UnrealEnginePython プラグインを使ってみた3 (アセットインポート・マテリアル編)

More than 1 year has passed since last update.


はじめに

前回、前々回に引き続き、UnrealEnginePython プラグインを使ってみるシリーズ。

今回はアセットインポート~マテリアル作成・ノード接続・メッシュ割当てあたりのテストコード書いてみる。

ここではサンプル用のデータとして Gray ちゃんアセット(http://rarihoma.xvs.jp/products/graychan/) の

テクスチャと fbx ファイルを使わせていただきました。

(目的がインポートやマテリアルの作成なので、.uasset ファイルはあえて使用しません)


アセットインポート

Gray ちゃんアセットのテクスチャと fbx ファイルを Python からパスを与えてインポートしてみる。


TestAssetImport.py

import unreal_engine as ue

from unreal_engine.classes import PyFbxFactory, TextureFactory
from unreal_engine.enums import TextureCompressionSettings
from unreal_engine import FRotator
import glob
import os.path

# GrayChan アセットのリソース先
resource_dir = 'D:/UnrealEngine/PythonTest/Resource/GrayChan_0_5_0/'
# インポート先
import_dir = '/Game/GrayChan/'

## テクスチャのインポート ##
texture_factory = ue.find_class('TextureFactory')
textures = {}
texture_output = os.path.join(import_dir,'Textures')
for file in glob.glob(os.path.join(resource_dir, 'Textures/*.png')):
name, ext = os.path.splitext(os.path.basename(file))
textures[name] = ue.import_asset(file, texture_output, texture_factory)
for file in glob.glob(os.path.join(resource_dir, 'Textures/*.psd')):
name, ext = os.path.splitext(os.path.basename(file))
textures[name] = ue.import_asset(file, texture_output, texture_factory)

# VectorDisplacementmap の設定
textures['T_GrayChan_Hair'].SRGB = False
textures['T_GrayChan_Hair'].CompressionSettings = TextureCompressionSettings.TC_VectorDisplacementmap
textures['T_GrayChan_Cloth_MSR'].SRGB = False
textures['T_GrayChan_Cloth_MSR'].CompressionSettings = TextureCompressionSettings.TC_VectorDisplacementmap

# テクスチャアセット保存
for tex in textures.values():
tex.save_package()

## fbx のインポート ##
fbx_factory = PyFbxFactory()

# インポート設定
fbx_factory.ImportUI.bCreatePhysicsAsset = False
fbx_factory.ImportUI.bImportMaterials = False
fbx_factory.ImportUI.bImportTextures = False
fbx_factory.ImportUI.bImportAnimations = False
fbx_factory.ImportUI.SkeletalMeshImportData.ImportRotation = FRotator(-90.0,0.0,0.0)

# インポートとアセット保存
mesh_dir = os.path.join(import_dir,'Mesh')
graychan_mesh = fbx_factory.factory_import_object(os.path.join(resource_dir, 'GrayChan.fbx'), mesh_dir)
graychan_mesh.save_package()


テクスチャの場合、TextureFactoryue.import_asset でインポートができる。

fbx の場合は別途 PyFbxFactory クラスが設けられている。

fbx_factory.ImportUI は、通常の fbx インポートするときのメニュー項目である UFbxImportUI と同じプロパティが扱える。

ここでは、ImportRotation で回転してインポートするようにしてある。

実行結果。

03_ImportAsset.png

03_ImportAsset2.png

なお、アセット管理に関しては、大体このあたりに解説がある。

https://github.com/20tab/UnrealEnginePython/blob/master/docs/ManagingAssets.md

Delete, Move, Duplicate, Reimport など一通り揃っている。

このあたりは、他のシステムと連携することで、大量のアセットを自動更新する機能などの拡張ができそうだ。


マテリアルの作成とノード接続

なんと、UnrealEnginePython ではマテリアルをゼロから作ることが可能!

もちろん、ノード接続も含めてすべて Python で書くことができる。まじかよすげー!

ってことで、試しに Gray ちゃんマテリアルを Python だけで構築してみる。

以下、スクリプト行数がかなり膨大になってしまったので、区切りながら解説する。


1. エクスプレッションクラスのインポート・マテリアルのファクトリ

とりあえず、最初の定義部分。


TestMaterial.py

import unreal_engine as ue

from unreal_engine.classes import Texture2D, MaterialFunction, MaterialFactoryNew
from unreal_engine.classes import MaterialExpressionTextureSample, MaterialExpressionTextureObject
from unreal_engine.classes import MaterialExpressionBumpOffset
from unreal_engine.classes import MaterialExpressionAdd, MaterialExpressionMultiply, MaterialExpressionSubtract
from unreal_engine.classes import MaterialExpressionConstant, MaterialExpressionConstant3Vector, MaterialExpressionClamp
from unreal_engine.classes import MaterialExpressionLinearInterpolate, MaterialExpressionMaterialFunctionCall
from unreal_engine.enums import EMaterialShadingModel, EMaterialSamplerType
from unreal_engine.structs import LinearColor, ColorMaterialInput, ScalarMaterialInput, ExpressionInput

import os.path

# インポートしたときのパス。マテリアルアセットを置くパス
import_dir = '/Game/GrayChan/'
material_dir = os.path.join(import_dir, 'Materials/')
texture_dir = os.path.join(import_dir, 'Textures/')

# マテリアルのファクトリ
material_factory = MaterialFactoryNew()



エクスプレッションについて

'from unreal_engine.classes' で大量にインポートしている中で MaterialExpression と名がつくのはエクスプレッション、要するにマテリアルの表現式、マテリアルノードのクラスのこと。

例えば、

e.t.c.

といった具合。

これを事前にインポートしておくことで、これらのノードの作成、プロパティ設定、ノード接続が可能になる。

他のエクスプレッションはソースコードは Engine/Source/Runtime/Engine/Classes/Materials 以下に、

API リファレンスの解説は https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Materials に一覧がある。

これらを読んで、エクスプレッションを組む際の参考にする。


マテリアル作成のファクトリ

MaterialFactoryNew がマテリアルを作成するためのファクトリ。

新規マテリアル作成時はこれを使用する。


2. Gray ちゃんの目(エフェクト無し版)のマテリアル作成

では、まず、GrayChan の目のマテリアルを作ってみる。


TestMaterial.py(続き)

### M_GrayChan_Eyeball #################################################################################

def make_eyeball_material():
# eyeball マテリアルオブジェクト生成
new_material = material_factory.factory_create_new(os.path.join(material_dir, 'M_GrayChan_Eyeball'))
# Eyeball のテクスチャサンプラー
eyeball_base = MaterialExpressionTextureSample('', new_material)
eyeball_base.Texture = ue.load_object(Texture2D, os.path.join(texture_dir, 'T_GrayChan_Eyeball'))
eyeball_base.MaterialExpressionEditorX = -600
eyeball_base.MaterialExpressionEditorY = 0
# Eyeball(Highlight) のテクスチャサンプラー
eyeball_highlight = MaterialExpressionTextureSample('', new_material)
eyeball_highlight.Texture = ue.load_object(Texture2D, os.path.join(texture_dir, 'T_GrayChan_Eyeball_Highlight'))
eyeball_highlight.MaterialExpressionEditorX = -600
eyeball_highlight.MaterialExpressionEditorY = 200
# eyeball のベースカラー用加算 (base + highlight)
eyeball_basecolor_add = MaterialExpressionAdd('', new_material)
eyeball_basecolor_add.MaterialExpressionEditorX = -400
eyeball_basecolor_add.MaterialExpressionEditorY = 0
# emissive カラー用 Const
const_specular = MaterialExpressionConstant('', new_material)
const_specular.R = 0.0
const_specular.MaterialExpressionEditorX = -100
const_specular.MaterialExpressionEditorY = 100
# emissive カラー用乗算
eyeball_emissive_mult = MaterialExpressionMultiply('', new_material)
eyeball_emissive_mult.MaterialExpressionEditorX = -300
eyeball_emissive_mult.MaterialExpressionEditorY = 200
# emissive カラー用加算
eyeball_emissive_add = MaterialExpressionAdd('', new_material)
eyeball_emissive_add.MaterialExpressionEditorX = -100
eyeball_emissive_add.MaterialExpressionEditorY = 200

# 事前に Expression を設定してないとマテリアルを開くときに容赦なくエディタが落ちる
new_material.Expressions = [eyeball_base, eyeball_highlight, eyeball_basecolor_add, eyeball_highlight,
const_specular, eyeball_emissive_mult, eyeball_emissive_add]

# BaseColor ノード接続
eyeball_basecolor_add.A = ExpressionInput(Expression=eyeball_base)
eyeball_basecolor_add.B = ExpressionInput(Expression=eyeball_highlight)
new_material.BaseColor = ColorMaterialInput(Expression=eyeball_basecolor_add)
# Specular ノード接続
new_material.Specular = ScalarMaterialInput(Expression=const_specular)
# EmissiveColor ノード接続
eyeball_emissive_mult.A = ExpressionInput(Expression=eyeball_highlight)
eyeball_emissive_mult.ConstB = 4.0
eyeball_emissive_add.A = ExpressionInput(Expression=eyeball_base)
eyeball_emissive_add.B = ExpressionInput(Expression=eyeball_emissive_mult)
new_material.EmissiveColor = ColorMaterialInput(Expression=eyeball_emissive_add)

# マテリアルの変更を伝える
new_material.post_edit_change()
return new_material


この関数を実行すると、以下のマテリアルが作られる。

image.png

普通に作ったようにみえるけど、UE エディタ上では一切操作していません。上の Python を実行しただけ。なんてこったい。


エクスプレッションの定義

見て分かる通り、必要なノードごとに、インスタンスを作る必要がある。

MaterialExpressionEditorX, MaterialExpressionEditorY は、マテリアルエディタ内での座標位置。

マテリアルのリザルトノードは、デフォルトで左上が (0,0) の位置に置かれるらしい。

なので、可読性よくするためにも、X方向はだいたいマイナス側を設定することになる。

必要に応じて、各ノードごとのパラメタ値の指定、さらに、ExpressionInput クラスを使用してノード接続を行う。


Expressions の注意点

注意点としては、'new_material.Expressions' の行。

Expressions には事前に各 Expression を配列で格納しておく必要がある。

これをしておかないと Python を実行した瞬間に UE エディタもろともクラッシュしてしまう。


3. Gray ちゃんの髪の毛マテリアル作成


TestMaterial.py(続き)

### M_GrayChan_Hair #################################################################################

def make_hair_material():
# hair マテリアルオブジェクト生成
new_material = material_factory.factory_create_new(os.path.join(material_dir, 'M_GrayChan_Hair'))
# hair のテクスチャサンプラー
hair_base = MaterialExpressionTextureSample('', new_material)
hair_base.Texture = ue.load_object(Texture2D, os.path.join(texture_dir, 'T_GrayChan_Hair'))
hair_base.SamplerType = EMaterialSamplerType.SAMPLERTYPE_LinearColor
hair_base.MaterialExpressionEditorX = -1200
hair_base.MaterialExpressionEditorY = 0
# hair のテクスチャオブジェクト
hair_lut = MaterialExpressionTextureObject('', new_material)
hair_lut.Texture = ue.load_object(Texture2D, os.path.join(texture_dir, 'T_GrayChan_Hair_LUT'))
hair_lut.MaterialExpressionEditorX = -1200
hair_lut.MaterialExpressionEditorY = 300
# hair カラー用乗算
basecolor_mult = MaterialExpressionMultiply('', new_material)
basecolor_mult.MaterialExpressionEditorX = -1000
basecolor_mult.MaterialExpressionEditorY = 30
# GradientMap_Multi 用 Const
const_zero = MaterialExpressionConstant('', new_material)
const_zero.R = 0.0
const_zero.MaterialExpressionEditorX = -850
const_zero.MaterialExpressionEditorY = 60
# GradientMap_Multi 用 Const
const_one = MaterialExpressionConstant('', new_material)
const_one.R = 1.0
const_one.MaterialExpressionEditorX = -850
const_one.MaterialExpressionEditorY = 200
# GradientMap_Multi 用 Const
const_two = MaterialExpressionConstant('', new_material)
const_two.R = 2.0
const_two.MaterialExpressionEditorX = -850
const_two.MaterialExpressionEditorY = 300
# FunctionCall(GradientMap_Multi) 1つ目
gradientmap_mult0 = MaterialExpressionMaterialFunctionCall('', new_material)
gradientmap_mult0.MaterialExpressionEditorX = -700
gradientmap_mult0.MaterialExpressionEditorY = 0
gradientmap_mult0.SetMaterialFunction(ue.load_object(MaterialFunction,
'/Engine/Functions/Engine_MaterialFunctions02/Gradients/GradientMap_Multi'))
# FunctionCall(GradientMap_Multi) 2つ目
gradientmap_mult1 = MaterialExpressionMaterialFunctionCall('', new_material)
gradientmap_mult1.MaterialExpressionEditorX = -700
gradientmap_mult1.MaterialExpressionEditorY = 200
gradientmap_mult1.SetMaterialFunction(ue.load_object(MaterialFunction,
'/Engine/Functions/Engine_MaterialFunctions02/Gradients/GradientMap_Multi'))
# Lerp Alpha 計算する Subtracts
basecolor_sub = MaterialExpressionSubtract('', new_material)
basecolor_sub.MaterialExpressionEditorX = -750
basecolor_sub.MaterialExpressionEditorY = 400
basecolor_sub.ConstB = 0.9
# Lerp Alpha 計算する Clamp
basecolor_clamp = MaterialExpressionClamp('', new_material)
basecolor_clamp.MaterialExpressionEditorX = -500
basecolor_clamp.MaterialExpressionEditorY = 400
basecolor_clamp.MinDefault = 0.0
basecolor_clamp.MaxDefault = 1.0
# BaseColor につなげる Lerp
basecolor_lerp = MaterialExpressionLinearInterpolate('', new_material)
basecolor_lerp.MaterialExpressionEditorX = -200
basecolor_lerp.MaterialExpressionEditorY = 0
# roughness 用 Const
const_roughness = MaterialExpressionConstant('', new_material)
const_roughness.R = 0.6
const_roughness.MaterialExpressionEditorX = -100
const_roughness.MaterialExpressionEditorY = 200

# 事前に Expression を設定してないとマテリアルを開くときに容赦なくエディタが落ちる
new_material.Expressions = [ hair_base, hair_lut, basecolor_mult, const_zero, const_one, const_two,
gradientmap_mult0, gradientmap_mult1,
basecolor_sub, basecolor_clamp, basecolor_lerp, const_roughness]

# BaseColor ノード接続
inputs = gradientmap_mult0.FunctionInputs
inputs[0].Input = ExpressionInput(Expression=hair_base, Mask=1, MaskR=1)
inputs[1].Input = ExpressionInput(Expression=const_zero)
inputs[2].Input = ExpressionInput(Expression=hair_lut)
inputs[3].Input = ExpressionInput(Expression=const_two)
gradientmap_mult0.FunctionInputs = inputs
basecolor_mult.A = ExpressionInput(Expression=hair_base, Mask=1, MaskR=1)
basecolor_mult.B = ExpressionInput(Expression=hair_base, Mask=1, MaskG=1)
inputs = gradientmap_mult1.FunctionInputs
inputs[0].Input = ExpressionInput(Expression=basecolor_mult)
inputs[1].Input = ExpressionInput(Expression=const_one)
inputs[2].Input = ExpressionInput(Expression=hair_lut)
inputs[3].Input = ExpressionInput(Expression=const_two)
gradientmap_mult1.FunctionInputs = inputs
basecolor_sub.A = ExpressionInput(Expression=hair_base, Mask=1, MaskG=1)
basecolor_clamp.Input = ExpressionInput(Expression=basecolor_sub)
basecolor_lerp.A = ExpressionInput(Expression=gradientmap_mult0, OutputIndex=0)
basecolor_lerp.B = ExpressionInput(Expression=gradientmap_mult1, OutputIndex=0)
basecolor_lerp.Alpha = ExpressionInput(Expression=basecolor_clamp)
new_material.BaseColor = ColorMaterialInput(Expression=basecolor_lerp)
# Roughness ノード接続
new_material.Roughness = ScalarMaterialInput(Expression=const_roughness)

# マテリアルの変更を伝える
new_material.post_edit_change()
return new_material


この関数を実行すると、以下のマテリアルが作られる。

image.png

・・・正直つかれた _(:3」∠)_

エクスプレッション数やノード数が増えると一気に行数が増えていく。つらい・・・


TextureSample のタイプ

`hair_base.SamplerType = EMaterialSamplerType.SAMPLERTYPE_LinearColor' というように、

EMaterialSamplerType を使用して設定する。


TextureSample の RGBA ノード

basecolor_mult.A = ExpressionInput(Expression=hair_base, Mask=1, MaskR=1) などのように、

TextureSmaple に対して ExpressionInput 時にマスク指定すると、マスクされた個別のノードから接続ができる。


マテリアルファンクションノード

MaterialExpressionMaterialFunctionCall はマテリアルファンクションだが、

ue.load_object で対象のマテリアルファンクションのアセットを指定することで問題なく使用することができた。

Input 側の接続は、inputs = gradientmap_mult1.FunctionInputs で一旦 Input の内容を展開してから、

その中の Input に接続すべきノードを書き込む。

Output 側の接続は、ExpressionInput(Expression=gradientmap_mult0, OutputIndex=0) というように、OutputIndex で指定が可能。


4. Gray ちゃんの肌マテリアル作成


TestMaterial.py(続き)

### M_GrayChan_Skin #################################################################################

def make_skin_material():
# skin マテリアルオブジェクト生成
new_material = material_factory.factory_create_new(os.path.join(material_dir, 'M_GrayChan_Skin'))
new_material.ShadingModel = EMaterialShadingModel.MSM_Subsurface
# skin のテクスチャサンプラー
skin_base = MaterialExpressionTextureSample('', new_material)
skin_base.Texture = ue.load_object(Texture2D, os.path.join(texture_dir, 'T_GrayChan_Skin'))
skin_base.MaterialExpressionEditorX = -600
skin_base.MaterialExpressionEditorY = 0
# skin 用 Const Vector3
skin_color = MaterialExpressionConstant3Vector('', new_material)
skin_color.Constant = LinearColor(R=0.886275, G=0.560784, B=0.478431)
skin_color.MaterialExpressionEditorX = -600
skin_color.MaterialExpressionEditorY = 200
# sub カラー用乗算
skin_mult = MaterialExpressionMultiply('', new_material)
skin_mult.MaterialExpressionEditorX = -300
skin_mult.MaterialExpressionEditorY = 200
# specular 用 Const
const_specular = MaterialExpressionConstant('', new_material)
const_specular.R = 0.0
const_specular.MaterialExpressionEditorX = -100
const_specular.MaterialExpressionEditorY = 60
# roughness 用 Const
const_roughness = MaterialExpressionConstant('', new_material)
const_roughness.R = 0.35
const_roughness.MaterialExpressionEditorX = -100
const_roughness.MaterialExpressionEditorY = 120
# opacity 用 Const
const_opacity = MaterialExpressionConstant('', new_material)
const_opacity.R = 0.1
const_opacity.MaterialExpressionEditorX = -100
const_opacity.MaterialExpressionEditorY = 160

# 事前に Expression を設定してないとマテリアルを開くときに容赦なくエディタが落ちる
new_material.Expressions = [skin_base, skin_color, skin_mult,
const_specular, const_roughness, const_opacity]

# BaseColor ノード接続
new_material.BaseColor = ColorMaterialInput(Expression=skin_base)
# Specular ノード接続
new_material.Specular = ScalarMaterialInput(Expression=const_specular)
# Roughness ノード接続
new_material.Roughness = ScalarMaterialInput(Expression=const_roughness)
# Opacity ノード接続
new_material.Opacity = ScalarMaterialInput(Expression=const_opacity)
# SubsurfaceColor ノード接続
skin_mult.A = ExpressionInput(Expression=skin_base, Mask=1, MaskR=1, MaskG=1, MaskB=1)
skin_mult.B = ExpressionInput(Expression=skin_color)
new_material.SubsurfaceColor = ColorMaterialInput(Expression=skin_mult)

# マテリアルの変更を伝える
new_material.post_edit_change()
return new_material


この関数を実行すると、以下のマテリアルが作られる。

image.png


ShadingModel

ここでは、new_material.ShadingModel = EMaterialShadingModel.MSM_Subsurface とマテリアル側のプロパティに

EMaterialShadingModel を指定している。


5. Gray ちゃんの服・ロゴ(発光なし)マテリアル作成


TestMaterial.py(続き)

### M_GrayChan_Cloth #################################################################################

def make_cloth_material():
# cloth マテリアルオブジェクト生成
new_material = material_factory.factory_create_new(os.path.join(material_dir, 'M_GrayChan_Cloth'))
# cloth のテクスチャサンプラー1
cloth_base = MaterialExpressionTextureSample('', new_material)
cloth_base.Texture = ue.load_object(Texture2D, os.path.join(texture_dir, 'T_GrayChan_Cloth'))
cloth_base.MaterialExpressionEditorX = -600
cloth_base.MaterialExpressionEditorY = 0
# cloth のテクスチャサンプラー2
cloth_detail = MaterialExpressionTextureSample('', new_material)
cloth_detail.Texture = ue.load_object(Texture2D, os.path.join(texture_dir, 'T_GrayChan_Cloth_Details'))
cloth_detail.MaterialExpressionEditorX = -600
cloth_detail.MaterialExpressionEditorY = 200
# cloth のテクスチャサンプラー3
cloth_msr = MaterialExpressionTextureSample('', new_material)
cloth_msr.Texture = ue.load_object(Texture2D, os.path.join(texture_dir, 'T_GrayChan_Cloth_MSR'))
cloth_msr.SamplerType = EMaterialSamplerType.SAMPLERTYPE_LinearColor
cloth_msr.MaterialExpressionEditorX = -300
cloth_msr.MaterialExpressionEditorY = 150
# basecolor 用乗算
base_mult = MaterialExpressionMultiply('', new_material)
base_mult.MaterialExpressionEditorX = -300
base_mult.MaterialExpressionEditorY = 0

# 事前に Expression を設定してないとマテリアルを開くときに容赦なくエディタが落ちる
new_material.Expressions = [cloth_base, cloth_detail, cloth_msr, base_mult]

# BaseColor ノード接続
base_mult.A = ExpressionInput(Expression=cloth_base)
base_mult.B = ExpressionInput(Expression=cloth_detail)
new_material.BaseColor = ColorMaterialInput(Expression=base_mult)

# Metallic ノード接続
new_material.Metallic = ScalarMaterialInput(Expression=cloth_msr, Mask=1, MaskR=1)
# Specular ノード接続
new_material.Specular = ScalarMaterialInput(Expression=cloth_msr, Mask=1, MaskG=1)
# Roughness ノード接続
new_material.Roughness = ScalarMaterialInput(Expression=cloth_msr, Mask=1, MaskB=1)

# マテリアルの変更を伝える
new_material.post_edit_change()
return new_material

### M_GrayChan_Logo #################################################################################
def make_logo_material():
# logo マテリアルオブジェクト生成
new_material = material_factory.factory_create_new(os.path.join(material_dir, 'M_GrayChan_Logo'))

# BumpOffset 用 height の const
const_height = MaterialExpressionConstant('', new_material)
const_height.R = -1.0
const_height.MaterialExpressionEditorX = -700
const_height.MaterialExpressionEditorY = 200
# BumpOffset
bump_offset = MaterialExpressionBumpOffset('', new_material)
bump_offset.ReferencePlane = 0.5
bump_offset.HeightRatio = 0.05
bump_offset.MaterialExpressionEditorX = -600
bump_offset.MaterialExpressionEditorY = 200
# cloth のテクスチャサンプラー1
cloth_base = MaterialExpressionTextureSample('', new_material)
cloth_base.Texture = ue.load_object(Texture2D, os.path.join(texture_dir, 'T_GrayChan_Cloth'))
cloth_base.MaterialExpressionEditorX = -300
cloth_base.MaterialExpressionEditorY = 0
# cloth のテクスチャサンプラー2
cloth_detail = MaterialExpressionTextureSample('', new_material)
cloth_detail.Texture = ue.load_object(Texture2D, os.path.join(texture_dir, 'T_GrayChan_Cloth_Details'))
cloth_detail.MaterialExpressionEditorX = -300
cloth_detail.MaterialExpressionEditorY = 200
# BaseColor 用乗算
base_mult = MaterialExpressionMultiply('', new_material)
base_mult.MaterialExpressionEditorX = -100
base_mult.MaterialExpressionEditorY = 0

# 事前に Expression を設定してないとマテリアルを開くときに容赦なくエディタが落ちる
new_material.Expressions = [const_height, bump_offset, cloth_base, cloth_detail, base_mult]

# BaseColor
bump_offset.Height = ExpressionInput(Expression=const_height)
cloth_detail.Coordinates = ExpressionInput(Expression=bump_offset)
base_mult.A = ExpressionInput(Expression=cloth_base)
base_mult.B = ExpressionInput(Expression=cloth_detail)
new_material.BaseColor = ColorMaterialInput(Expression=base_mult)

# マテリアルの変更を伝える
new_material.post_edit_change()
return new_material


それぞれ、Gray ちゃんの服マテリアルは、

image.png

Gray ちゃんのロゴ(発光なし)マテリアルは、

image.png

こんな感じ。

他のマテリアルと同様なので、補足は特になし。


マテリアルをスケルタルメッシュに割り当て

最後に、せっかくマテリアルを作ったので、最初にインポートした GrayChan スケルタルメッシュに割り当ててみる。

事前に、前の節での関数が定義されていたとして、以下のスクリプトでマテリアルを生成、保存する。

# M_GrayChan_Eyeball を作成する

m_eyeball = make_eyeball_material()
# M_GrayChan_Hair を作成する
m_hair = make_hair_material()
# M_GrayChan_Cloth を作成する
m_cloth = make_cloth_material()
# M_GrayChan_Logo_Tim を作成する
m_logo = make_logo_material()
# M_GrayChan_Skin を作成する
m_skin = make_skin_material()

# 保存
m_eyeball.save_package()
m_hair.save_package()
m_cloth.save_package()
m_logo.save_package()
m_skin.save_package()

material.png

さらに、以下のようにして、メッシュに対してマテリアルの設定が可能。

from unreal_engine.classes import SkeletalMesh

from unreal_engine.structs import SkeletalMaterial, MeshUVChannelInfo

# メッシュにマテリアルを割り当てる
mesh_dir = os.path.join(import_dir,'Mesh/')
graychan_mesh = ue.load_object(SkeletalMesh, os.path.join(mesh_dir, 'GrayChan'))

graychan_mesh.Materials = [
SkeletalMaterial(MaterialInterface=m_eyeball, MaterialSlotName='M_GrayChan_Eyballs', UVChannelData=MeshUVChannelInfo(bInitialized=True)),
SkeletalMaterial(MaterialInterface=m_hair, MaterialSlotName='M_GrayChan_Hair', UVChannelData=MeshUVChannelInfo(bInitialized=True)),
SkeletalMaterial(MaterialInterface=m_cloth, MaterialSlotName='M_GrayChan_Cloth', UVChannelData=MeshUVChannelInfo(bInitialized=True)),
SkeletalMaterial(MaterialInterface=m_skin, MaterialSlotName='M_GrayChan_Skin', UVChannelData=MeshUVChannelInfo(bInitialized=True)),
SkeletalMaterial(MaterialInterface=m_logo, MaterialSlotName='M_GrayChan_Logo', UVChannelData=MeshUVChannelInfo(bInitialized=True))
]
graychan_mesh.save_package()

実行結果。

作ったマテリアルがちゃんと設定できていることが確認できる。

image.png