건설 시스템 기초 생성 및 Kaykit Medival 애셋 추가
This commit is contained in:
283
GRID_BASED_COLLISION.md
Normal file
283
GRID_BASED_COLLISION.md
Normal file
@@ -0,0 +1,283 @@
|
||||
# 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**
|
||||
Reference in New Issue
Block a user