Houdini 20.0 Unreal

Public API

A list and commands for different Public APIs for Unreal

On this page

The public API is available for C++, Blueprints, and Python.

The public API supports the following:

Houdini Public API Instance

The class UHoudiniPublicAPI provides some functions to control the session and instantiate Houdini asset actors.

Command

Function

IsSessionValid

Returns true if a valid Houdini Engine session is running/connected

CreateSession

Start a new Houdini Engine Session if there is no current session

StopSession

Stops the current Houdini Engine session

RestartSession

Stops, then creates a new Houdini Engine session

InstantiateAsset

Instantiates an HDA in the specified world/level. Returns a wrapper for instantiated asset. See Instantiating HDAs

IsAssetCookingPaused

Returns true if asset cooking is paused

PauseAssetCooking

Pause asset cooking (if not already paused)

ResumeAssetCooking

Resume asset cooking (if it was paused)

CreateEmptyInput

Create a new empty API input object. The user must populate it and then set it as an input on an asset wrapper. See Inputs. See Inputs

Instantiating HDAs

The InstantiateAsset function returns an API wrapper class (UHoudiniPublicAPIAssetWrapper) to interact with the instantiated HDA

Warning

The Public API does not manage the lifecycle of the UHoudiniPublicAPIAssetWrapper after creation with InstantiateAsset. Use a UProperty or Blueprint variable to prevent unexpected garbage collection of the wrapper.

Command

Function

InHoudiniAsset

The HDA uasset to instantiate

InInstantiateAt

The Transform to instantiate the HDA actor

InWorldContextObject

A world context object for identifying the world to spawn, if InSpawnInLevelOverride is null

InSpawnInLevelOverride

If not nullptr, then the AHoudiniAssetActor is spawned in that level. If both InSpawnInLevelOverride and InWorldContextObject are null, then the actor is spawned in the current editor context world’s current level.

bInEnableAutoCook

If true (the default) the HDA cooks automatically after instantiation and after parameter, transform, and input changes

bInEnableAutoBake

If true, the HDA output is automatically baked after a cook. Default is false

InBakeDirectoryPath

The directory to bake to if the bake path is not set in attributes on the HDA output

InBakeMethod

The bake target (to actor vs blueprint)

bInRemoveOutputAfterBake

If true, HDA temporary outputs are removed after a bake. Default is false

bInRecenterBakedActors

Recenter the baked actors to their bounding box center. Default is false

bInReplacePreviousBake

If true, on every bake replace the previous bake’s output (assets and actors) with the new bake’s output. Default is false

Public API Asset Wrapper

The API wraps instantiated HDAs in instances of UHoudiniPublicAPIAssetWrapper. This class allows you to manipulate the instantiated HDA by setting parameters, inputs, cooking, baking, and accessing outputs.

Creating A Wrapper For An Existing HDA Actor

The Instantiating HDAs section discusses the InstantiateAsset function that instantiates a new HDA and returns a UHoudiniPublicAPIAssetWrapper, but you can also create a wrapper for an existing HDA actor/ component. The CreateWrapper static function of UHoudiniPublicAPIAssetWrapper (also available in editor utility blueprints as Create Wrapper) takes an existing HDA actor or component as an argument and creates and returns a UHoudiniPublicAPIAssetWrapper that wraps the specified HDA actor / component.

Alternatively, you can also use the CreateEmptyWrapper function to create a UHoudiniPublicAPIAssetWrapper that does not initially wrap any HDA actor/component. You can then use the WrapHoudiniAssetObject function of UHoudiniPublicAPIAssetWrapper to wrap an existing HDA actor/component with the wrapper.

Warning

The Public API does not manage the lifecycle of the UHoudiniPublicAPIAssetWrapper after creation with CreateEmptyWrapper or CreateWrapper. Use a UProperty or Blueprint variable to prevent unexpected garbage collection of the wrapper.

Delegates

In many cases, plugin interacts with the Houdini Engine asynchrously. This means after an operation completes, you need to bind to a delegate to recieve a callback.

An example is if you want to change a parameter, the node cooks then fetches the output. You need to bind to the proper delegate to receive a callback once the process completes.

Command

Function

OnPostInstantiationDelegate

