xNodeでノードベースエディターを作る(導入編)

# はじめに

UnityEditorでノードベースエディターを作るとなると、わりと面倒です。

というのも、ShaderGraphでも使われているGraphViewという標準のパッケージがあるんですが、なぜかいまだにExperimental(実験的)で、でもすでにメンテナンスモード入りしています(＝使っていいけど新機能は開発されない)。その後継とされるGraphTools Foundation(GTF)はまだまだ未完成で、完成するまではGraphViewを使ってください、と公式フォーラムで中の人が言っています。その上、どちらもドキュメントもサンプルも少なく、ちょっと試してみましたが、正直お手上げです。

↓ Unityの中の人のお言葉

https://forum.unity.com/threads/graphview-graphtools-foundation-what-can-we-expect-in-the-near-future.1327434/#post-8542202

それで調べたところ、GraphViewを楽に使うためのパッケージとしてxNodeとNodeGraphProcessorというものが公開されていました。ここではMITライセンスでカスタマイズしやすそうという理由で、xNodeを使ってノードベースエディターを作ってみようと思います。(とはいえ、xNodeもすでに開発は止まっていますが…)

# xNodeのインストール

アセットストアからだと11ドルですが、

https://assetstore.unity.com/packages/tools/visual-scripting/xnode-104276

ここに "xNode is free! Get it from GitHub!" (xNodeは無料だよ！ GitHubから取ってきてね！) と書いてあるので、GitHubから持ってきます。

https://github.com/Siccity/xNode

Zipでダウンロードして展開するのも面倒なので、OpenUPMを使って導入するのが楽です。

https://openupm.com/packages/com.github.siccity.xnode/

UnityEditorのProject SettingsのPackage ManagerのScoped RegistriesのURLに "http://package.openupm.com" とScopeに "com.github.siccity.xnode" を設定。Nameは表示用なので "OpenUPM" でもなんでもOKです。

![PackageManager_OpenUPM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141731/2f096be3-14f1-f8bc-4b54-141b0304aecc.png)

すると、Package Managerで"My Registries"を選択すると"xNode"が表示されるようになるので"Install"します。(ここらへんはアセットストアのパッケージと同じ)

xNodeに限らず、他のGitHubで配布されているパッケージもこれで取り込めるので、おすすめです。

# ドキュメントとサンプル

xNodeもドキュメントとサンプルが充実しているとまでは言えないんですが、使い方がシンプルなので、Getting Startedである程度分かります。

https://github.com/Siccity/xNode/wiki/Getting%20Started

日本語版がないのは諦めるしかないですね…。最近は有償の有名なツールであっても日本語ドキュメントがなくなりつつあり(メジャーバージョンアップを機に廃止、とかよくある)、日本のプレゼンスの低下をひしひしと感じます。とはいえ、AI翻訳が技術文書でもかなり使えるようになってきたので、なんとか読んでみてください。

サンプルも公式のものがあって、Exampleフォルダ内のものが一番簡単で読みやすいです。

https://github.com/Siccity/xNode/tree/examples

とはいえ、すべての機能を網羅できているわけではないので、足りない部分はxNode自体のコードを読む必要があります。VisualStudioを駆使して読んでいきましょう。

なお、OpenUPM経由で取り込んだ場合はそのままではコードジャンプできないので(宣言しか見えない)、Preferencesの"External Tools"で"Registry packages"にチェックを入れて"Regenerate project files"しておきましょう。(他のも見えちゃうけど)

![Preferences_ExternalTools.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141731/0c0512da-264b-3d79-9805-520845260103.png)

# xNodeの構造

まずxNodeの構造を理解しておく必要があります。

xNodeはグラフ全体を表す **NodeGraph** と、ノードを表す **Node** で構成されています。NodeGraphはすべてのNodeを保持していて、Nodeは必要なパラメーターと **NodePort** でノード間の接続情報を保持しています。これらを用途に合わせて実装することになります。

データは専用のEditorWindowで編集し、ScriptableObjectとしてシリアライズされます。ノードの配置や移動や接続は実装済みなので、ノードの中身の実装さえしてしまえば、ささっと試すことが出来ます。

まず、何も考えずに手を動かしてみましょう。

# 作り方

試しにfloatの値を2つ入力して加算した結果を出力する超高機能なノードを作ります。

AssetsメニューのCreate→xNodeに"Node C# Script"と"NodeGraph C# Script"という、実装に必要なスクリプトを作る項目が追加されているので、Projectウィンドウで適当なフォルダ(Editorフォルダ以外)に移動した上で、選択します。

![xNode_Menu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141731/1de51a9f-a9d2-3934-e064-c7aeb46ed02e.png)

"NewNode"と"NewNodeGraph"というC#スクリプトが作成されたと思います(もちろんファイル名とクラス名は好きに変えて良い)。すると、同じくAssets→Createに"New Node Graph"というメニューが追加されていて、ノードグラフのアセットを作れるようになります。

![xNode_Menu_NewNodeGraph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141731/1809fae4-f01f-a48f-6a2a-ae8c59b25f3a.png)

アセットを作るとxNodeという名前のEditorWindowが出てきて(出てこない場合はアセットをダブルクリック)、ウィンドウ内で右クリックメニューからノード名(デフォルトでは"New")を選択すると、ノードが置けるようになります。あとは直感的に操作できると思います。

![xNode_Menu_NewNodeGraphAsset.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141731/0898ef29-1f7f-79de-db07-b8580a88165d.png)

このままだとノードが置けるだけで何も出来ないので、Nodeを実装していきます。ノードのスクリプトを編集して、Input, Outputというアトリビュートを付けて入出力値のフィールドを宣言、GetValueに足し算を実装します(解説はあとでするのでひとまずコピペで)。

```C#:NewNode.cs
public class NewNode : Node {
	[Input] public float a;
	[Input] public float b;
	[Output] public float c;

    public override object GetValue(NodePort port) {
        if (port.fieldName == "c")
            return GetInputValue<float>("a", a) + GetInputValue<float>("b", b);
        else
            return null;
    }
}
```

これでノードに数値の入力欄と入出力ポートが出来て、マウスの左ボタンドラッグでポートから線を伸ばして接続できるようになりました。ポートを右クリックして"Clear Connections"を選択すれば接続を解除できます。

試しにaとbに数値を入れて試してみてください。出力ポートをマウスオーバーすると足し算した結果が表示されるはずです。そして、他のノードを入力ポートに接続すると入力欄が消えて、接続したノードの出力値が入力されて結果が変わります。

# おわりに

足し算をノードベースエディターでやりたい人はいないと思いますが、基本的なものはできました。ここからいろいろ実装していきます。

記事が長くなりそうなので、一旦ここまで。次は実装編です。