Files
Northbound/GRID_BASED_COLLISION.md

7.9 KiB

Grid-Based Collision System

How It Works

The building system uses grid-based collision detection, NOT the actual colliders on building prefabs.

Grid Bounds vs Collider Bounds

❌ OLD WAY (Collider-based):
Building A has BoxCollider (2.5 x 3.7 x 4.2)
Building B has MeshCollider (complex shape)
→ Hard to predict, inconsistent placement

✅ NEW WAY (Grid-based):
Building A has width=2, length=3, height=2 in BuildingData
Building B has width=1, length=4, height=3 in BuildingData
→ Predictable, consistent grid placement

Why Grid-Based?

Advantages

  1. Predictable: Buildings snap to grid, easy to understand
  2. Consistent: Same rules for all buildings, regardless of visual model
  3. Flexible: Visual model can be any size/shape
  4. Network-Friendly: Simple data to sync (just grid position + rotation)
  5. Performance: Fast AABB (Axis-Aligned Bounding Box) checks

Comparison

Aspect Collider-Based Grid-Based
Placement Visual, complex shapes Predictable grid cells
Performance Slower (physics queries) Faster (simple bounds check)
Network Sync Complex mesh data Simple int coordinates
Rotation Complex recalculation Swap width/length
Debugging Hard to visualize Easy (grid gizmos)

How Grid Size Works

BuildingData Settings

[Header("Grid Size")]
public int width = 2;   // X-axis grid cells
public int length = 3;  // Z-axis grid cells
public float height = 2f; // Y-axis size (can be float)

Rotation Effect

Building: width=2, length=3

Rotation 0° (0):     Rotation 90° (1):
┌─────┐              ┌───────┐
│  2  │              │   3   │
│  x  │              │   x   │
│  3  │              └───────┘
└─────┘                  2

Rotation 180° (2):   Rotation 270° (3):
┌─────┐              ┌───────┐
│  3  │              │   2   │
│  x  │              │   x   │
│  2  │              └───────┘
└─────┘                  3

The GetSize(rotation) method automatically swaps width/length for 90° and 270° rotations.

Visual Examples

Example 1: Small House

BuildingData:
  width: 2
  length: 2
  height: 3

Grid Footprint (top view):
┌─┬─┐
├─┼─┤  Occupies 4 grid cells (2x2)
└─┴─┘

Visual Model: Can be any size!
- Model might be 1.8 x 1.8 (smaller than grid)
- Model might be 2.3 x 2.3 (larger than grid)
- Collision still uses 2x2 grid

Example 2: Wall Segment

BuildingData:
  width: 1
  length: 4
  height: 2

Grid Footprint:
┌───────────┐
│ 1 x 4     │  Occupies 4 grid cells (1x4)
└───────────┘

When rotated 90°:
┌─┐
├─┤
├─┤  Becomes 4x1
├─┤
└─┘

Example 3: Large Building

BuildingData:
  width: 4
  length: 5
  height: 4

Grid Footprint:
┌─┬─┬─┬─┬─┐
├─┼─┼─┼─┼─┤
├─┼─┼─┼─┼─┤  Occupies 20 grid cells (4x5)
├─┼─┼─┼─┼─┤
└─┴─┴─┴─┴─┘

Collision Detection Code

IsValidPlacement (BuildingManager.cs)

// Get grid size from BuildingData (NOT collider)
Vector3 gridSize = data.GetSize(rotation);

// Shrink bounds slightly to allow adjacent placement
// Without this, Bounds.Intersects() returns true for touching bounds
Vector3 shrunkSize = gridSize - Vector3.one * 0.01f;
Bounds checkBounds = new Bounds(
    groundPosition + Vector3.up * gridSize.y * 0.5f,
    shrunkSize
);

// Check against all placed buildings' GRID bounds
foreach (var building in placedBuildings)
{
    Bounds buildingGridBounds = building.GetGridBounds();
    if (checkBounds.Intersects(buildingGridBounds))
        return false; // Overlap detected
}

