It seems that dynamic batching only works for instantiated entities. Entities with the same material in their RenderMeshes but with different Meshes do not seem to dynamically batch.
Is this expected behavior? Am I missing something?
I am hoping to create block structures using many different shapes but all the same Material.
Here are images from my test rig:
The top image shows the case where each block has a uniquely-generated Mesh. The second shows the same stacking of blocks using instantiation of a source entity.
Basically the only difference is this:
Entity boxEntity = CreateUniqueBoxEntity(blockSize, new float3(-2, 0, 0), blockMass, blockMaterial, blockVelocity);
for (int j=0; j<rows; j++)
{
for (int i = 0; i < columns; i++)
{
float3 blockPosition = new float3(j + 1.5f, i * 1f, 0);
if (uniqueBlockMeshes)
{
// GENERATE A UNIQUE MESH
CreateUniqueBoxEntity(blockSize, blockPosition, 2, blockMaterial, blockVelocity);
}
else
{
// INSTANTIATE
var tmpEntity = entityManager.Instantiate(boxEntity);
entityManager.SetComponentData(tmpEntity, new Translation() { Value = blockPosition });
}
}
}
Here is the full code:
using UnityEngine;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Entities;
using Unity.Transforms;
using Unity.Rendering;
using UnityEngine.Rendering;
using Unity.Mathematics;
using Unity.Physics;
using Collider = Unity.Physics.Collider;
using Unity.Physics.Extensions;
public class TestEntityGenerator : MonoBehaviour
{
public Mesh mesh;
public UnityEngine.Material blockMaterial;
public UnityEngine.Material projectileMaterial;
public float rows = 10;
public float columns = 10;
public float blockMass = 2;
public Vector3 blockSize = Vector3.one;
public float projectileMass = 10;
public Vector3 projectileSize = Vector3.one;
public bool uniqueBlockMeshes = true;
EntityManager entityManager;
EntityArchetype blockArchetypeype;
// Start is called before the first frame update
void Start()
{
// ENTITY MANAGER
entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
// BLOCK_ARCHETYPE
ComponentType[] dynamicComponentTypes = new ComponentType[11];
dynamicComponentTypes[0] = typeof(RenderMesh);
dynamicComponentTypes[1] = typeof(RenderBounds);
dynamicComponentTypes[2] = typeof(Translation);
dynamicComponentTypes[3] = typeof(Rotation);
dynamicComponentTypes[4] = typeof(LocalToWorld);
dynamicComponentTypes[5] = typeof(PhysicsCollider);
dynamicComponentTypes[6] = typeof(PhysicsVelocity);
dynamicComponentTypes[7] = typeof(PhysicsMass);
dynamicComponentTypes[8] = typeof(PhysicsDamping);
dynamicComponentTypes[9] = typeof(Damage);
dynamicComponentTypes[10] = typeof(OriginalTransform);
blockArchetypeype = entityManager.CreateArchetype(dynamicComponentTypes);
// CREATE STACKED BLOCKS
PhysicsVelocity blockVelocity = new PhysicsVelocity();
Entity boxEntity = CreateUniqueBoxEntity(blockSize, new float3(-2, 0, 0), blockMass, blockMaterial, blockVelocity);
for (int j=0; j<rows; j++)
{
for (int i = 0; i < columns; i++)
{
float3 blockPosition = new float3(j + 1.5f, i * 1f, 0);
if (uniqueBlockMeshes)
{
// GENERATE A UNIQUE MESH
CreateUniqueBoxEntity(blockSize, blockPosition, 2, blockMaterial, blockVelocity);
}
else
{
// INSTANTIATE
var tmpEntity = entityManager.Instantiate(boxEntity);
entityManager.SetComponentData(tmpEntity, new Translation() { Value = blockPosition });
}
}
}
// CREATE PROJECTILE
float3 projectileLaunchPoint = new float3(-120, 40, 0);
PhysicsVelocity projectileVelocity = new PhysicsVelocity() { Linear = new float3(80f, 0f, 0f) };
CreateUniqueBoxEntity(projectileSize, projectileLaunchPoint, projectileMass, projectileMaterial, projectileVelocity);
}
/// <summary>
/// Creates a box entity by generating a simple cube Mesh and a RenderMesh .
/// </summary>
/// <returns>The box entity.</returns>
/// <param name="size">Size.</param>
/// <param name="trans">Trans.</param>
/// <param name="mass">Mass.</param>
/// <param name="material">Material.</param>
/// <param name="physicsVelocity">Physics velocity.</param>
private Entity CreateUniqueBoxEntity(Vector3 size, float3 trans, float mass, UnityEngine.Material material, PhysicsVelocity physicsVelocity)
{
// CREATE A UNIQUE MESH
mesh = BoxMesh.CreateBoxMesh(size.x, size.y, size.z);
RenderMesh renderMesh = new RenderMesh()
{
castShadows = ShadowCastingMode.On,
layer = 1,
material = material,
mesh = mesh,
receiveShadows = true,
subMesh = 0
};
BlobAssetReference<Unity.Physics.Collider> boxCollider = Unity.Physics.BoxCollider.Create(new BoxGeometry()
{
BevelRadius = 0f,
Center = new float3(0, size.y/2, 0),
Orientation = quaternion.identity,
Size = new float3(size.x, size.y, size.z)
}, CollisionFilter.Default);
return CreateEntity(renderMesh, boxCollider, mass, trans, physicsVelocity);
}
/// <summary>
/// Creates an entity from scratch.
/// </summary>
/// <returns>The entity.</returns>
/// <param name="renderMesh">Render mesh.</param>
/// <param name="_collider">Collider.</param>
/// <param name="mass">Mass.</param>
/// <param name="trans">Trans.</param>
/// <param name="physicsVelocity">Physics velocity.</param>
unsafe Entity CreateEntity(RenderMesh renderMesh, BlobAssetReference<Collider> _collider, float mass, float3 trans, PhysicsVelocity physicsVelocity)
{
Unity.Entities.Entity entity = entityManager.CreateEntity(blockArchetypeype);
entityManager.AddSharedComponentData (entity, renderMesh);
entityManager.SetComponentData (entity, new RenderBounds { Value = renderMesh.mesh.bounds.ToAABB() });
entityManager.AddComponentData (entity, new Translation { Value = trans });
entityManager.SetComponentData (entity, new Rotation { Value = Quaternion.Euler(0f, 0f, 0f) });
entityManager.SetComponentData (entity, new PhysicsCollider { Value = _collider });
Collider* colliderPtr = (Collider*)_collider.GetUnsafePtr();
entityManager.SetComponentData(entity, PhysicsMass.CreateDynamic(colliderPtr->MassProperties, mass));
entityManager.SetComponentData(entity, physicsVelocity);
entityManager.SetComponentData(entity, new PhysicsDamping()
{
Linear = 0.01f,
Angular = 0.05f
});
return entity;
}
}