public override void UpdateInstance(BlockInstance instance)
        {
            var data = instance.GetData <MotionData>();

            if (HitForward(instance))
            {
                if (HitBackward(instance))
                {
                    data.velocity = Vector2.zero;
                }
                else if (Mathf.Approximately(data.velocity.magnitude, 0))
                {
                    data.velocity = (Direction == MoveDirection.Horizontal ? Vector2.left : Vector2.down) * Speed;
                }
                else
                {
                    data.velocity = -data.velocity;
                }
            }
            else if (Mathf.Approximately(data.velocity.magnitude, 0))
            {
                data.velocity = (Direction == MoveDirection.Horizontal ? Vector2.left : Vector2.down) * Speed;
            }

            instance.GetComponent <Rigidbody2D>().velocity = data.velocity;

            /*
             * if (MergeMode == BlockMergeMode.Both)
             * {
             *
             * }
             * else
             * {
             *  var pos = instance.transform.position.ToVector2() + instance.BoxCollider.offset;
             *  var dir = instance.BoxCollider.size / 2 * data.velocity.normalized;
             *  var count = Physics2D.RaycastNonAlloc(pos, dir.normalized, hits, dir.magnitude, 1 << 11);
             *  Debug.DrawLine(pos, pos + dir, Color.red);
             *  for (int i = 0; i < count; i++)
             *  {
             *      if (hits[i].collider.isTrigger)
             *          continue;
             *      if (hits[i].rigidbody == instance.GetComponent<Rigidbody2D>())
             *          continue;
             *      var block = hits[i].rigidbody?.GetComponent<IBlockInstance>()?.GetContactedBlock(hits[i].point, hits[i].normal);
             *      if (block)
             *      {
             *          data.velocity = -data.velocity;
             *          break;
             *      }
             *  }
             *
             * }*/
        }
        void GenerateBlockInstance()
        {
            var position = transform.position.ToVector2();

            rotatedBlocks = new Blocks.BlocksCollection(ComponentData.Component.Rotate(rotateStep));
            if (!blockInstance)
            {
                blockInstance = BlockInstance.CreateInstance(new BlockInstanceOptions()
                {
                    BlockType        = rotatedBlocks.First().BlockType,
                    Blocks           = rotatedBlocks,
                    GenerateRenderer = true,
                    GenerateCollider = true,
                    IsTrigger        = true,
                    IsStatic         = true,
                    GameObject       = gameObject
                });
                var rigidbody = blockInstance.GetComponent <Rigidbody2D>();
                rigidbody.bodyType                    = RigidbodyType2D.Kinematic;
                rigidbody.sleepMode                   = RigidbodySleepMode2D.NeverSleep;
                blockInstance.transform.parent        = transform;
                blockInstance.transform.localPosition = Vector3.zero;
                BlockInstance = blockInstance;
            }
            else
            {
                blockInstance.UpdateInstance(new BlockInstanceOptions()
                {
                    BlockType        = rotatedBlocks.First().BlockType,
                    Blocks           = rotatedBlocks,
                    GenerateRenderer = true,
                    GenerateCollider = true,
                    IsTrigger        = true,
                    IsStatic         = true,
                    GameObject       = gameObject
                });
            }
            UI.sizeDelta = rotatedBlocks.Bound.size.ToVector2();
            MoveTo(position);
            renderers = GetComponentsInChildren <SpriteRenderer>();
        }
        bool HitForward(BlockInstance instance)
        {
            var data = instance.GetData <MotionData>();
            var dir  = data.velocity.normalized * .5f;

            if (Mathf.Approximately(data.velocity.magnitude, 0))
            {
                dir = this.Direction == MoveDirection.Horizontal
                    ? Vector2.right
                    : Vector2.up;
            }
            dir += dir.normalized * 0.01f;
            for (var blockIdx = 0; blockIdx < instance.Blocks.BlocksList.Count; blockIdx++)
            {
                var block = instance.Blocks.BlocksList[blockIdx];
                var pos   = block.Position.ToVector3() - instance.Blocks.Bound.center + instance.transform.position + new Vector3(.5f, .5f, 0);
                var count = Physics2D.RaycastNonAlloc(pos, dir.normalized, hits, dir.magnitude, 1 << 11);
                Debug.DrawLine(pos, pos + dir.ToVector3(), Color.red);
                for (int i = 0; i < count; i++)
                {
                    if (hits[i].collider.isTrigger)
                    {
                        continue;
                    }
                    if (hits[i].rigidbody == instance.GetComponent <Rigidbody2D>())
                    {
                        continue;
                    }
                    var hitBlock = hits[i].rigidbody?.GetComponent <IBlockInstance>()?.GetContactedBlock(hits[i].point, hits[i].normal);
                    if (hitBlock)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }