Search - User list
Full Version: New Houdini Engine for Unity feature: Attributes Store
Root » Houdini Engine for Unity » New Houdini Engine for Unity feature: Attributes Store
seelan
In Houdini 18.0.311 and newer, a new feature was added to store any attributes of a SOP in the output gameobject as a script component (HEU_OutputAttributesStore). More info provided in the online documentation:

https://www.sidefx.com/docs/unity/_attributes.html#AttributesStore [www.sidefx.com]

This is a useful feature, especially when combined with a script callback to apply those attributes right after a cook. See the included example HDA (Assets/Plugins/HoudiniEngineUnity/HDAs/HEUInstanceAttributesStore.hda) which triggers a callback to query the health values on instances and set them as y-scale. You'll need to create a Cube prefab in Assets/Prefabs/Cube.prefab before instancing the example HDA in Unity.
sascha
Is the attribute store only accessible from the attached detail unity_script? I'm trying to access the HDA's OutputAttributesStore in a script on another game object (just an empty) but I guess I'm missing something:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HoudiniEngineUnity;

public class HEU_AttributesStore : MonoBehaviour
{
    void Start()
    {
        string attributesStoreAssetPath = "Assets/Plugins/HoudiniEngineUnity/HDAs/HEUInstanceAttributesStore.hda";
        string attributesStoreFullPath = HEU_AssetDatabase.GetAssetFullPath(attributesStoreAssetPath);
        if (string.IsNullOrEmpty(attributesStoreFullPath))
        {
            Debug.LogErrorFormat("Unable to load asset at path: {0}", attributesStoreAssetPath);
            return;
        }

        HEU_SessionBase session = HEU_SessionManager.GetOrCreateDefaultSession();

        GameObject rootGO = HEU_HAPIUtility.InstantiateHDA(attributesStoreFullPath, Vector3.zero, session, true);
        if (rootGO != null)
        {
            HEU_EditorUtility.SelectObject(rootGO);
        }

        HEU_HoudiniAsset houdiniAsset = QueryHoudiniAsset(rootGO);
        if (houdiniAsset == null)
        {
            return;
        }

        CookAsset(houdiniAsset);

        HEU_OutputAttributesStore attrStore = houdiniAsset.GetComponent<HEU_OutputAttributesStore>();
        if (attrStore == null)
        {
            Debug.LogWarning("No HEU_OutputAttributesStore component found!");
            return;
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public static HEU_HoudiniAsset QueryHoudiniAsset(GameObject rootGO)
    {
        HEU_HoudiniAssetRoot heuRoot = rootGO.GetComponent<HEU_HoudiniAssetRoot>();
        if (heuRoot == null)
        {
            Debug.LogWarningFormat("Unable to get the HEU_HoudiniAssetRoot from gameobject: {0}. Not a valid HDA.", rootGO.name);
            return null;
        }

        if (heuRoot._houdiniAsset == null)
        {
            Debug.LogWarningFormat("Unable to get the HEU_HoudiniAsset in root gameobject: {0}. Not a valid HDA.", rootGO.name);
            return null;
        }

        return heuRoot._houdiniAsset;
    }

    public static void CookAsset(HEU_HoudiniAsset houdiniAsset)
    {
        houdiniAsset.RequestCook(bCheckParametersChanged: true, bAsync: false, bSkipCookCheck: true, bUploadParameters: true);
    }
}

So far I only got:
No HEU_OutputAttributesStore component found!

How do I get access to the OutputAttributesStore?

PS: The script above should work in any vanilla Unity project with HEU installed, just attach it to an empty and hit play. I used Unity 2019.3.13f and Houdini 18.0.463.
seelan
You should be able to access it from any script, as long as you have access to the HEU_HoudiniAsset component.
Note that your HDA has to output a valid geometry, I believe. If you HDA does output that, and has attribute with name hengine_attr_store of class Detail and type String, then it should work.

Attach your HDA if you are still having a problem.
seelan
Apologies, I should have check out your sample code. I see what you're trying to do now. Unfortunately, there are 2 problems with it.

First, I believe when transitioning to play mode, the internal attribute data is stored as a Dictionary which is likely being cleared during the code domain reload. So don't use play mode for getting the attributes.

Second, the HEU_HoudiniAsset.GetAttributesStores() function returns the attribute store on the HDA. This is different from the output attribute store (HEU_OutputAttributesStore) which is for each output geometry. To get those, you need to get the output GameObjects, and get the HEU_OutputAttributesStore component on them. See below code. The rootGO is your HDA root gameobject.

HEU_HoudiniAsset houdiniAsset = QueryHoudiniAsset(rootGO);

List<GameObject> outputGOs = new List<GameObject>();
houdiniAsset.GetOutputGameObjects(outputGOs);

HEU_OutputAttributesStore attrStore = outputGOs[0].GetComponent<HEU_OutputAttributesStore>();
if (attrStore == null)
{
    Debug.LogWarning("No HEU_OutputAttributesStore component found!");
    return;
}

Check HEU_ExampleInstanceCustomAttribute.cs which has more example code.
sascha
seelan
Attach your HDA if you are still having a problem.
The HDA I used is one that ships with HEU examples: HEUInstanceAttributesStore.hda
sascha
seelan
Apologies, I should have check out your sample code. I see what you're trying to do now. Unfortunately, there are 2 problems with it.

First, I believe when transitioning to play mode, the internal attribute data is stored as a Dictionary which is likely being cleared during the code domain reload. So don't use play mode for getting the attributes.

Second, the HEU_HoudiniAsset.GetAttributesStores() function returns the attribute store on the HDA. This is different from the output attribute store (HEU_OutputAttributesStore) which is for each output geometry. To get those, you need to get the output GameObjects, and get the HEU_OutputAttributesStore component on them. See below code. The rootGO is your HDA root gameobject.

HEU_HoudiniAsset houdiniAsset = QueryHoudiniAsset(rootGO);

List<GameObject> outputGOs = new List<GameObject>();
houdiniAsset.GetOutputGameObjects(outputGOs);

HEU_OutputAttributesStore attrStore = outputGOs[0].GetComponent<HEU_OutputAttributesStore>();
if (attrStore == null)
{
    Debug.LogWarning("No HEU_OutputAttributesStore component found!");
    return;
}

Check HEU_ExampleInstanceCustomAttribute.cs which has more example code.

Thanks for the detailed reply!

Actually the dictionary doesn't seem to get cleared in play mode, at least not my my project right now. Though I'm not pursuing that route.

By the way, does the HEU_OutputAttribute support vector values? I guess not but floats work just fine…
seelan
Sorry, the issue was indeed due to the serialization. Since it stored as dictionary, on code domain reload, its being cleared. This will be fixed in next daily build (Houdini 18.0.472).
seelan
Yes vector values are supported. The next daily build will also add a “tupleSize” field to HEU_OutputAttribute so that you can get the vector size.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB