Files
Northbound/GRID_BASED_COLLISION.md

284 lines
7.9 KiB
Markdown

# 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
```csharp
[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
```yaml
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
```yaml
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
```yaml
BuildingData:
width: 4
length: 5
height: 4
Grid Footprint:
┌─┬─┬─┬─┬─┐
├─┼─┼─┼─┼─┤
├─┼─┼─┼─┼─┤ Occupies 20 grid cells (4x5)
├─┼─┼─┼─┼─┤
└─┴─┴─┴─┴─┘
```
## Collision Detection Code
### IsValidPlacement (BuildingManager.cs)
```csharp
// 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)
```csharp
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
```csharp
// 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
```csharp
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**