Why shrink by 0.01f? Unity's Bounds.Intersects() returns true when bounds are touching (edge-to-edge), not just overlapping. By shrinking the bounds by a tiny amount (0.01 units), we allow buildings to be placed directly adjacent without triggering a false overlap detection.

GetGridBounds (Building.cs)

public Bounds GetGridBounds()
{
    // Uses BuildingData size, not collider
    Vector3 gridSize = buildingData.GetSize(rotation);

    // Shrink slightly to allow adjacent buildings
    Vector3 shrunkSize = gridSize - Vector3.one * 0.01f;
    return new Bounds(
        transform.position + Vector3.up * gridSize.y * 0.5f,
        shrunkSize
    );
}

Note: The 0.01f shrink is tiny and not visible, but prevents false overlap detection for adjacent buildings.

Visualizing Grid Bounds

In Scene View

  1. Enter Build Mode (Press B)
  2. Look at Scene View (not Game view)
  3. You'll see:
    • Green/Red Wire Cube: Preview's grid bounds
    • Yellow Grid Cells: Individual cells
    • Cyan Wire Cubes: Placed buildings' grid bounds

Debug Settings

BuildingPlacement:

  • Show Grid Bounds - Shows preview grid visualization

Building:

  • Show Grid Bounds - Shows cyan wire cube for this building
  • Grid Bounds Color - Customize visualization color

Example Scene

Scene View:
        Preview (Green)
        ┌─────┐
        │ 2x3 │
        └─────┘
                    Placed Building (Cyan)
                    ┌───┐
                    │1x2│
                    └───┘

Grid Cells (Yellow):
┌─┬─┬─┬─┬─┬─┐
├─┼─┼─┼─┼─┼─┤
└─┴─┴─┴─┴─┴─┘

Best Practices

1. Match Grid Size to Gameplay

// Small decorations
width: 1, length: 1, height: 1

// Medium buildings
width: 2-3, length: 2-3, height: 2-3

// Large buildings
width: 4-6, length: 4-6, height: 3-5

2. Visual Model Can Differ

The visual model doesn't need to match grid size exactly:

  • Overhang/decorations can extend beyond grid
  • Model can be smaller, leaving empty grid space
  • Use placementOffset to adjust visual alignment

3. Height Consideration

height: 2f  // Building is 2 units tall
  • Used for vertical bounds checking
  • Prevents buildings on top of each other
  • Can be float (e.g., 2.5f for tall buildings)

4. Colliders Still Needed

Building prefabs should still have colliders for:

  • Player/entity collision during gameplay
  • Physics interactions
  • Raycast detection

But these are NOT used for placement validation!

Common Questions

Q: Why is my small model blocking a large area? A: Check the width and length in BuildingData. The grid size determines collision, not the visual model.

Q: Buildings overlap visually but can't place? A: Grid bounds are overlapping. Check Scene view with "Show Grid Bounds" enabled.

Q: How do I make a building take less space? A: Reduce width and length in BuildingData. The visual model size doesn't matter.

Q: Can I use fractional grid sizes? A: width and length are integers (whole grid cells). Only height can be a float.

Q: What if my model is rotated strangely? A: Grid rotation is separate from model rotation. Grid always aligns to world axes. Adjust model's prefab rotation or use placementOffset.

Q: Can buildings be placed directly next to each other with no gap? A: Yes! The system shrinks bounds by 0.01f to allow adjacent placement. Buildings can touch edge-to-edge.

Q: I want a gap between buildings. How? A: Increase the width and length values in BuildingData by 1. For example, change a 2x2 building to 3x3 to add a 1-cell buffer zone.

Summary

Use BuildingData grid size for collision Visual model can be any size Predictable, grid-aligned placement Easy debugging with gizmos Fast performance

Don't rely on collider size Don't expect pixel-perfect visual collision Don't use colliders for placement validation