Houdini 20.0 Unreal

APIを使用してHDAをインスタンス化する

How-toガイド: Public APIを使用してHDAをインスタンス化する方法。

On this page

このチュートリアルでは、以下を通して、Public APIの機能をいくつか説明していきます:

利用可能なコマンドのリストは、Public APIドキュメントを参照してください。

Houdini Public APIインスタンス

UHoudiniPublicAPIインスタンスは、それ関連のブループリント関数ライブラリUHoudiniPublicAPIBlueprintLibを介して取得します。

プラグインのPublic APIはEditorモジュールの中にあるため、Editor Onlyのブループリントからのみアクセスすることができます。 ブループリントを作成する際は、EditorUtilityActorまたはEditorUtilityWidget(UIウィジェット用)といったEditor Onlyの基本クラスを選択し、ブループリントをEditor Onlyにする必要があります。

Warning

既存のブループリントを編集すると、そのブループリントはEditor Onlyのブループリントの子に親子化し直されます。 しかし、新しい親クラスと古い親クラスに互換性がないと、その親子化によって問題が発生したり、データが失なわれてしまう可能性があります。

詳細は、Unrealのブループリントによるスクリプト化のドキュメントを参照してください。

C++:

#include "HoudiniPublicAPIBlueprintLib.h"
#include "HoudiniPublicAPI.h"

UHoudiniPublicAPI* const API = UHoudiniPublicAPIBlueprintLib::GetAPI();

ブループリント:

Python:

import unreal

api = unreal.HoudiniPublicAPIBlueprintLib.get_api()    

セッションの開始

APIインスタンスセットアップを使用して、Houdini Engineセッションのステータスを確認し、(必要な場合)そのセッションを開始します。

C++:

if (!API->IsSessionValid())
    API->CreateSession();

ブループリント:

Python:

if not api.is_session_valid():
    api.create_session()  

HDAのインスタンス化

ワールドでHDAをインスタンス化することができます。 ここでは、プラグインに含まれているサンプルHDAの1つであるcopy_to_curve_1_0を使用しています。

C++:

// HDA uassetをロードします。
UHoudiniAsset* const ExampleHDA = Cast<UHoudiniAsset>(StaticLoadObject(UHoudiniAsset::StaticClass(), nullptr, TEXT("/HoudiniEngine/Examples/hda/copy_to_curve_1_0.copy_to_curve_1_0")));
// HDAをインスタンス化してそれを操作できるようにAPIラッパーインスタンスを作成します。
UHoudiniPublicAPIAssetWrapper* const Wrapper = API->InstantiateAsset(ExampleHDA, FTransform::Identity)

ブループリント:

Python:

# HDA uassetをロードします。
example_hda = unreal.load_object(None, '/HoudiniEngine/Examples/hda/copy_to_curve_1_0.copy_to_curve_1_0')
# HDAをインスタンス化してそれを操作できるようにAPIラッパーインスタンスを作成します。
wrapper = api.instantiate_asset(example_hda, instantiate_at=unreal.Transform())

InstantiateAsset関数は、インスタンス化されたHDAを操作(例えば、パラメータ値の設定や入力の割り当てなど)するAPIラッパークラス(UHoudiniPublicAPIAssetWrapper)を返します。

Asset Wrapper - デリゲート

たいていのインスタンスでは、プラグインはHoudini Engineと非同期でやり取りします。 つまり、操作が完了した後にコールバックを受け取るには、デリゲートをバインドする必要があります。

パラメータインターフェースの準備が整ったら、最初のクックの前に、OnPreInstantiationDelegateをバインドしてパラメータを設定します。

Note

これは、最も早いタイミングでのパラメータ設定ですが、必ずしも必要ではありません。 HDAをインスタンス化してクックし、パラメータを設定して、再クックすることも可能です。 HDAのクックに長い時間がかかる場合は、デリゲートをいくつか効率的に使用して、負荷の大きい再クックを避けることをお勧めします。

クラスACurveInputExampleを使用すると、一部の関数をデリゲートにバインドして、パラメータおよび/または入力を設定できます。

C++:

void ACurveInputExample::RunCurveInputExample_Implementation()
{
    // APIインスタンスを取得します。
    UHoudiniPublicAPI* const API = UHoudiniPublicAPIBlueprintLib::GetAPI();
    // 確実にセッションが実行するようにします。
    if (!API->IsSessionValid())
        API->CreateSession();
    // HDA uassetをロードします。
    UHoudiniAsset* const ExampleHDA = Cast<UHoudiniAsset>(StaticLoadObject(UHoudiniAsset::StaticClass(), nullptr, TEXT("/HoudiniEngine/Examples/hda/copy_to_curve_1_0.copy_to_curve_1_0")));
    // HDAをインスタンス化してそれを操作できるようにAPIラッパーインスタンスを作成します。
    AssetWrapper = API->InstantiateAsset(ExampleHDA, FTransform::Identity);
    if (IsValid(AssetWrapper))
    {
        // インスタンス化前が、パラメータ値を設定できる最も早いタイミングです。
        AssetWrapper->GetOnPreInstantiationDelegate().AddUniqueDynamic(this, &ACurveInputExample::SetInitialParameterValues);
        // もう少し後で: 入力を設定する必要もありますが、入力を使用できるのはインスタンス化後です。
        AssetWrapper->GetOnPostInstantiationDelegate().AddUniqueDynamic(this, &ACurveInputExample::SetInputs);
        // もう少し後で: また、ノードをクックしてプラグインが出力を処理した後、出力を表示する必要もあります。
        AssetWrapper->GetOnPostProcessingDelegate().AddUniqueDynamic(this, &ACurveInputExample::PrintOutputs);
    }
}

Note

この例では、インスタンス化前にパラメータを設定し、インスタンス化後に入力を設定しています。 インスタンス化後にパラメータと入力を設定することもできます。

ブループリント:

Python:

def run_curve_input_example(self):
    # APIインスタンスを取得します。
    api = unreal.HoudiniPublicAPIBlueprintLib.get_api()
    # 確実にセッションが実行するようにします。
    if not api.is_session_valid():
        api.create_session()
    # HDA uassetをロードします。
    example_hda = unreal.load_object(None, '/HoudiniEngine/Examples/hda/copy_to_curve_1_0.copy_to_curve_1_0')
    # HDAをインスタンス化してそれを操作できるようにAPIラッパーインスタンスを作成します。
    self._asset_wrapper = api.instantiate_asset(example_hda, instantiate_at=unreal.Transform())
    if self._asset_wrapper:
        # インスタンス化前が、パラメータ値を設定できる最も早いタイミングです。
        self._asset_wrapper.on_pre_instantiation_delegate.add_callable(self._set_initial_parameter_values)
        # もう少し後で: 入力を設定する必要もありますが、入力を使用できるのはインスタンス化後です。
        self._asset_wrapper.on_post_instantiation_delegate.add_callable(self._set_inputs)
        # もう少し後で: また、ノードをクックしてプラグインが出力を処理した後、出力を表示する必要もあります。
        self._asset_wrapper.on_post_processing_delegate.add_callable(self._print_outputs)

パラメータの設定

HDAのインスタンス化前の段階で、2つのパラメータを設定します:

  • upvectoratstartfalse

  • scale0.2

デリゲートでは、インスタンス化前のデリゲートにSetInitialParameterValues()関数をバインドしました。 これによって、その関数を実装することでパラメータ値が設定できるようになりました。

C++:

#pragma once
#include "CoreMinimal.h"
#include "EditorUtilityActor.h"
#include "CurveInputExample.generated.h"
class UHoudiniPublicAPIAssetWrapper;
UCLASS()
class HOUDINIENGINEEDITOR_API ACurveInputExample : public AEditorUtilityActor
{
    GENERATED_BODY()
public:
    ACurveInputExample();

    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, CallInEditor)
    void RunCurveInputExample();
protected:
    // 初期パラメータ値を設定: upvectorstartを無効にし、スケールを0.2に設定します。
    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, CallInEditor)
    void SetInitialParameterValues(UHoudiniPublicAPIAssetWrapper* InWrapper);
    // 入力を設定: 入力0は立方体、入力1は螺旋にします。
    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, CallInEditor)
    void SetInputs(UHoudiniPublicAPIAssetWrapper* InWrapper);
    // HDAによって生成された出力を表示します(クック後)。
    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, CallInEditor)
    void PrintOutputs(UHoudiniPublicAPIAssetWrapper* InWrapper);
    UPROPERTY(BlueprintReadWrite)
    UHoudiniPublicAPIAssetWrapper* AssetWrapper;
};
void ACurveInputExample::SetInitialParameterValues_Implementation(UHoudiniPublicAPIAssetWrapper* InWrapper)
{
    // upvectoratstartパラメータのチェックを外します。
    InWrapper->SetBoolParameterValue(TEXT("upvectoratstart"), false);
    // スケールを0.2に設定します。
    InWrapper->SetFloatParameterValue(TEXT("scale"), 0.2f);
    // 初期値の設定を完了したので、デリゲートからバインドを解除できます。
    InWrapper->GetOnPreInstantiationDelegate().RemoveDynamic(this, &ACurveInputExample::SetInitialParameterValues);
}

ブループリント:

Python:

import math
import unreal
@unreal.uclass()
class CurveInputExample(unreal.PlacedEditorUtilityBase):
    def __init__(self, *args, **kwargs):
        self._asset_wrapper = None
    def run_curve_input_example(self):
        ...
    def _set_initial_parameter_values(self, in_wrapper):
        """ 初期パラメータ値を設定: upvectorstartを無効にし、スケールを0.2に設定します。 """
        # upvectoratstartパラメータのチェックを外します。
        in_wrapper.set_bool_parameter_value('upvectoratstart', False)
        # スケールを0.2に設定します。
        in_wrapper.set_float_parameter_value('scale', 0.2)
        # 初期値の設定を完了したので、デリゲートからバインドを解除できます。
        in_wrapper.on_pre_instantiation_delegate.remove_callable(self._set_initial_parameter_values)
    def _set_inputs(self, in_wrapper):
        """ 入力を設定: 入力0は立方体、入力1は螺旋にします。 """
        raise NotImplementedError
    def _print_outputs(self, in_wrapper):
        """ HDAによって生成された出力を表示します(クック後)。 """
        raise NotImplementedError

プラグインがHDAのインスタンス化プロセスを開始すると、パラメータが設定され、最初のクックの準備が整います。

入力の作成

ラップされ、インスタンス化されたHDAに入力を設定するには、適切な入力クラスをインスタンス化してから、入力オブジェクトと設定を入力に設定する必要があります。

UHoudiniPublicAPIAssetWrapper::CreateEmptyInput()関数を使用して、入力をインスタンス化します。 関数は、入力のクラスを唯一の引数として受け取ります。この例では、ジオメトリおよびカーブ入力を作成します。

ジオメトリ入力を作成するには:

  1. CreateEmptyInput()と入力し、新しい入力をインスタンス化します。

  2. その入力オブジェクトとして立方体アセットを設定します。

  3. インスタンス化されたHDAに入力を設定します。

C++:

void ACurveInputExample::SetInputs_Implementation(UHoudiniPublicAPIAssetWrapper* InWrapper)
{
    // 空っぽのジオメトリ入力を作成します。
    UHoudiniPublicAPIGeoInput* const GeoInput = Cast<UHoudiniPublicAPIGeoInput>(InWrapper->CreateEmptyInput(UHoudiniPublicAPIGeoInput::StaticClass()));
    // 立方体のスタティックメッシュアセットをロードします。
    UStaticMesh* const Cube = Cast<UStaticMesh>(StaticLoadObject(UStaticMesh::StaticClass(), nullptr, TEXT("/Engine/BasicShapes/Cube.Cube")));
    // ジオメトリ入力に入力オブジェクト配列を設定します(この場合は立方体のみを含んでいます)。
    GeoInput->SetInputObjects({Cube});
    // ラッパーを介してインスタンス化されたHDAに入力を設定します。
    InWrapper->SetInputAtIndex(0, GeoInput);
    // やること: カーブ入力を作成する
    // 初期値の設定を完了したので、デリゲートからバインドを解除できます。
    InWrapper->GetOnPostInstantiationDelegate().RemoveDynamic(this, &ACurveInputExample::SetInputs);
}

ブループリント:

Python:

class CurveInputExample(unreal.PlacedEditorUtilityBase):
    ... 
    def _set_inputs(self, in_wrapper):
        """ 入力を設定: 入力0は立方体、入力1は螺旋にします。 """
        # 空っぽのジオメトリ入力を作成します。
        geo_input = in_wrapper.create_empty_input(unreal.HoudiniPublicAPIGeoInput)
        # 立方体のスタティックメッシュアセットをロードします。
        cube = unreal.load_object(None, '/Engine/BasicShapes/Cube.Cube')
        # ジオメトリ入力に入力オブジェクト配列を設定します(この場合は立方体のみを含んでいます)。
        geo_input.set_input_objects((cube, ))
        # ラッパーを介してインスタンス化されたHDAに入力を設定します。
        in_wrapper.set_input_at_index(0, geo_input)
        # やること: カーブ入力を作成する
        # 入力の設定を完了したので、デリゲートからバインドを解除できます。
        in_wrapper.on_post_instantiation_delegate.remove_callable(self._set_inputs)

