コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】ECS を利用して 10,000 体のスプライトを描画するサンプル「ecs-instanced-sprite-renderer」紹介

はじめに

「ecs-instanced-sprite-renderer」は
ECS を利用して 10,000 体のスプライトを描画するサンプルです

スクリーンショット

f:id:baba_s:20180415101841p:plain

ソースコード

SpriteRendererMovementSystem.cs

using System;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;

[Serializable]
public struct SpriteInstanceRenderer : ISharedComponentData
{
    public Texture2D sprite       ;
    public int       pixelsPerUnit;
    public float2    pivot        ;

    public SpriteInstanceRenderer
    (
        Texture2D sprite       ,
        int       pixelsPerUnit,
        float2    pivot
    )
    {
        this.sprite        = sprite       ;
        this.pixelsPerUnit = pixelsPerUnit;
        this.pivot         = pivot        ;
    }
}

public class SpriteInstanceRendererComponent :
    SharedComponentDataWrapper<SpriteInstanceRenderer> { }

SpriteRendererSceneBootstrap.cs

using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using Unity.Transforms2D;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;

public sealed class SpriteRendererSceneBootstrap
{
    [RuntimeInitializeOnLoadMethod( RuntimeInitializeLoadType.AfterSceneLoad )]
    public static void InitializeAfterScene()
    {
        var scene = SceneManager.GetActiveScene();
        
        if ( scene.name != "SpriteRendererScene" ) return;

        var manager = World.Active.GetOrCreateManager<EntityManager>();

        // 必要なテクスチャを読み込む
        var dir = "Assets/Scenes/Sprite Rendering Example/Sprites/";
        var list = new []
        {
            AssetDatabase.LoadAssetAtPath<Texture2D>( dir + "elephant.png" ),
            AssetDatabase.LoadAssetAtPath<Texture2D>( dir + "giraffe.png"  ),
            AssetDatabase.LoadAssetAtPath<Texture2D>( dir + "zebra.png"    ),
        };
        
        // 読み込んだテクスチャをレンダラーに設定する
        var renderers = new[]
        {
            new SpriteInstanceRenderer( list[ 0 ], list[ 0 ].width, new float2( .5f, .5f ) ),
            new SpriteInstanceRenderer( list[ 1 ], list[ 1 ].width, new float2( .5f, .5f ) ),
            new SpriteInstanceRenderer( list[ 2 ], list[ 2 ].width, new float2( .5f, .5f ) ),
        };
        
        // 10,000 体のエンティティを生成する
        for ( int i = 0; i < 10000; i++ )
        {
            var entity = manager.CreateEntity
            (
                ComponentType.Create<Position2D>(),
                ComponentType.Create<Heading2D>(),
                ComponentType.Create<TransformMatrix>()
            );

            manager.SetComponentData( entity, new Position2D
            {
                Value = new float2( Random.value * 50, Random.value * 25 )
            } );

            manager.SetComponentData( entity, new Heading2D
            {
                Value = new float2( Random.value, Random.value )
            } );

            manager.AddSharedComponentData( entity, renderers[ i % 3 ] );
        }
    }
}