Houdini Engine for Unityでインスタンスを配置する

# はじめに
![OpenWorld_SS01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230036/a30ea90a-5bed-1a29-fe24-092fd9e05179.jpeg)
先日**Houdini Engine for Unity**の使い方について講演をさせて頂きました。
講演ではHoudini Engineのインストールから、Houdini Engineを使ってUnityでインスタンスをプロシージャルに配置するところまでをご紹介しまして、その動画も既に公開されています。
この記事はその中でも特に有効な機能だと思っている**「Unityでのインスタンス配置」**について資料化したものです。Unityで作成したTerrainに対して、任意のPrefabオブジェクトのインスタンスを沢山配置する、という内容となります。
Houdini Engine for UnityのインストールやUnityに持ち込むHDAの作り方などの説明は本文では省略しますので、このあたりから知りたい方はぜひ動画も合わせてご覧ください。
[<img width = 600 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230036/5aa34995-1d1f-fb7a-3b4e-5fa8adf513ec.jpeg">](https://learning.unity3d.jp/4427/)
[**【Houdini Engine for Unityを使ってみよう ~インストールからインスタンス配置まで~】**](https://learning.unity3d.jp/4427/)
# サンプルプロジェクトについて
今回配布用のサンプルプロジェクトを作成しました。
[**Houdini Engine Instance Sample.zip**](https://drive.google.com/open?id=1EeHSJ-NZc97Kvn2tESjUo8j1sP-DCzde)
※サンプルはUnity 2019.3.0f3、Houdini Core 18.0.348で作成しています
※動作にはHoudini CoreまたはFXのライセンスが必要になります

サンプルでは、Unityで作ったTerrainに2種類の樹木を自動で配置しています。
また自動で配置するだけではなく、Unityでオブジェクトのインスペクタを操作する事で、
・樹木の本数を変えたり、
![数の増減.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230036/d3cb6665-031a-29c2-dcbf-25314def2f79.gif)
・樹木の種類が変わる高さを変えたり、
![種類切り替え.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230036/09426f4f-3f40-b7d1-c8c9-cd56e809479f.gif)

という事が出来るようになっています（実際にはパラメータを変更する度にHoudiniの処理が走るので画像ほど機敏には変更されません）。これらの手法を応用する事で、より柔軟なインスタンスの配置が出来るようになり、その結果として最初に載せた画像のような複雑な配置も可能となります。また自動配置の利点として配置元となるTerrainを編集してもその変化に即追随できるという事もあります。
![Terrainの変更.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230036/9f61559c-2767-e735-06c5-6496c6f88842.gif)

このサンプルの作成方法について解説します。

## 用意するもの（Unityプロジェクト)
*  Terrainで作った地形
*  低地用の樹木のPrefab (Assets/Prefab/tree.prefab)
*  高地用の樹木のPrefab (Assets/Prefab/pine.prefab)
![準備.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230036/1ae85351-14ce-025c-ace3-a4570d02a699.jpeg)
Terrainはシーン上に配置しておきます。2種類の樹木はUnityの[**ProBuilder**](https://unity3d.com/jp/unity/features/worldbuilding/probuilder)で作成しました。また配置するオブジェクトは元となるPrefabのパス(プロジェクトフォルダの中の場所)が重要になります。

## HoudiniでHDAを作成

Houdiniを使い、以下の流れでHDAを作成します。
![ノード.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230036/bc74e40e-6faa-2f18-2378-d0a15bc427f6.jpeg)

* **Subnetworkノードを作成。以降はSubnetwork内での作業**
* **Height Field Scatterを作成**
  * SubnetworkのInput1ノードを接続
  * Scatter Methodを`Total Point Count using Mask Layer`に変更
  * Total Point Countの値を`10000`に変更
* **Attribute Deleteノードを作成**
  * Height Field Scatterノードを接続
  * Point Attributesに`falloff,footprint,height,mask,N,tag,uv`を入力
* **Attribute Createノードを作成**
  * Attribute Deleteノードを接続
  * nameを`orient`、sizeを`4`に変更、Valueを`0` `0` `0` `1`に変更
  * nameを`pscale`、Valueを`1` `0` `0` `0`に変更
* **Attribute Wrangleノードを作成**
  * Attribute Createノードを接続
  * ノードにfloatパラメータを追加、nameとlabelを`threshold`に変更
  * VEXに以下のコードを記入

```
string @unity_instance = "Assets/Prefab/tree.prefab";
if (@T.y > `chs("threshold")`)
{
     string @unity_instance = "Assets/Prefab/pine.prefab";
}
```
ここまで出来たらSubNetworkの階層から一つ上のGeometory階層に上がります。

* **SubnetworkノードをHDA化**
  * Subnetworkノードを右クリック、メニューから**Create Digital Assets…**を選択
  * Save to LibraryにUnityプロジェクトAssets以下の任意のフォルダを指定
  * OperatorNameとOperatorLavelにファイル名を入力しAcceptボタンをクリック。Edit Operator Type Propertiesウィンドウが開く
  * Height Field ScatterノードのTotal Point Countをパラメータに追加
  * Total Point CountのNameとLabelを`tree count`に変更
  * tree countのRangeを`0` `30000`に変更
  * Attribute Wrangleノードのthresholdをパラメータに追加
  * thresholdのRangeを`0` `200`に変更
  * Apply、Acceptのボタンをクリックし、ファイルを保存
![パラメーター.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230036/01b7acb3-5f78-f28d-9f14-d65e91c06a32.jpeg)

 ここまででUnityに持ち込むHDAファイルが出来上がりです。

## UnityでHDAを使用
先ほど作成したHDAファイルを以下の方法でUnity内で使用します。

* 保存したHDAファイルをUnityのシーン(Hierarchy)にドラッグ&ドロップ
* 追加されたオブジェクトのインスペクターのINPUT NODES欄 Add Slotをクリック
* 追加されたInput1スロットにHierarchy上のTerrainをドラッグ&ドロップ

以上でシーンの地形上にオブジェクトが配置されます。
オブジェクトのインスペクタ内ASSET PARAMETERS欄のtree countとthresholdの値を変更する事でそれぞれ、樹木の本数、2種類の樹木が切り替わる高さを変える事ができます。またTerrainの形状を変更したり別のTerrainをInput1に入れた際は、インスペクタ内のRecook Assetボタンをクリックする事で配置が更新されます。
![Unity.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230036/692c8d0f-3d88-9423-d2cc-5dd7fd0ac473.jpeg)


以上で完成です！
作成方法は以上ですが、手順のみの説明となっていましたので、最後に２つだけ補足を記載します。
#補足
### Unity TerrainとHoudini HeightField
Houdini Engine for Unityでは、**Unity TerrainとHoudini HeightFieldのラウンドトリップ(相互乗り入れ)**を実現しています。つまり、Unityで作ったTerrainをHDAの入力に使えば、Houdini Engineで処理される際にはHeightFieldに変換されて扱われ、逆にHoudiniで作ったHeightFieldをHDAで出力に設定しておけば、Unity上にはTerrainとして出現します。そのため、今回のインスタンス配置のようにTerrainを入力に使って、出力は別の形(インスタンス配置)であっても、Houdini内部ではTerrainがHeightFieldとして扱われているという事を意識する必要があります。今回のサンプルではHoudini内でインスタンス配置のために大量のポイントを地形に散布しますが、これには通常のScatterではなく、HeightField用のHeightField Scatterというノードを用いています。
###　Houdini Engine for Unity専用のアトリビュート
Houdiniでは各クラス(Point、Primitiveなど)に自由にアトリビュートを付加できますが、Houdini Engine for Unityには独自のアトリビュートが複数種類あります。これらはアトリビュート名によって関連付けされ、Unityに持ち込んだ際に効果を発揮します。今回のサンプルではAttribute Wrangleの中で**”unity_instance”**というアトリビュートを作り使用しました。これはアトリビュートに格納した”Unityアセットのパス”を参照し、そのインスタンスをポイント位置に配置する、という効果があります。その他専用のアトリビュートとその効果についてはHoudini Engineのマニュアルに記載されています。
**https://www.sidefx.com/docs/unity/_attributes.html**
#最後に
講演でも述べたとおり、Houdiniは高機能、高難易度という印象もありますが、実際にはこの程度の手数で出来る事であっても実務には高い効果を発揮すると思います。特に数が膨大なオブジェクトの配置などには必須の技術と言えるかもしれません。
サンプルを動かすのにはHoudiniのライセンスが必要となりますので誰でもというのは難しいかもしれませんが、これからHoudini Engineを使ってみたいという方はぜひお試しください。