カーブ入力

カーブ入力を作成するには:

  1. CreateEmptyInput()と入力し、新しい入力をインスタンス化します。

  2. UHoudiniPublicAPICurveInputObjectを作成します。

  3. UHoudiniPublicAPICurveInputObjectにカーブポイントを追加します。

  4. カーブ入力に、入力オブジェクトとしてカーブオブジェクトを設定します。

  5. インスタンス化されたHDAに入力を設定します。

Note

APIカーブ入力は、入力オブジェクトとしてUHoudiniPublicAPICurveInputObjectに制限されていません。 また、入力オブジェクトとしてUHoudiniSplineComponentインスタンスもサポートしています。

C++:

void ACurveInputExample::SetInputs_Implementation(UHoudiniPublicAPIAssetWrapper* InWrapper)
{
    // 空っぽのジオメトリ入力を作成します。
    ...
    // 空っぽのカーブ入力を作成します。
    UHoudiniPublicAPICurveInput* const CurveInput = InWrapper->CreateEmptyInput(UHoudiniPublicAPICurveInput::StaticClass());
    // カーブ入力オブジェクトを作成します。
    UHoudiniPublicAPICurveInputObject* const CurveObject = Cast<UHoudiniPublicAPICurveInput>(NewObject<UHoudiniPublicAPICurveInputObject>(CurveInput));
    // それをNURBSカーブにします。
    CurveObject->SetCurveType(EHoudiniPublicAPICurveType::Nurbs)
    // カーブのポイントを設定します。この例では、100ポイントで構成される螺旋を作成します。
    TArray<FTransform> CurvePoints;
    CurvePoints.Reserve(100);
    for (int32 i = 0; i < 100; ++i)
    {
        const float t = i / 20.0f * PI * 2.0f;
        const float x = 100.0f * cos(t);
        const float y = 100.0f * sin(t);
        const float z = i;
        CurvePoints.Emplace(FTransform(FVector(x, y, z)));
    }
    CurveObject->SetCurvePoints(CurvePoints);
    // 入力オブジェクトとしてカーブラッパーを設定します。
    CurveInput->SetInputObjects({CurveObject});
    // ノード入力1として、入力データをHDAにコピーします。
    InWrapper->SetInputAtIndex(1, CurveInput);
    // 初期値の設定を完了したので、デリゲートからバインドを解除できます。
    InWrapper->GetOnPostInstantiationDelegate().RemoveDynamic(this, &ACurveInputExample::SetInputs);
}

ブループリント:

Python:

class CurveInputExample(unreal.PlacedEditorUtilityBase):
    ... 
    def _set_inputs(self, in_wrapper):
        """ 入力を設定: 入力0は立方体、入力1は螺旋にします。 """
        # 空っぽのジオメトリ入力を作成します。
        ...

        # カーブ入力を作成します。
        curve_input = in_wrapper.create_empty_input(unreal.HoudiniPublicAPICurveInput)
        # カーブラッパー/ヘルパーを作成します。
        curve_object = unreal.HoudiniPublicAPICurveInputObject(curve_input)
        # それをNURBSカーブにします。
        curve_object.set_curve_type(unreal.HoudiniPublicAPICurveType.NURBS)
        # カーブのポイントを設定します。
        # この例では、100ポイントで構成される螺旋を作成します。
        curve_points = []
        for i in range(100):
            t = i / 20.0 * math.pi * 2.0
            x = 100.0 * math.cos(t)
            y = 100.0 * math.sin(t)
            z = i
            curve_points.append(unreal.Transform([x, y, z], [0, 0, 0], [1, 1, 1]))
        curve_object.set_curve_points(curve_points)
        # 入力オブジェクトとしてカーブラッパーを設定します。
        curve_input.set_input_objects((curve_object, ))
        # ノード入力1として、入力データをHDAにコピーします。
        in_wrapper.set_input_at_index(1, curve_input)

        # 入力の設定を完了したので、デリゲートからバインドを解除できます。
        in_wrapper.on_post_instantiation_delegate.remove_callable(self._set_inputs)

ラップされたアセットの既存の入力を取得するには、ノード入力とパラメータベースの入力にGetInputAtIndex()関数とGetInputParameter()関数を使用します。

まとめ

例のまとめ:

  • Houdini Public APIインスタンス で、Houdini Engineセッションが実行されていることを確認し、HDAのインスタンス化プロセスを開始します。

  • デリゲート では、デリゲートを使用して、カスタム関数をHDAのインスタンス化前およびインスタンス後の段階にバインドします。

  • パラメータ では、インスタンス化前の段階でHDAのパラメータを設定します。

  • 入力 では、インスタンス後の段階でHDAに入力を作成および設定します。

この時点で、プラグインはHDAの処理を非同期で継続し、Houdiniにパラメータと入力を送ります。Houdiniがノードをクックしたら、結果の出力を受け取って出力(メッシュ、マテリアル)を作成します。

Unrealビューポートでの例の結果:

Detailsパネル(入力と変更されたパラメータ値に注目してください):

出力

このセクションでは、HDAがクックされ、出力オブジェクトおよびアセットを処理した後に、HDAの出力にアクセスする方法を説明します。

  1. OnPostProcessingDelegateにバインドし(デリゲートで実行済み)、

  2. すべての出力をイテレートして、出力オブジェクトとコンポーネント名を表示し、

  3. 出力オブジェクトがプロキシであるかどうかを表示します。

C++:

void ACurveInputExample::PrintOutputs_Implementation(UHoudiniPublicAPIAssetWrapper* InWrapper)
{
    // HDAによって生成されたすべての出力を表示します。
    const int32 NumOutputs = InWrapper->GetNumOutputs();
    UE_LOG(LogTemp, Log, TEXT("NumOutputs: %d"), NumOutputs);
    if (NumOutputs > 0)
    {
        for (int32 OutputIndex = 0; OutputIndex < NumOutputs; ++OutputIndex)
        {
            TArray<FHoudiniPublicAPIOutputObjectIdentifier> Identifiers;
            InWrapper->GetOutputIdentifiersAt(OutputIndex, Identifiers);
            UE_LOG(LogTemp, Log, TEXT("\toutput index: %d"), OutputIndex);
            UE_LOG(LogTemp, Log, TEXT("\toutput type: %d"), InWrapper->GetOutputTypeAt(OutputIndex));
            UE_LOG(LogTemp, Log, TEXT("\tnum_output_objects: %d"), Identifiers.Num());
            if (Identifiers.Num() > 0)
            {
                for (const FHoudiniPublicAPIOutputObjectIdentifier& Identifier : Identifiers)
                {
                    UObject* const OutputObject = InWrapper->GetOutputObjectAt(OutputIndex, Identifier);
                    UObject* const OutputComponent = InWrapper->GetOutputComponentAt(OutputIndex, Identifier);
                    const bool bIsProxy = InWrapper->IsOutputCurrentProxyAt(OutputIndex, Identifier);
                    UE_LOG(LogTemp, Log, TEXT("\t\tidentifier: %s_%s"), *(Identifier.PartName), *(Identifier.SplitIdentifier));
                    UE_LOG(LogTemp, Log, TEXT("\t\toutput_object: %s"), IsValid(OutputObject) ? *(OutputObject->GetFName().ToString()) : TEXT("None"))
                    UE_LOG(LogTemp, Log, TEXT("\t\toutput_component: %s"), IsValid(OutputComponent) ? *(OutputComponent->GetFName().ToString()) : TEXT("None"))
                    UE_LOG(LogTemp, Log, TEXT("\t\tis_proxy: %d"), bIsProxy)
                    UE_LOG(LogTemp, Log, TEXT(""))
                }
            }
        }
    }
}

ブループリント:

Python:

class CurveInputExample(unreal.PlacedEditorUtilityBase):
    ... 
    def _print_outputs(self, in_wrapper):
        """  HDAによって生成された出力を表示します(クック後)。 """
        num_outputs = in_wrapper.get_num_outputs()
        print('num_outputs: {}'.format(num_outputs))
        if num_outputs > 0:
            for output_idx in range(num_outputs):
                identifiers = in_wrapper.get_output_identifiers_at(output_idx)
                print('\toutput index: {}'.format(output_idx))
                print('\toutput type: {}'.format(in_wrapper.get_output_type_at(output_idx)))
                print('\tnum_output_objects: {}'.format(len(identifiers)))
                if identifiers:
                    for identifier in identifiers:
                        output_object = in_wrapper.get_output_object_at(output_idx, identifier)
                        output_component = in_wrapper.get_output_component_at(output_idx, identifier)
                        is_proxy = in_wrapper.is_output_current_proxy_at(output_idx, identifier)
                        print('\t\tidentifier: {}'.format(identifier))
                        print('\t\toutput_object: {}'.format(output_object.get_name() if output_object else 'None'))
                        print('\t\toutput_component: {}'.format(output_component.get_name() if output_component else 'None'))
                        print('\t\tis_proxy: {}'.format(is_proxy))
                        print('')

出力をベイクする

UHoudiniPublicAPIAssetWrapperクラスも出力のベイクをサポートしています。

ベイクする方法は3通りあります:

  1. 自動ベイクを有効にします。これは、クック後に出力を自動的にベイクし、インスタンス化されたHDAに設定されたベイク設定を使用します。

  2. HDAのすべての出力を手動でベイクします。

  3. 出力インデックスおよび識別子によって識別された特定の出力オブジェクトのみベイクします。

詳細は、出力をベイクするを参照してください。

次のステップ

ブループリント/Pythonバージョンの非同期プロセス、コンテンツサンプル、Public APIのコマンドリストに関する詳細は、Public APIドキュメントを参照してください。

Unreal

はじめよう

基本

Houdini Engineを使用する

リファレンス

Houdini Engine for Unreal Engineは、HoudiniのテクノロジーをUnrealに統合できるプラグインです。 Session SyncとNode Syncは、Houdiniのライブセッションと相互作用するためのHoudini Engineプラグインの2つの機能です。

このプラグインを使用すると、Houdiniの強力かつ柔軟なプロシージャルワークフローを、Houdiniデジタルアセットを通してUnreal Engineで実現できます。 アーティストはエディタ内でアセットパラメータをインタラクティブに調整して、Unrealアセットを入力として使用することができます。 その後、Houdiniのプロシージャルエンジンがアセットを“クック”し、その結果をエディタで使用できるようになります。ベイクする必要はありません。

一般情報:

互換性:

現在のところ、プラグインにはUE5.3、5.2、5.1、5.0、UE4.27、UE4.26向けにビルドされたバイナリがあり、Houdiniの最新のプロダクションビルドにリンクされています。

プラグインのソースコードは、UE5.3、5.2、5.1、5.0、UE4.27、UE4.26のこのリポジトリで利用可能です。

Note

UE5.1およびUE5.0は、同じソースファイル/ブランチを使用し、5.0ソースは5.1でも使用できるようになっています。

サポートおよびバグのレポート:

便利なリンク:

SessionSync

Houdini Engine SessionSync機能を使用すると、GUIを使ってHoudini内で実行されているHoudini Engineのセッションに接続することができます。 通常のHoudini Engineワークフローのすべての機能と、Session Sync固有の追加機能をサポートしています。

Houdini Engineは非UIバージョンのHoudiniを使用しますが、Session SyncではHoudiniのユーザインターフェースを通してHoudiniセッションを確認したり、操作することができます。 また、UnrealやHoudiniで加えた変更は同期されるため、どちらのプログラムでも変更を加えても、同じ結果が得られます。

NodeSync

NodeSyncは、UnrealとHoudini Session Sync間のアセット共有を可能にする、Houdini Engine for Unrealプラグインの機能です。スケルタルメッシュとスタティックメッシュで機能します。

専用のHDAを使用することなく、Unrealにデータを送信したり、Unrealからデータを受信することができます。アクターに加えて、スタティックメッシュやスケルタルメッシュでも機能します。

Houdini Niagara

Houdini-Niagaraプラグインを使用すると、HoudiniNiagara Data Interfaceを使用して、HoudiniとUnrealのNiagaraシステム間でポイントクラウドデータを交換することができます。 Houdiniのアトリビュートデータを、HoudiniPointCacheアセットとしてエクスポートできます。 これらをUnrealにインポートし、Niagaraシステムとエミッターを使用して、複雑なエフェクトやパーティクルシステムを作成できます。