Broadcast before an HDA is instantiated. The HDA’s default parameters are available and can be set

OnPostInstantiationDelegate

Broadcast after the asset was successfully instantiated. Recommended to set/configure inputs before the first cook

OnPostCookDelegate

Broadcast after a cook completes. Output objects/assets not yet created or updated

OnPreProcessStateExitedDelegate

Broadcast at the end of the pre-processing phase (after a cook). Output objects/assets not yet created or updated

OnPostProcessingDelegate

Broadcast after output processing in Unreal. Output objects/assets not yet created or updated

OnPostBakeDelegate

Broadcast after baking the asset (not called for individual outputs baked to the content browser)

OnPostPDGTOPNetworkCookDelegate

Broadcast after a cook of a TOP network completes. Work item results not necessarily loaded

OnPostPDGBakeDelegate

Broadcast after baking PDG outputs (not called for individual outputs baked to the content browser)

OnProxyMeshesRefinedDelegate

Broadcast after refining all proxy meshes for this wrapped asset

Note

In blueprints the public API is only available in editor utility graphs: any blueprint event or function bound to a delegate must have Call In Editor enabled otherwise the event/function will not execute when broadcasting the delegate.

Parameters

The following functions can set and get parameter values of a named parameter tuple. The parameter tuple name is a required argument and the index of the parameter in the tuple is optional (default to 0).

Command

Function

SetFloatParameterValue

Set the value of a float parameter

GetFloatParameterValue

Get the value of a float parameter

SetColorParameterValue

Set the value of a float parameter

GetColorParameterValue

Get the value of a float parameter

SetIntParameterValue

Set the value of a integer parameter

GetIntParameterValue

Get the value of a integer parameter

SetBoolParameterValue

Set the value of a boolean/toggle parameter

GetBoolParameterValue

Get the value of a boolean/toggle parameter

SetStringParameterValue

Set the value of a string parameter

GetStringParameterValue

Get the value of a string parameter

SetAssetRefParameterValue

Set the value of string parameter from a UObject as an asset reference

GetAssetRefParameterValue

Get the UObject instance referenced by a string parameter

TriggerButtonParameter

Executes the callback script of a button parameter

GetParameterTuples

Gets the values of all parameter tuples as an array of structs

SetParameterTuples

Sets the values of the parameter tuples in the given array of structs

The following functions help simplify working with ramp parameters:

Command

Function

SetRampParameterNumPoints

Set the number of points of ramp parameter

GetRampParameterNumPoints

Get the number of points of ramp parameter

SetFloatRampParameterPointValue

Set the point position, value and interpolation of a float ramp point by index

GetFloatRampParameterPointValue

Get the point position, value and interpolation of a float ramp point by index

SetFloatRampParameterPoints

Set all of the points of a float ramp parameter from an array

GetFloatRampParameterPoints

Get all of the points of a float ramp parameter as an array.

SetColorRampParameterPointValue

Set the point position, value and interpolation of a color ramp point by index

GetColorRampParameterPointValue

Get the point position, value and interpolation of a color ramp point by index

SetColorRampParameterPoints

Set all of the points of a color ramp parameter from an array

GetColorRampParameterPoints

Get all of the points of a color ramp parameter as an array.

Inputs

Inputs types are supported in API wrapper classes.

To set an input on a wrapped instantiated HDA, instantiate the appropriate input class and then set the input objects and settings. You can instantiate inputs using the UHoudiniPublicAPIAssetWrapper::CreateEmptyInput() function. The function takes the input’s class as its only argument.

Command

Function

UHoudiniPublicAPIInput

The base class of the inputs, only use this to create subclasses for new input types

UHoudiniPublicAPIGeoInput

A geometry input

UHoudiniPublicAPICurveInput

A curve input

UHoudiniPublicAPIAssetInput

An asset input (using another instantiated asset as an input)

UHoudiniPublicAPIWorldInput

A world input: using an actor from the world as an input

UHoudiniPublicAPILandscapeInput

A landscape as an input

GetInputAtIndex()

Fetches the existing node input of a wrapped asset

GetInputParameter()

Fetches the existing parameter-based input of a wrapped asset

SetInputAtIndex()

Set the node input

SetInputParameter()

Set the parameter-based input

