public void LerpMapToGrid(
            IPredictionProjectile predictor, float duration, float resolution,
            float playerBoundingBoxWidth, bool debug)
        {
            var predictionCount = predictor.GetLerpLength(duration, resolution);

            predictionCount = Mathf.Max(
                predictionCount,
                Mathf.CeilToInt(duration / TimeStep / resolution)
                );
            for (var i = 0; i < predictionCount; i++)
            {
                var time = (float)i / predictionCount * duration;
                MapToGrid(predictor, time, playerBoundingBoxWidth, debug);
            }
        }
        public void MapToGrid(IPredictionProjectile projectile, float time,
                              float playerBoundingBoxWidth, bool debug = false)
        {
            var position2d   = projectile.GetPosition(time);
            var position     = new Vector3(position2d.x, time, position2d.y);
            var gridPosition = GlobalCoordsToGrid(position2d, time);

            if (debug)
            {
                _predictions.Add(position);

                if (IsWithinBounds(gridPosition))
                {
                    _gridPredictions.Add(gridPosition);
                }
            }

            if (!IsWithinCheckBounds(position, projectile.BoundingBoxWidth))
            {
                return;
            }

            var projectileCellSize = projectile.BoundingBoxWidth / CellSize;
            var areaCheckPadding   = Mathf.CeilToInt(
                projectileCellSize / 2.0f
                );

            // TODO: Figure out how this time padding stuff should be actually done
            // instead of relying on projectile bounds. Bounds might also technically
            // be a good idea, I really don't know.
            //var projectileTimeSize = projectile.BoundingBoxWidth / TimeStep;
            //var timeCheckPadding = Mathf.CeilToInt(
            //	projectileTimeSize / 2.0f
            //);
            var timeCheckPadding = 0;

            var minX    = gridPosition.X - areaCheckPadding;
            var maxX    = gridPosition.X + areaCheckPadding;
            var minY    = gridPosition.Y - areaCheckPadding;
            var maxY    = gridPosition.Y + areaCheckPadding;
            var minTime = gridPosition.T - timeCheckPadding;
            var maxTime = gridPosition.T + timeCheckPadding;

            for (var x = minX; x <= maxX; x++)
            {
                for (var t = minTime; t <= maxTime; t++)
                {
                    for (var y = minY; y <= maxY; y++)
                    {
                        if (!IsWithinBounds(x, t, y))
                        {
                            continue;
                        }

                        if (_grid[x, t, y])
                        {
                            continue;
                        }

                        var coords = _globalCoords[x, t, y];
                        var result = projectile.DoesOverlapWithCell(
                            position, coords, new Vector3(
                                CellSize3D.x + playerBoundingBoxWidth,
                                CellSize3D.y,
                                CellSize3D.z + playerBoundingBoxWidth
                                ));

                        _grid[x, t, y] = result;
                    }
                }
            }
        }