protected override void OnPostMoveUpdate(float deltaTime)
        {
            // Get screen size at the object depth
            var cameraSize = Utils.GetScreenSizeInWorldCoords(CameraToUse, ProCamera2D.CameraDepthPos - Vector3D(_objStartPosition));

            // Find indices
            var cameraPos = _cameraToUseTransform.position;
            var camBottomLeft = new Vector2(
                                    Vector3H(cameraPos) - cameraSize.x / 2,
                                    Vector3V(cameraPos) - cameraSize.y / 2);

            var camOffset = new Vector2(
                                camBottomLeft.x - _objStartPosition.x - ObjectBottomLeft.x,
                                camBottomLeft.y - _objStartPosition.y - ObjectBottomLeft.y);

            var startIndex = new IntPoint(
                                 Mathf.FloorToInt(camOffset.x / ObjectSize.x),
                                 Mathf.FloorToInt(camOffset.y / ObjectSize.y));

            var copiesNeeded = new IntPoint(
                                   Mathf.CeilToInt(cameraSize.x / ObjectSize.x),
                                   Mathf.CeilToInt(cameraSize.y / ObjectSize.y));

            var endIndex = new IntPoint(
                               startIndex.X + copiesNeeded.X,
                               startIndex.Y + copiesNeeded.Y);

            // If the indices change
            if (!startIndex.IsEqual(_prevStartIndex) || !endIndex.IsEqual(_prevEndIndex))
            {
                // Free out of range objects
                FreeOutOfRangeObjects(startIndex, endIndex);

                // Fill the grid
                FillGrid(startIndex, endIndex);
            }

            _prevStartIndex = startIndex;
            _prevEndIndex = endIndex;
        }
 public bool IsEqual(IntPoint other)
 {
     return other.X == X && other.Y == Y;
 }
        void FillGrid(IntPoint startIndex, IntPoint endIndex)
        {
            if (!_repeatHorizontal)
            {
                startIndex.X = 0;
                endIndex.X = 0;
            }

            if (!_repeatVertical)
            {
                startIndex.Y = 0;
                endIndex.Y = 0;
            }

            // Cycle horizontally
            for (int i = startIndex.X; i <= endIndex.X; i++)
            {
                // Cycle vertically
                for (int j = startIndex.Y; j <= endIndex.Y; j++)
                {
                    // Place the copies on the provided range
                    var gridPos = new IntPoint(i, j); 
                    var isIndexOccupied = false;
                    if (!_occupiedIndices.TryGetValue(gridPos, out isIndexOccupied))
                    {
                        // Create object copy if needed
                        if (_inactiveRepeatedObjects.Count == 0)
                            InitCopy(Instantiate(ObjectToRepeat) as Transform, false);

                        // Set index as occupied
                        _occupiedIndices[gridPos] = true;
                    
                        // Retrieve item from inactive list
                        var repeatedObject = _inactiveRepeatedObjects.Dequeue();
                    
                        // Position it on-screen
                        PositionObject(repeatedObject, gridPos);
                    }
                }
            }
        }
 void PositionObject(RepeatedObject obj, IntPoint index)
 {
     obj.GridPos = index;
     obj.Transform.position = VectorHVD(
         _objStartPosition.x + index.X * ObjectSize.x,
         _objStartPosition.y + index.Y * ObjectSize.y,
         _objStartPosition.z);
 }
        void FreeOutOfRangeObjects(IntPoint startIndex, IntPoint endIndex)
        {
            //Go through the objects list and make them inactive if possible
            for (int i = 0; i < _allRepeatedObjects.Count; i++)
            {
                var repeatedObject = _allRepeatedObjects[i];
                if ((repeatedObject.GridPos.X != int.MaxValue && (repeatedObject.GridPos.X < startIndex.X || repeatedObject.GridPos.X > endIndex.X)) ||
                    (repeatedObject.GridPos.Y != int.MaxValue && (repeatedObject.GridPos.Y < startIndex.Y || repeatedObject.GridPos.Y > endIndex.Y)))
                {
                    // Set index as unoccupied
                    _occupiedIndices.Remove(repeatedObject.GridPos);

                    // Add item to inactive list
                    _inactiveRepeatedObjects.Enqueue(repeatedObject);

                    // Position it off-screen (it's faster then disabling it)
                    PositionObject(repeatedObject, IntPoint.MaxValue);
                }
            }
        }