Note

The GetInputAtIndex() and GetInputParameter() functions return a copy of the input configuration of the wrapped asset. If you change the properties or input objects, the inputs of the wrapped asset does not automatically update. To apply the changes, the inputs have to be set again using SetInputAtIndex() or SetInputParameter().

Curve Inputs

Curve inputs have an additional helper class to construct a curve from points: UHoudiniPublicAPICurveInputObject. The object has functions to set or add curve points, where each point is represented by an FTransform.

Command

Function

SetCurvePoints

Set the curve points to the specified array of FTransforms

AppendCurvePoint

Append a point as an FTransform, to the curve

ClearCurvePoints

Remove all points from the curve

GetCurvePoints

Get the curve’s points as an array of FTransforms

You can also configure curve properties such as NURBS or Bezier and open or closed curves using UHoudiniPublicAPICurveInputObject with the following functions:

Command

Function

IsClosed

Returns true if the curve is closed

SetClosed

Set the curve as closed

IsReversed

Returns true if the curve is reversed

SetReversed

Set the curve as reversed

GetCurveType

Get the curve type as an enum (Polygon, NURBs, Bezier, Points): EHoudiniPublicAPICurveType

SetCurveType

Set the curve type using the EHoudiniPublicAPICurveType enum

GetCurveMethod

Get the curve method as an enum (CVs, Breakpoints, Freehand): EHoudiniPublicAPICurveMethod

SetCurveMethod

Set the curve method using an enum EHoudiniPublicAPICurveMethod

Outputs

The UHoudiniPublicAPIAssetWrapper class provides functions to access the HDA’s outputs after a cook:

Command

Function

GetNumOutputs

Returns the number of outputs for the HDA

GetOutputTypeAt

Returns the type of the output (EHoudiniOutputType: Mesh, Instancer, Landscape, Curve, Skeletal) at the given output index

GetOutputIdentifiersAt

Populates an array of FHoudiniPublicAPIOutputObjectIdentifier for a given output index. These identify individual objects in the output at the given index. For example, a rendered static mesh and its collision meshes

GetOutputObjectAt

Returns the output object at the given output index identified by the FHoudiniPublicAPIOutputObjectIdentifier. For example a UStaticMesh

GetOutputComponentAt

Returns the output component for the object at the given output index identified by the FHoudiniPublicAPIOutputObjectIdentifier. For example a UStaticMeshComponent

HasAnyCurrentProxyOutput

Returns true any output that contains any current proxy mesh

HasAnyCurrentProxyOutputAt

Returns true if the output is at the specified index

IsOutputCurrentProxyAt

Returns true if the output at the specified index and identifier is a current proxy

Baking Outputs

The UHoudiniPublicAPIAssetWrapper class also supports baking outputs.

There are three ways approach baking:

  1. Enable auto-bake which automatically bakes the output after a book and uses the bake settings configured on the instantiated HDA.

  2. Manually bake all outputs on an HDA

  3. Bake a specific output object only identified by its output index and identifier.

Command

Function

SetAutoBakeEnabled

Enables/disables auto-baking after a successful cook

IsAutoBakeEnabled

Returns true if auto-baking is enabled

Auto-baking will automatically bake the outputs after a cook and uses the bake settings configured on the instantiated HDA.

These settings can be queried or set using the following:

Command

Function

SetBakeMethod

Sets the bake method: bake to actors, blueprints, or foliage.

GetBakeMethod

Gets the bake method

SetRemoveOutputAfterBake

Enable/disable automatically removing temporary HDA output from the world after a bake

GetRemoveOutputAfterBake

Return true if temporary HDA output will be removed from the world after a bake

SetRecenterBakedActors

Enable/disable recentering baked output actors at their bounding box center

GetRecenterBakedActors

Returns true if recentering is enabled

SetReplacePreviousBake

Enable/disable bake replacement mode: if enabled the previous bake’s assets and actors are replaced (if names match)

GetReplacePreviousBake

Returns true if replacement mode is enabled

Manually bake all outputs of an HDA:

Command

Function

BakeAllOutputs

Bakes all outputs with the settings configured using the wrapper

BakeAllOutputsWithSettings

Nakes all outputs but the bake settings can be passed to the function, overriding settings configured on the wrapper

Bake a specific output object only identified by its output index and identifier.

Command

Function

BakeOutputObjectAt

Bakes the output object specified by its output index and indentifier

Blueprint Async Processor

The instantiation and cooking of the HDAs happen asynchonously in the plugin. Delegates help notify when HDA processing enters a certain phase or when cooking is complete. This means you have to manually bind and unbind delegates while writing scripts or tools using the API. To simplify this in Blueprints, the API also includes a Blueprint Async Action node: UHoudiniPublicAPIProcessHDANode or ProcessHDA.

The ProcessHDA node has all of the options of the UHoudiniPublicAPI::InstantiateAsset() function and also provides some quality of life features:

  • Accepts a map of FName to FHoudiniParameterTuple to set parameters without having to manually bind to delegates

  • Accepts a map of int32 to UHoudiniPublicAPIInput to set index-based node iputs without having to manually bind to delegates

  • Accepts a map of FName to UHoudiniPublicAPIInput to set parameter-based inputs without having to manually bind to delegates

  • A latent node with output pins that are bound to the various delegates such as OnPreInstantiateDelegate, OnPostInstantiateDelegate, and OnPostProcessDelegate which makes it easier to bind custom logic to these events.

A screenshot of the Process HDA node with the blueprint version of the curve input example. This is slightly modified so the MakeGeoInput and MakeCurveInput functions create and populate the UHoudiniPublicAPIGeoInput and UHoudiniPublicAPICurveInput.

Python Async Processor

Python is similar to the ProcessHDA Blueprint node. The ProcessHDA Python class is located in the HoudiniEngineV2.asyncprocessor module.

The ProcessHDA class constructor takes the same arguments as the Async Blueprint node. You start the processing by using the ProcessHDA.activate() function.

The difference is the ProcessHDA class has a function for each delegate:

  • on_failure

  • on_complete

  • on_pre_instantiation

  • on_post_instantiation

  • on_post_auto_cook

  • on_pre_process

  • on_post_processing

  • on_post_auto_bake

These are internally bound to a UHoudiniPublicAPIAssetWrapper and called when the delegate broadcasts. You can subclass the ProcessHDA class and override the above functions to implement their own functionality.

Here is our curve input example implemented as a subclass of the ProcessHDA:

import math
import unreal
from HoudiniEngineV2.asyncprocessor import ProcessHDA
_g_processor = None
class ProcessHDAExample(ProcessHDA):
    def on_failure(self):
        print('on_failure')
        global _g_processor
        _g_processor = None
    def on_complete(self):
        print('on_complete')
        global _g_processor
        _g_processor = None
    def on_post_processing(self):
        # Print out all outputs generated by the HDA
        num_outputs = self.asset_wrapper.get_num_outputs()
        print('num_outputs: {}'.format(num_outputs))
        if num_outputs > 0:
            for output_idx in range(num_outputs):
                identifiers = self.asset_wrapper.get_output_identifiers_at(output_idx)
                print('\toutput index: {}'.format(output_idx))
                print('\toutput type: {}'.format(self.asset_wrapper.get_output_type_at(output_idx)))
                print('\tnum_output_objects: {}'.format(len(identifiers)))
                if identifiers:
                    for identifier in identifiers:
                        output_object = self.asset_wrapper.get_output_object_at(output_idx, identifier)
                        output_component = self.asset_wrapper.get_output_component_at(output_idx, identifier)
                        is_proxy = self.asset_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('')
def make_geo_input():
    """ Makes a cube geometry input. """
    # get the API singleton
    houdini_api = unreal.HoudiniPublicAPIBlueprintLib.get_api()
    # Create a geo input
    geo_input = houdini_api.create_empty_input(unreal.HoudiniPublicAPIGeoInput)
    # Set the input objects/assets for this input
    geo_object = unreal.load_object(None, '/Engine/BasicShapes/Cube.Cube')
    geo_input.set_input_objects((geo_object, ))
    return geo_input
def make_curve_input():
    """ Makes a helix input curve. """
    # get the API singleton
    houdini_api = unreal.HoudiniPublicAPIBlueprintLib.get_api()
    # Create a curve input
    curve_input = houdini_api.create_empty_input(unreal.HoudiniPublicAPICurveInput)
    # Create a curve wrapper/helper
    curve_object = unreal.HoudiniPublicAPICurveInputObject(curve_input)
    # Make it a Nurbs curve
    curve_object.set_curve_type(unreal.HoudiniPublicAPICurveType.NURBS)
    # Set the points of the curve, for this example we create a helix
    # consisting of 100 points
    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)
    # Set the curve wrapper as an input object
    curve_input.set_input_objects((curve_object, ))
    return curve_input
def make_parameters():
    """ Make a dict of HoudiniParameterTuple containing `upvectoratstart` and
    `scale`.
    """
    parameters = {}
    parameter_tuple = unreal.HoudiniParameterTuple()
    parameter_tuple.bool_values = (False, )
    parameters['upvectoratstart'] = parameter_tuple
    parameter_tuple = unreal.HoudiniParameterTuple()
    parameter_tuple.float_values = (0.2, )
    parameters['scale'] = parameter_tuple
    return parameters
def run():
    # Create the processor with preconfigured inputs
    global _g_processor
    _g_processor = ProcessHDAExample(
        unreal.load_object(None, '/HoudiniEngine/Examples/hda/copy_to_curve_1_0.copy_to_curve_1_0'), 
        parameters=make_parameters(),
        node_inputs={0: make_geo_input(), 1: make_curve_input()},
    )
    # Activate the processor, this will start instantiation, and then cook
    if not _g_processor.activate():
        unreal.log_warning('Activation failed.')
    else:
        unreal.log('Activated!')
if __name__ == '__main__':
    run()

PDG/TOP Networks

The Public API supports interacting with the PDG asset link if an HDA contains one or more TOP networks.

There are two delegates for PDG related events:

Command

Function

GetOnPostPDGTOPNetworkCookDelegate()

Broadcast after cooking a TOP Network in the HDA. Work item results do not have to be loaded yet

GetOnPostPDGBakeDelegate()

Broadcast after baking PDG outputs

The following functions are available in UHoudiniPublicAPIAssetWrapper to interact with the PDG asset link:

Command

Function

HasPDGAssetLink()

Returns true if the wrapped asset is valid and has a PDG asset link

GetPDGTOPNetworkPaths()

Gets the paths (relative to the instantiated asset) of all TOP networks in the HDA

GetPDGTOPNodePaths()

Gets the paths (relative to the specified TOP network) of all TOP nodes in the network

PDGDirtyAllNetworks()

Dirty all TOP networks in this asset

PDGDirtyNetwork()

Dirty the specified TOP network

PDGDirtyNode()

Dirty the specified TOP node

PDGCookOutputsForNetwork()

Cook all outputs for the specified TOP network

PDGCookNode()

Cook the specified TOP node

PDGBakeAllOutputs()

Bake all outputs of the instantiated asset’s PDG contexts using the settings configured on the asset

PDGBakeAllOutputsWithSettings()

Bake all outputs of the instantiated asset’s PDG contexts using the specified settings

SetPDGAutoBakeEnabled()

Set whether to automatically bake PDG work items after a successfully loading them

IsPDGAutoBakeEnabled()

Returns true if PDG auto bake is enabled

SetPDGBakeMethod()

Sets the bake method to use for PDG baking (to actor, blueprint, foliage)

GetPDGBakeMethod()

Gets the currently set bake method to use for PDG baking (to actor, blueprint, foliage)

SetPDGBakeSelection()

Sets outputs to bake for PDG. For example all, selected network, and selected node.

GetPDGBakeSelection()

Get outputs to bake for PDG. For example all, selected network, and selected node.

SetPDGRecenterBakedActors()

Determines if baked actors are recentered to their bounding box center after a PDG bake on the PDG asset link.

GetPDGRecenterBakedActors()

Returns true if baked actors are recentered to their bounding box center after a PDG bake on the PDG asset link.

SetPDGBakingReplacementMode()

Set the replacement mode to use for PDG baking (replace previous bake output vs incrementing the output names)

GetPDGBakingReplacementMode()

Get the replacement mode to use for PDG baking

Note

PDG/TOP network cooking is not directly linked the HDAs cooking. If auto-cook is enabled for the HDA (or the asset was instantiated with bEnableAutoCook == true), PDG will not cook automatically. The auto-cook setting for the PDG asset link is not currently exposed via the public API, so the user must call PDGCookNode() or PDGCookOutputsForNetwork() to cook PDG.

Additional Examples

The content and examples directory of the plugin contains HDAs, Python scripts, Editor Utility Widget, and Editor Utility Actor examples.

The following C++ example is available: Command

Function

CurveInputExample.h and CurveInputExample.cpp

The ACurveInputExample in Instantiate HDA using API

The following Blueprint examples are available:

Command

Function

EUA_CurveInputExample

The blueprint example from Instantiate HDA using API

EUW_APIExample

An example editor utility widget with various options for instantiating and HDA and setting parameters

The following Python examples are available:

Command

Function

asset_input_example.py

An example script using asset inputs

bake_all_outputs_example.py

An example script that bakes all outputs of the HDA after a cook

bake_output_object_example.py

An example script that bakes a specific output object to the content browser after a cook

curve_input_example.py

Similar exmaple to Instantiate HDA using API using an input curve

eua_curve_input_example.py

The example Python script from Instantiate HDA using API

geo_input_example.py

An example scirpt for using geometry inputs

instances_example.py

Setting a parameter, cooking an HDA with instances as output

landscape_input_example.py

Using landscape inputs

outputs_example.py

TIterating over the outputs after cooking an HDA

pdg_example.py

Cooking and baking PDG output

process_hda_example.py

Using the ProcessHDA class to simplify delegate handling

ramp_parameter_example.py

Using the helper functions in the API for setting ramp parameter points

start_session_example.py

A simple example that starts the Houdini Engine session

world_input_example.py

Using world inputs

Error Messages

A common error in the public API is functions return a boolean to indicate success or failure. If an error occurred, the last error message can be retrieved with the GetLastErrorMessage() function.

This is available on any classes that derive from UHoudiniPublicAPIObjectBase such as UHoudiniPublicAPI, UHoudiniPublicAPIAssetWrapper, the input classes deriving from UHoudiniPublicAPIInput, and UHoudiniPublicAPICurveInputObject.

Unreal

Getting started

Basics

Using Houdini Engine

Reference

Houdini Engine for Unreal Engine is a plug-in that allows integration of Houdini technology into Unreal. Session Sync and Node Sync are two features of the Houdini Engine Plugin to interact with a live session of Houdini.

This plug-in brings Houdini’s powerful and flexible procedural workflow into Unreal Engine through Houdini Digital Assets. Artists can interactively adjust asset parameters inside the editor and use Unreal assets as inputs. Houdini’s procedural engine will then “cook” the asset and the results will be available in the editor without the need for baking.

General information:

Compatibility:

Currently, the plugins has binaries that have been built for UE5.3, 5.2, 5.1, 5.0, UE4.27 and UE4.26, and is linked with the latest production build of Houdini.

Source code for the plugin is available on this repository for UE5.3, 5.2, 5.1, 5.0, UE4.27, UE4.26.

Note

UE5.1 and UE5.0 use the same source files/branches, the 5.0 sources are also intended to be used with 5.1.

Support and reporting bugs:

SessionSync

The Houdini Engine SessionSync feature allows you to connect to a session of Houdini Engine running inside Houdini with its GUI. It supports all the features of the regular Houdini Engine workflow and additional features specific to Session Sync.

Houdini Engine uses a non-UI version of Houdini while Session Sync lets you see and interact with the Houdini session through Houdini’s user interface. It also synchronizes changes made in either Unreal or Houdini so both programs can make changes and see the same results.

NodeSync

NodeSync is a feature for the Houdini Unreal Engine Plugin that enables sharing assets between Unreal and Houdini Session Sync. It works for Skeletal and static meshes.

You can send and receive data to and from Unreal without a dedicated HDA. It works with Static and Skeletal meshes as well as Actors.

Houdini Niagara

The Houdini-Niagara plugin allows you to exchange point cloud data between Houdini and Unreal’s Niagara system using the HoudiniNiagara Data Interface. You can export Houdini’s attribute data as HoudiniPointCache assets. These can then be imported into Unreal to use the Niagara systems and emitters to create complex effects and particle systems.