いんでぃーづ

ゲームいろいろ、いろいろ自由

Unity ECS : preview版 (0.8.0) Hybrid Renderer V2 を使う

基本的に私は何も考えずにUnityをメジャーアップデートして使うしパッケージもどんどんpreview状態で使っていくタイプなのですが、そのたびに何かしら問題が発生し、開発期間中にハマるときは大体Unityアップデートした直後だったりして「ちょっとお前落ち着け」と自分に言い聞かせたくもなりますが、楽しいからしょうがないね。

ということで、今作っているローグライクゲームで、生成した3Dダンジョンをどうやってシーンに構築するかと考えたときに、自然とDOTSでやろうという流れになりました(脳内で)。

今回はDOTSの Hybrid Renderer を導入する手順です。

言わずもがなECS関連は2020年現在バリバリのpreviewで、破壊的変更も、超巨大巨人が壁を蹴り壊すごとく、いとも簡単にえげつなく行われていきます。
つまり、この記事が来月でも使えるという保証はありません(泣)。

Hybrid Renderer とは

Unity の ECS3Dオブジェクトを描画する 仕組みです。
ECSて何? て方は読んでもしょうがないので、一旦ブラウザを閉じてコーヒーでも飲みましょう。

導入の第一歩

Hybrid Renderer のバージョンについて

Hybrid Renderer は 二つバージョンがあります(V1とV2)。
そしてV1はすでに 開発が終了している旨 がアナウンスされています。

DOTS Hybrid Renderer | Hybrid Renderer | 0.8.0-preview.19

It is no longer in active development.

まだpreview状態のパッケージで同機能のバージョンが二つってどういうこっちゃ、しかも一つ目はすでにオワコンて。
とか言いたいことはたくさんありますが、previewだから全て許されるのです。私は元気です。

さて、V1とV2の違いも公式サイトでまとめられています。

DOTS Hybrid Renderer | Hybrid Renderer | 0.8.0-preview.19

主に URP, HDRP でのシェーダまわりの基本機能が整備されているようです。

いずれにしろV1を使う理由は特にないのでV2を導入していきます。

V2の導入環境について

ここで 第一の関門 です。

URP (Universal Rendering Pipeline) でV2を導入する場合、

URP version 9.0.0 and above, with Unity 2020.1 and above

と指定されているとおり、URP v9を使うために Unity 2020.1 が必要なのですが、実はこのバージョンのUnityは 一部の preview パッケージを Package Manager からインストールできません

Package Manager updates in Unity 2020.1Unity 2020.1 - 패키지 관리자 업데이트Unity 2020.1 でのパッケージマネージャーのアップデート - Unity Technologies Blog

全社的な取り組みとして、パッケージリストを再検討し、まだ正式版よりは実験的なパッケージに近いプレビュー版パッケージ、またはアクティブに開発が進んでいないプレビュー版パッケージを特定しました。Unity 2020.1 以降のバージョンでは、これらのカテゴリのプレビュー版パッケージはパッケージマネージャーに表示されません。

そして私が試した時点では ECS関連のパッケージはリストアップされませんでした

例えば、Unity 2020.1 でプレビュー版パッケージがパッケージマネージャーに表示されている場合、そのパッケージは Unity 2020 LTS のリリースまでに検証済みに移行させることを計画しているということです。

ともされているので、つまり ECSのプレビューが外れるのは Unity2021 以降 ってことなんですかね。ふーん、えっ、ちえんじゃん?

ということで今回は Unity2020.1 を使いつつ、手作業で各種パッケージをインポートします。

必要なパッケージのインポート

前述のとおり Package Manager が使えないので、プロジェクトルートディレクトリ の Packages/manifest.json ファイルを直接編集する という方法をとります。

ファイルをエディタで開き、dependencies のなかに各種パッケージを記述、保存してUnityに戻るとインポートがはじまります。

