Plant Jumper – Creating a breakeble and a moveable Block

At the start i planned to implement two types of blocks.

  • Breaekable: This block once hitted by a collision starts a timer and then fade away
  • Moveable: This block moves in a zigzag around a starting point

Components Modeling

The first part when creating a new behavior in a ECS mindset it is to try to break it in components, wich will store the behavior data.

Breakeable Block

This block has 3 states, not touched, counting and dead. For that i created a component with two informations. The breaking cooldown and if the breaking started;

public struct BreakComponent : IComponentData
{
    public float coolDown;
    public float started;
}

ZigZag Block

This block will move to the right and then to the left along a initial point a until a determined amplitude.

public struct ZigZagMoveable : IComponentData
{
public float Amplitude;
public float CurrentPosition;
public float Speed;
public float Direction;
}

The amplitude determines how far will the block moves from the initial Position
The CurrentPosition stores the relative moviment of the block
The Speed, how fast will the block moves
The Direction, if the block moves right or left.

Entity Modeling

The Entities are pretty much blocks with an additional behavior, so the entity archetype will seams to be the block one

var brackeableArchetype = this._entityManager.CreateArchetype(
            typeof(Position),
            typeof(Block),
            typeof(BreakComponent),
            typeof(AABBComponent),
            typeof(Collider),
            typeof(CollisionComponent),
            typeof(MeshInstanceRenderer)
        );
var zigzagArchetype = this._entityManager.CreateArchetype(
            typeof(Position),
            typeof(Block),
            typeof(ZigZagMoveable),
            typeof(AABBComponent),
            typeof(Collider),
            typeof(CollisionComponent),
            typeof(MeshInstanceRenderer)
        );

Systems Modeling

BreakItemSystem

For the first one, the breakeable i created a simple idea of a state machine, actually just the idea

using UnityEngine;
using Unity.Entities;
using Unity.Transforms;

using Unity.Mathematics;

public class BreakeItemSystem : ComponentSystem
{
    public struct Data
    {
        public readonly int Length;
        public ComponentDataArray<CollisionComponent> Collision;
        public EntityArray Entities;

        public ComponentDataArray<BreakComponent> BreakComponent;

    }

    [Inject] private Data m_Data;

    protected override void OnUpdate()
    {
        float dt = Time.deltaTime;
        for (int index = 0; index < m_Data.Length; ++index)
        {
            BreakComponent breakComponent = m_Data.BreakComponent[index];
            if (breakComponent.started == 0)
            {
                if (m_Data.Collision[index].direction.y > 0)
                {

                    m_Data.BreakComponent[index] = new BreakComponent
                    {
                        started = 1,
                        coolDown = breakComponent.coolDown
                    };
                }
            }
            else
            {
                float coolDown = m_Data.BreakComponent[index].coolDown;
                coolDown -= dt;
                if (coolDown <= 0.0f)
                {
                    PostUpdateCommands.DestroyEntity(m_Data.Entities[index]);
                }
                else
                {
                    m_Data.BreakComponent[index] = new BreakComponent
                    {
                        started = 1,
                        coolDown = coolDown
                    };
                }
            }
        }
    }
}

In the update method i check if there is a valid collision in the object, if it is true i started the break timer and in the next cicle will be started and untill the time it is not equals to zero, we decrease its amount, otherwise kill the block.

ZigZag System

In this system i check if the relative position are bigger or smaller than the Amplitude, if so, the direction is changed 


using UnityEngine;
using Unity.Entities;
using Unity.Transforms;
using Unity.Collections;
using Unity.Jobs;

using Unity.Mathematics;

public class ZigZagSystem : ComponentSystem
{
    public struct Data
    {
        public readonly int Length;
        public ComponentDataArray<ZigZagMoveable> ZigZagMoveable;
        public ComponentDataArray<Position> Position;
    }

    [Inject] private Data m_Data;

    protected override void OnUpdate()
    {
        float dt = Time.deltaTime;

        for (int index = 0; index < m_Data.Length; ++index)
        {
            ZigZagMoveable zigzag = m_Data.ZigZagMoveable[index];

            float speed = 0;

            if (zigzag.CurrentPosition >= zigzag.Amplitude)
            {
                zigzag.Direction = -1;
            }
            else if (zigzag.CurrentPosition <= -zigzag.Amplitude)
            {
                zigzag.Direction = 1;
            }
            speed = zigzag.Direction * zigzag.Speed;

            float3 currentPosition = m_Data.Position[index].Value;
            float deltaPosition = dt * speed;
            float newPosition = currentPosition.x + deltaPosition;

            m_Data.ZigZagMoveable[index] = new ZigZagMoveable
            {
                Amplitude = zigzag.Amplitude,
                CurrentPosition = zigzag.CurrentPosition + deltaPosition,
                Speed = zigzag.Speed,
                Direction = zigzag.Direction
            };

            m_Data.Position[index] = new Position
            {
                Value = new float3(newPosition, currentPosition.y, currentPosition.z)
            };
        }


    }

}

As you can noticed i didn´t need to think about its collision, because it is also a block and contains colliders, so the other systems will treat it well. This is the beauty of ECS, you just need to append behaviors and see the magic happening