いんでぃーづ

ゲームメインのブレブレブログ。ゲーム,Unity,デザイン,UI/UX

Unity : PureECSで100体のゾンビをランダムウォークさせるサンプルソース

100体でも1000体でもいいのですが、とりあえず物体を大量に動かしたかった。

f:id:sugar_affordance:20190802110136g:plain

未来の自分のために ソースコード完全コピペで動かせる のを目指しました。

・環境
Unity 2019.1.11f
ECS : preview 0.1.0

※LWRPで検証

PakcageManager

EntitiesHybridRenderer をインストール

f:id:sugar_affordance:20190803062835p:plain

ComponentSystem 用のソースコード

スクリプト1つです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;
using Unity.Rendering;
using Unity.Transforms;

public class ZombieComponentSystem : ComponentSystem
{
    
    static EntityArchetype archetype;

    // Entity用データ構造体
    struct Zombie : IComponentData {
        public Quaternion rotation;
    }

    public static void CreateEntity(Vector3 position, Mesh mesh, Material mat)
    {
        // Entityを作成する
        var e = World.Active.EntityManager.CreateEntity(archetype);

        // Entityの初期値設定
        // ゾンビ
        Zombie z = World.Active.EntityManager.GetComponentData<Zombie>(e);
        z.rotation = Quaternion.Euler(-90, Random.Range(-360, 360), 0);
        World.Active.EntityManager.SetComponentData<Zombie>(e, z);

        // 描画するメッシュ
        RenderMesh r = World.Active.EntityManager.GetSharedComponentData<RenderMesh>(e);
        r.mesh = mesh;
        r.material = mat;
        World.Active.EntityManager.SetSharedComponentData<RenderMesh>(e, r);

        // 位置(MonoBehaviourのTransformとほぼ同じ)
        Translation t = World.Active.EntityManager.GetComponentData<Translation>(e);
        t.Value = position;
        World.Active.EntityManager.SetComponentData<Translation>(e, t);
    }

    protected override void OnCreate() {
        // アーキタイプを作成
        archetype = World.Active.EntityManager.CreateArchetype(
            typeof(Zombie),
            typeof(Translation),
            typeof(Rotation),
            typeof(LocalToWorld),
            typeof(RenderMesh));

    }

    protected override void OnUpdate()
    {
        // !!! Rotationもクエリに入れるとエラーが出る(バグ?)
        Entities.WithAll<Zombie>().ForEach((Entity e, ref Zombie zombie, ref Translation translation) => {

            // 回転の設定
            zombie.rotation = Quaternion.Euler(0, Random.Range(-10, 10) + zombie.rotation.eulerAngles.y, 0);

            Rotation rotation = World.Active.EntityManager.GetComponentData<Rotation>(e);
            rotation.Value = zombie.rotation;
            World.Active.EntityManager.SetComponentData<Rotation>(e, rotation);

            // 向いている方向に移動
            Vector3 move = (zombie.rotation * Vector3.forward) * 0.1f;
            translation.Value = translation.Value + new Unity.Mathematics.float3(move);
        });
    }
}

シーンに置いてEntityを生成するコード

スクリプト1ツです。
描画したいメッシュとマテリアルを設定しておきます。

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

public class ZombieSpawner : MonoBehaviour
{
    [SerializeField]
    Mesh mesh;
    [SerializeField]
    Material mat;

    void Start()
    {
        for (int i = 0; i < 1000; i++)
            ZombieComponentSystem.CreateEntity(new Vector3(Random.Range(-20, 20), 0, Random.Range(-20, 20)), mesh, mat);   
    }

}

f:id:sugar_affordance:20190802110451p:plain:w400

Entity Component System | Package Manager UI website
Struct RenderMesh | Package Manager UI website


あとアニメーションもさせたいので下記記事を参考に実装中。

【Unity】ECS向けのアニメーションシステムを実装してみた - Qiita


“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.


免責事項

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

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

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