{
  "dependencies": {

    ...

    "com.unity.entities": "0.14.0-preview.19",
    "com.unity.jobs": "0.2.10-preview.12",
    "com.unity.render-pipelines.universal": "9.0.0-preview.55",
    "com.unity.rendering.hybrid": "0.8.0-preview.19",

    ...
  }
}

今回使用したパッケージと各バージョンは、上のpackage.jsonに書いてあるものです。

もしくは Unity2019 でPackageManagerからインストールした後にUnity2020にアップデート、手作業で各パッケージのバージョンだけ書き換える、という方法もあります。手作業でやると関連パッケージが足りないかもしれないので、うまくいかない場合はこっちの方法で。

V2を使うためプロジェクトの設定を変更

メニューの Edit > Project Settings ... を開き、Playerの項目の Scripting Define SymbolsENABLE_HYBRID_RENDERER_V2 を追加します。

f:id:sugar_affordance:20200923090414p:plain

Hybrid Renderer V2を使う準備としては以上です。

描画するEntityをシーンに配置する

ECSでEntityを配置する方法は結構いろいろありますが、今回はローグライクダンジョンというテーマなので、
動的に生成したタイルのEntityをその都度生成していくことになります。

この場合

  • Archetypeを決めてCreateEntityする
  • 普通のGameObjectで用意したプレハブをEntity に変換する

という方法がありますが、おすすめは後者です。
というのも Archetype から生成する場合、関連するコンポーネントを完璧にAddしないと、ライトが当たらなかったり無駄にカリングされ て不自然なダンジョンになったりと、いいことがありません。

GameObjectから変換したEntityをデバッガで見てみると、名前からは何してるかわからないコンポーネントがいろいろ追加されているのがわかります。

f:id:sugar_affordance:20200923093050p:plain
お、おう

もし正確にArchetypeから生成するコードを書けたとしても、今後のアップデートの都度ソースを調整するのも気が重い話です。

ということで、GameObjectから変換するためのメソッドが用意されているので、それを使います。

Class GameObjectConversionUtility | Entities | 0.8.0-preview.8

GameObjectから変換したEntityはPrefabコンポーネントをつけてプレハブEntityにしておき、次回からはそこから生成します。

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;
using Unity.Rendering;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

public class CreateEntitySystem : SystemBase
{

    // Prefab化してキャッシュしておくEntity
    Entity prefabEntity;

    public void CreateTileEntity(GameObject prefab, Vector3 position) {

        if (prefabEntity == null) {
            // プレハブをシーンにInstantiate
            var objecInScene = GameObject.Instantiate(prefab) as GameObject;

            // Entityに変換
            var entity = GameObjectConversionUtility.ConvertGameObjectHierarchy(
                objecInScene,
                GameObjectConversionSettings.FromWorld(World, new BlobAssetStore())
            );

            // 他に必要なコンポーネントは AddComponentData する
            EntityManager.AddComponentData(
                entity,
                new Scale() {
                    Value = 1
                }
            );

            // 次回生成のためにPrefab化しておき
            EntityManager.AddComponentData(entity, new Prefab());
        }

        // タイルの生成
        Entity newEntity = EntityManager.Instantiate(prefabEntity);

        // 配置
        EntityManager.SetComponentData(
            newEntity,
            new Translation() {
                Value = position
            }
        );
    }

}

結果

ここまでで、とりあえず表示はできていると思います。
ほんとは載せたい動画があったのですが、UnityのRecorderでキャプチャしたGifがはてなにアップロードできなかったので断念。

・参考

DOTS Hybrid Renderer | Hybrid Renderer | 0.8.0-preview.19


“Unity” and Unity logos are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere, and are used under license.


免責事項

当サイトの広告バナー、リンクによって提供される情報、サービス内容について、当サイトは一切の責任を負いません。

また、当サイトの情報を元にユーザ様が不利益を被った場合にも、当サイトは一切の責任を負いません。

すべて自己責任でお願いします。