---
title: "내적: 적이 앞에 있나 뒤에 있나"
description: "백어택 판정과 시야각 판정은 Vector3.Dot 한 줄입니다. 내적은 같은 자리끼리 곱해서 더한 숫자이고, 부호는 앞과 뒤를, 값은 사이각의 cos 를 알려 줍니다."
author: "유니얼"
pubDate: 2026-11-05
category: "game-dev/math"
tags: ["Unity", "기초"]
canonical: https://blog.unialgames.com/posts/math-dot/
---
뒤에서 때리면 두 배 피해를 주는 백어택을 만들려면 "적이 공격자를 등지고 있나" 를 알아야 합니다.
적 AI 에 시야를 주려면 "플레이어가 내 앞 120도 안에 있나" 를 알아야 합니다. 둘 다 각도를 구하지 않고 풉니다.

두 방향 벡터의 **내적**, 곧 같은 자리끼리 곱해서 더한 숫자 하나면 됩니다. 길이가 1 이면 이 숫자가 사이각의 **cos** 입니다.
cos 는 길이 1 인 막대를 θ 만큼 기울였을 때 **바닥에 누운 가로 길이**입니다. 0° 면 1, 90° 면 0(똑바로 섬), 180° 면 −1(반대로 누움)이라, 부호가 앞과 뒤를 가릅니다.

> **`Vector3.Dot(a, b)` 는 `a.x × b.x + a.y × b.y + a.z × b.z` 입니다.
> a 와 b 가 길이 1 이면 결과는 1(같은 방향)에서 −1(정반대) 사이이고, 사이각이 클수록 작아집니다.
> 앞뒤 판정은 부호만, 시야각 판정은 `cos(시야각의 절반)` 과 비교합니다.**

## 내적은 같은 자리끼리 곱해서 더한 숫자다

**벡터**는 방향과 길이를 가진 화살표이고, 유니티에서는 `Vector3` 의 x, y, z 세 숫자로 씁니다.
두 벡터의 내적은 x 끼리, y 끼리, z 끼리 곱한 다음 전부 더한 값입니다.
결과는 벡터가 아니라 **숫자 하나**입니다.

위에서 내려다본 바닥이라 y 를 빼고 (x, z) 두 개만 씁니다. 나는 앞 (0, 1) 을 보고 있습니다.

| 적이 있는 방향 | 계산 | 내적 | 뜻 |
| --- | --- | --- | --- |
| 바로 앞 (0, 1) | 0 × 0 + 1 × 1 | **1** | 같은 방향 |
| 오른쪽 앞 (0.71, 0.71) | 0 × 0.71 + 1 × 0.71 | **0.71** | 앞쪽 |
| 바로 오른쪽 (1, 0) | 0 × 1 + 1 × 0 | **0** | 옆 |
| 오른쪽 뒤 (0.71, −0.71) | 0 × 0.71 + 1 × (−0.71) | **−0.71** | 뒤쪽 |
| 바로 뒤 (0, −1) | 0 × 0 + 1 × (−1) | **−1** | 정반대 |

적의 방향은 모두 길이 1 로 맞췄습니다. (0.71, 0.71) 은 대각선 (1, 1) 을 길이 1 로 줄인 값입니다.

<x-vec>
<script type="application/json">
{
  "label": "적이 내 주위를 돌 때 Dot(앞, 적 방향)",
  "view": [-2, -2, 2, 2],
  "dwell": 2.2,
  "steps": [
    {
      "caption": "적이 바로 앞. 두 화살표가 같은 방향이라 내적이 가장 큰 1 입니다.",
      "items": [
        { "id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted" },
        { "id": "f", "from": [0, 0], "to": [0, 1], "label": "앞", "labelAt": [-0.35, 1.3] },
        { "id": "e", "from": [0, 0], "to": [0, 1], "color": "accent2" },
        { "id": "t", "type": "text", "at": [0, -1.6], "color": "accent2", "label": "Dot = 1" }
      ]
    },
    {
      "caption": "오른쪽 앞 45도. 아직 앞쪽이라 0 보다 큽니다. 0.71.",
      "items": [
        { "id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted" },
        { "id": "f", "from": [0, 0], "to": [0, 1], "label": "앞", "labelAt": [-0.35, 1.3] },
        { "id": "e", "from": [0, 0], "to": [0.71, 0.71], "color": "accent2" },
        { "id": "t", "type": "text", "at": [0, -1.6], "color": "accent2", "label": "Dot = 0.71" }
      ]
    },
    {
      "caption": "바로 오른쪽 90도. 앞도 뒤도 아니라서 정확히 0 입니다. 두 화살표가 수직이면 내적은 0 입니다.",
      "items": [
        { "id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted" },
        { "id": "f", "from": [0, 0], "to": [0, 1], "label": "앞", "labelAt": [-0.35, 1.3] },
        { "id": "e", "from": [0, 0], "to": [1, 0], "color": "muted" },
        { "id": "t", "type": "text", "at": [0, -1.6], "color": "muted", "label": "Dot = 0" }
      ]
    },
    {
      "caption": "오른쪽 뒤 135도. 뒤쪽으로 넘어가자 음수가 됩니다. −0.71.",
      "items": [
        { "id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted" },
        { "id": "f", "from": [0, 0], "to": [0, 1], "label": "앞", "labelAt": [-0.35, 1.3] },
        { "id": "e", "from": [0, 0], "to": [0.71, -0.71], "color": "warn" },
        { "id": "t", "type": "text", "at": [0, -1.6], "color": "warn", "label": "Dot = −0.71" }
      ]
    },
    {
      "caption": "바로 뒤 180도. 정반대라서 가장 작은 −1 입니다. 백어택은 이쪽입니다.",
      "items": [
        { "id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted" },
        { "id": "f", "from": [0, 0], "to": [0, 1], "label": "앞", "labelAt": [-0.35, 1.3] },
        { "id": "e", "from": [0, 0], "to": [0, -1], "color": "warn" },
        { "id": "t", "type": "text", "at": [0, -1.6], "color": "warn", "label": "Dot = −1" }
      ]
    },
    {
      "caption": "왼쪽 앞 45도. 오른쪽 앞과 똑같이 0.71 입니다. 내적은 사이각만 보고, 왼쪽인지 오른쪽인지는 가리지 않습니다.",
      "items": [
        { "id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted" },
        { "id": "f", "from": [0, 0], "to": [0, 1], "label": "앞", "labelAt": [-0.35, 1.3] },
        { "id": "e", "from": [0, 0], "to": [-0.71, 0.71], "color": "accent2" },
        { "id": "t", "type": "text", "at": [0, -1.6], "color": "accent2", "label": "Dot = 0.71" }
      ]
    }
  ]
}
</script>
</x-vec>

**부호가 앞뒤를 가릅니다.** 0 보다 크면 앞쪽 반, 작으면 뒤쪽 반입니다.
백어택은 "적의 앞 방향" 과 "적에서 공격자로 가는 방향" 의 내적이 0 보다 작은지로 판정합니다.

```csharp
// 적에서 공격자로 가는 방향 (도착 − 출발)
Vector3 toAttacker = attacker.position - enemy.position;

// 0 보다 작으면 공격자가 적의 뒤쪽 반에 있다
bool isBackAttack = Vector3.Dot(enemy.forward, toAttacker) < 0f;
```

## 왜 부호가 그렇게 나오나: 그림자 길이

내적에는 계산하는 법이 두 가지 있습니다. 하나는 위에서 한 **같은 자리끼리 곱해서 더하기**이고, 다른 하나는 **길이 × 길이 × cos(사이각)** 입니다.
둘은 늘 같은 값이 나옵니다. 열쇠는 **그림자**입니다. 한 화살표의 끝에서 다른 화살표가 놓인 직선으로 수직선을 내리면, 그 직선 위에 그림자가 생깁니다.

먼저 쉬운 경우입니다. a = (4, 0) 은 바닥(오른쪽)에 누워 있고, b = (3, 4) 는 비스듬히 서 있습니다.

| 단계 | 계산 | 결과 |
| --- | --- | --- |
| 같은 자리끼리 곱해 더하기 | 4 × 3 + 0 × 4 | **12** |
| a 의 길이 | 오른쪽으로 4 | 4 |
| b 의 길이 (빗변) | √(3² + 4²) = √25 | 5 |
| b 가 바닥에 드리운 그림자 (가로) | b 의 끝 (3, 4) 에서 수직선을 내리면 | 3 |
| 사이각의 cos | 가로 ÷ 빗변 = 3 ÷ 5 | 0.6 |
| 길이 × 길이 × cos | 4 × 5 × 0.6 | **12** |

두 길로 같은 12 가 나왔습니다. 이유도 보입니다. a 의 y 가 0 이라 곱해서 더하기가 `4 × 3` 하나만 남는데, 4 는 a 의 길이이고 3 은 b 의 그림자입니다.
그리고 그림자(가로)는 cos 의 뜻 그대로 **빗변 × cos** 입니다. 그래서 `a 의 길이 × 그림자 = a 의 길이 × b 의 길이 × cos` 가 됩니다.

a 가 비스듬해도 같습니다. 두 화살표를 **함께** 돌리면 길이와 사이각은 그대로이고, 곱해서 더한 값도 그대로입니다.
위의 둘을 함께 90° 돌리면 a = (0, 4), b = (−4, 3) 이 되는데, 0 × (−4) + 4 × 3 = 12 로 같습니다.

<x-vec>
<script type="application/json">
{
 "label": "내적 = 길이 × 그림자",
 "view": [
  -5,
  -5,
  5,
  5
 ],
 "cases": [
  {
   "name": "바닥에 놓인 a",
   "steps": [
    {
     "caption": "a = (4, 0) 은 오른쪽으로 4, b = (3, 4) 는 오른쪽 3, 위 4 입니다. b 의 길이는 √(9 + 16) = 5 입니다.",
     "items": [
      {
       "id": "a",
       "from": [
        0,
        0
       ],
       "to": [
        4,
        0
       ],
       "label": "a (4, 0)",
       "labelAt": [
        3.2,
        -0.6
       ]
      },
      {
       "id": "v",
       "from": [
        0,
        0
       ],
       "to": [
        3,
        4
       ],
       "color": "accent2",
       "label": "b (3, 4)",
       "labelAt": [
        3.2,
        4.3
       ]
      }
     ]
    },
    {
     "caption": "b 의 끝에서 a 가 놓인 바닥으로 수직선을 내립니다. 빗변 5, 가로 3, 세로 4 인 직각삼각형이 생깁니다.",
     "items": [
      {
       "id": "a",
       "from": [
        0,
        0
       ],
       "to": [
        4,
        0
       ],
       "label": "a (4, 0)",
       "labelAt": [
        3.2,
        -0.6
       ]
      },
      {
       "id": "v",
       "from": [
        0,
        0
       ],
       "to": [
        3,
        4
       ],
       "color": "accent2",
       "label": "b (3, 4)",
       "labelAt": [
        3.2,
        4.3
       ]
      },
      {
       "id": "p",
       "type": "line",
       "from": [
        3,
        4
       ],
       "to": [
        3,
        0
       ],
       "color": "accent2"
      }
     ]
    },
    {
     "caption": "b 가 a 위에 드리운 그림자는 가로 3 입니다. 사이각의 cos 는 가로 ÷ 빗변 = 3 ÷ 5 = 0.6. 그래서 a 의 길이 × b 의 길이 × cos = 4 × 5 × 0.6 = 12 입니다.",
     "items": [
      {
       "id": "a",
       "from": [
        0,
        0
       ],
       "to": [
        4,
        0
       ],
       "label": "a (4, 0)",
       "labelAt": [
        3.2,
        -0.6
       ]
      },
      {
       "id": "v",
       "from": [
        0,
        0
       ],
       "to": [
        3,
        4
       ],
       "color": "accent2",
       "label": "b (3, 4)",
       "labelAt": [
        3.2,
        4.3
       ]
      },
      {
       "id": "p",
       "type": "line",
       "from": [
        3,
        4
       ],
       "to": [
        3,
        0
       ],
       "color": "accent2"
      },
      {
       "id": "s",
       "from": [
        0,
        0
       ],
       "to": [
        3,
        0
       ],
       "color": "warn",
       "label": "그림자 3",
       "labelAt": [
        0.6,
        0.5
       ]
      }
     ]
    },
    {
     "caption": "같은 자리끼리 곱해 더하면 4 × 3 + 0 × 4 = 12. 두 계산이 같습니다. a 의 y 가 0 이라, 성분 곱의 합이 곧 a 의 길이 4 × 그림자 3 이기 때문입니다.",
     "items": [
      {
       "id": "a",
       "from": [
        0,
        0
       ],
       "to": [
        4,
        0
       ],
       "label": "a (4, 0)",
       "labelAt": [
        3.2,
        -0.6
       ]
      },
      {
       "id": "v",
       "from": [
        0,
        0
       ],
       "to": [
        3,
        4
       ],
       "color": "accent2",
       "label": "b (3, 4)",
       "labelAt": [
        3.2,
        4.3
       ]
      },
      {
       "id": "p",
       "type": "line",
       "from": [
        3,
        4
       ],
       "to": [
        3,
        0
       ],
       "color": "accent2"
      },
      {
       "id": "s",
       "from": [
        0,
        0
       ],
       "to": [
        3,
        0
       ],
       "color": "warn",
       "label": "4 × 3 = 12",
       "labelAt": [
        0.4,
        0.5
       ]
      }
     ]
    }
   ]
  },
  {
   "name": "비스듬한 f",
   "steps": [
    {
     "caption": "이번에는 기준 방향이 비스듬합니다. 길이 1 인 f = (0.6, 0.8) 과 v = (4, 2). f 의 길이는 √(0.36 + 0.64) = 1 입니다.",
     "items": [
      {
       "id": "fl",
       "type": "line",
       "from": [
        0,
        0
       ],
       "to": [
        3,
        4
       ],
       "color": "muted"
      },
      {
       "id": "f",
       "from": [
        0,
        0
       ],
       "to": [
        0.6,
        0.8
       ],
       "label": "f",
       "labelAt": [
        0.2,
        1.1
       ]
      },
      {
       "id": "v",
       "from": [
        0,
        0
       ],
       "to": [
        4,
        2
       ],
       "color": "accent2",
       "label": "v (4, 2)",
       "labelAt": [
        4.3,
        1.5
       ]
      }
     ]
    },
    {
     "caption": "v 의 끝에서 f 가 놓인 직선으로 수직선을 내립니다.",
     "items": [
      {
       "id": "fl",
       "type": "line",
       "from": [
        0,
        0
       ],
       "to": [
        3,
        4
       ],
       "color": "muted"
      },
      {
       "id": "f",
       "from": [
        0,
        0
       ],
       "to": [
        0.6,
        0.8
       ],
       "label": "f",
       "labelAt": [
        0.2,
        1.1
       ]
      },
      {
       "id": "v",
       "from": [
        0,
        0
       ],
       "to": [
        4,
        2
       ],
       "color": "accent2",
       "label": "v (4, 2)",
       "labelAt": [
        4.3,
        1.5
       ]
      },
      {
       "id": "p",
       "type": "line",
       "from": [
        4,
        2
       ],
       "to": [
        2.4,
        3.2
       ],
       "color": "accent2"
      }
     ]
    },
    {
     "caption": "그림자 끝은 (2.4, 3.2), 원점에서의 길이는 √(5.76 + 10.24) = 4 입니다. 성분 곱의 합 0.6 × 4 + 0.8 × 2 = 4 와 같습니다. f 의 길이가 1 이라 내적이 곧 그림자 길이입니다.",
     "items": [
      {
       "id": "fl",
       "type": "line",
       "from": [
        0,
        0
       ],
       "to": [
        3,
        4
       ],
       "color": "muted"
      },
      {
       "id": "f",
       "from": [
        0,
        0
       ],
       "to": [
        0.6,
        0.8
       ],
       "label": "f",
       "labelAt": [
        0.2,
        1.1
       ]
      },
      {
       "id": "v",
       "from": [
        0,
        0
       ],
       "to": [
        4,
        2
       ],
       "color": "accent2",
       "label": "v (4, 2)",
       "labelAt": [
        4.3,
        1.5
       ]
      },
      {
       "id": "p",
       "type": "line",
       "from": [
        4,
        2
       ],
       "to": [
        2.4,
        3.2
       ],
       "color": "accent2"
      },
      {
       "id": "s",
       "from": [
        0,
        0
       ],
       "to": [
        2.4,
        3.2
       ],
       "color": "warn",
       "label": "그림자 4",
       "labelAt": [
        1.0,
        2.6
       ]
      }
     ]
    },
    {
     "caption": "v 가 f 의 뒤쪽 (−4, −2) 로 가면 그림자도 뒤쪽에 생기고 내적은 −4 입니다. 부호가 앞뒤입니다.",
     "items": [
      {
       "id": "fl",
       "type": "line",
       "from": [
        -3,
        -4
       ],
       "to": [
        3,
        4
       ],
       "color": "muted"
      },
      {
       "id": "f",
       "from": [
        0,
        0
       ],
       "to": [
        0.6,
        0.8
       ],
       "label": "f",
       "labelAt": [
        0.2,
        1.1
       ]
      },
      {
       "id": "v",
       "from": [
        0,
        0
       ],
       "to": [
        -4,
        -2
       ],
       "color": "accent2",
       "label": "v (−4, −2)",
       "labelAt": [
        -3.4,
        -1.4
       ]
      },
      {
       "id": "p",
       "type": "line",
       "from": [
        -4,
        -2
       ],
       "to": [
        -2.4,
        -3.2
       ],
       "color": "accent2"
      },
      {
       "id": "s",
       "from": [
        0,
        0
       ],
       "to": [
        -2.4,
        -3.2
       ],
       "color": "warn",
       "label": "−4",
       "labelAt": [
        -0.8,
        -2.4
       ]
      }
     ]
    }
   ]
  }
 ]
}
</script>
</x-vec>

그래서 내적의 정식 모양은 이렇습니다.

```text
a · b = (a 의 길이) × (b 의 길이) × cos(사이각)
      = a.x × b.x + a.y × b.y + a.z × b.z
```

한쪽이 길이 1 이면 내적은 **다른 쪽이 그 방향에 드리운 그림자의 길이**입니다. 둘 다 길이 1 이면 앞의 두 곱이 1 이 되어 **내적 = cos(사이각)** 만 남습니다.
그림자가 같은 쪽에 생기면 양수, 수직이면 0, 반대쪽에 생기면 음수라서 부호가 앞뒤를 가릅니다.

| 사이각 | cos (가로 ÷ 빗변) | 빗변이 1 일 때 그림자 |
| --- | --- | --- |
| 0° | 1 | 1. 빗변이 그대로 눕는다 |
| 60° | 0.5 | 0.5 |
| 90° | 0 | 0. 수직이라 그림자가 없다 |
| 120° | −0.5 | 반대쪽으로 0.5 |
| 180° | −1 | 반대쪽으로 1 |

처음 표에서 본 1, 0.71, 0, −0.71, −1 이 cos 0°, 45°, 90°, 135°, 180° 입니다.

## 시야각은 cos 와 비교한다

적의 시야가 앞쪽 120 도라면, 좌우로 60 도씩입니다. 사이각이 60 도 이하면 보입니다.
각이 작을수록 cos 가 크니까, **사이각 ≤ 60°** 는 **내적 ≥ cos 60° = 0.5** 와 같은 말입니다.

| 시야 (전체) | 좌우로 | 기준 cos |
| --- | --- | --- |
| 180° | 90° | 0 (앞쪽 반 전부) |
| 120° | 60° | 0.5 |
| 90° | 45° | 0.71 |
| 60° | 30° | 0.87 |

<x-vec>
<script type="application/json">
{
  "label": "시야 120도 안에 있나",
  "view": [-3, -1, 3, 3],
  "steps": [
    {
      "caption": "앞 (0, 1) 을 보는 적. 점선이 좌우 60 도 경계입니다. 경계 방향과 앞의 내적은 cos 60° = 0.5 입니다.",
      "items": [
        { "id": "f", "from": [0, 0], "to": [0, 1], "label": "앞", "labelAt": [0.35, 1.2] },
        { "id": "l", "type": "line", "from": [0, 0], "to": [-2.6, 1.5], "color": "muted", "label": "60°", "labelAt": [-2.2, 1.9] },
        { "id": "r", "type": "line", "from": [0, 0], "to": [2.6, 1.5], "color": "muted", "label": "60°", "labelAt": [2.2, 1.9] }
      ]
    },
    {
      "caption": "플레이어 A 쪽 방향 (0.6, 0.8). 내적 0 × 0.6 + 1 × 0.8 = 0.8. 0.5 보다 크니 시야 안입니다.",
      "items": [
        { "id": "f", "from": [0, 0], "to": [0, 1], "label": "앞", "labelAt": [0.35, 1.2] },
        { "id": "l", "type": "line", "from": [0, 0], "to": [-2.6, 1.5], "color": "muted", "label": "60°", "labelAt": [-2.2, 1.9] },
        { "id": "r", "type": "line", "from": [0, 0], "to": [2.6, 1.5], "color": "muted", "label": "60°", "labelAt": [2.2, 1.9] },
        { "id": "a", "from": [0, 0], "to": [0.6, 0.8], "color": "accent2", "label": "A 0.8", "labelAt": [1.0, 1.1] }
      ]
    },
    {
      "caption": "플레이어 B 쪽 방향 (−0.95, 0.3). 내적 0.3. 앞쪽이긴 하지만 0.5 보다 작아 시야 밖입니다.",
      "items": [
        { "id": "f", "from": [0, 0], "to": [0, 1], "label": "앞", "labelAt": [0.35, 1.2] },
        { "id": "l", "type": "line", "from": [0, 0], "to": [-2.6, 1.5], "color": "muted", "label": "60°", "labelAt": [-2.2, 1.9] },
        { "id": "r", "type": "line", "from": [0, 0], "to": [2.6, 1.5], "color": "muted", "label": "60°", "labelAt": [2.2, 1.9] },
        { "id": "a", "from": [0, 0], "to": [0.6, 0.8], "color": "accent2", "label": "A 0.8", "labelAt": [1.0, 1.1] },
        { "id": "b", "from": [0, 0], "to": [-0.95, 0.3], "color": "warn", "label": "B 0.3", "labelAt": [-1.4, 0.0] }
      ]
    }
  ]
}
</script>
</x-vec>

```csharp
float viewAngle = 120f;

// 좌우로 절반씩. Deg2Rad 는 도(°)를 Mathf.Cos 가 받는 단위(라디안)로 바꾸는 값
float minDot = Mathf.Cos(viewAngle * 0.5f * Mathf.Deg2Rad);   // 0.5

// .normalized 는 방향은 그대로 두고 길이만 1 로 맞춘 벡터 (정규화)
Vector3 toPlayer = (player.position - transform.position).normalized;

bool canSee = Vector3.Dot(transform.forward, toPlayer) >= minDot;
```

`minDot` 은 시야각이 안 바뀌면 한 번만 구해 두면 됩니다. 매 프레임 적마다 하는 일은 곱셈 세 번과 덧셈 두 번입니다.

## 시야각을 볼 때는 둘 다 길이 1 이어야 한다

`toPlayer` 에 `.normalized` 를 붙인 이유가 있습니다.
내적은 **길이 × 길이 × cos** 라서, 길이가 1 이 아니면 값이 cos 가 아닙니다.

앞이 (0, 1) 일 때, 플레이어 방향을 정규화했는지에 따라 판정이 갈립니다.

| 플레이어까지 | 사이각 | 정규화 안 한 내적 | 정규화한 내적 | 120° 시야 |
| --- | --- | --- | --- | --- |
| (6, 8) | 37° | 8 | 0.8 | 안 |
| (10, 1) | 84° | 1 | 0.1 | **밖** |

(10, 1) 은 거의 옆인데, 정규화하지 않으면 내적이 1 이라 기준 0.5 를 넘어 "보인다" 가 됩니다. 멀리 있을수록 값이 커져서 생기는 일입니다.
반대로 **부호만 볼 때는 정규화가 필요 없습니다.** 길이는 늘 양수라서 곱해도 부호가 바뀌지 않습니다. 백어택 코드에 `.normalized` 가 없던 이유입니다.

| 하려는 것 | 비교 | 정규화 |
| --- | --- | --- |
| 앞인가 뒤인가 | `Dot > 0` | 필요 없음 |
| 시야각 안인가 | `Dot >= cos(절반)` | **둘 다 필요** |
| 얼마나 정면인가 (0 ~ 1 점수) | `Dot` 값 그대로 | 둘 다 필요 |

## 각도가 꼭 필요하면 Vector3.Angle

사이각을 도(°)로 보고 싶으면 `Vector3.Angle(a, b)` 가 있습니다. 안에서 내적을 두 길이로 나눠 cos 를 구한 뒤, **acos** 로 각도로 바꿉니다. acos 는 cos 를 거꾸로 돌리는 함수로, 0.5 를 넣으면 60° 를 돌려줍니다.

| | `Vector3.Dot` | `Vector3.Angle` |
| --- | --- | --- |
| 돌려주는 것 | 숫자 (길이 1 이면 cos) | 0° ~ 180° |
| 하는 일 | 곱셈과 덧셈 | 정규화 + 내적 + acos |
| 쓰는 곳 | 판정, 비교 | 화면에 각도를 보여 줄 때, 디버그 |

둘 다 **왼쪽과 오른쪽을 가리지 못합니다.** 왼쪽 45 도와 오른쪽 45 도의 내적이 똑같이 0.71 이었습니다.
어느 쪽으로 돌아야 하는지까지 알려면 두 벡터 모두에 수직인 벡터를 만드는 외적(`Vector3.Cross`)을 함께 씁니다. 그 벡터가 위를 향하는지 아래를 향하는지가 왼쪽과 오른쪽을 가릅니다.

내적은 판정 말고도 곳곳에 나옵니다. 빛이 면을 정면으로 비추면 밝고 비스듬히 비추면 어두운 것도, 면의 방향과 빛의 방향의 내적으로 밝기를 정하기 때문입니다.

## 정리

- 내적은 x 끼리, y 끼리, z 끼리 곱해서 더한 숫자 하나입니다
- 내적은 `길이 × 길이 × cos(사이각)` 과 같습니다. (4, 0) · (3, 4) 는 4 × 3 + 0 × 4 = 12 이고, 4 × 5 × 0.6 = 12 입니다
- 길이 1 인 방향 f 와 v 의 내적은 v 를 f 위에 내린 그림자의 길이이고, 둘 다 길이 1 이면 cos 만 남습니다
- 부호가 앞뒤를 가릅니다. 0 보다 크면 앞, 0 이면 수직, 작으면 뒤입니다. 부호만 볼 때는 정규화가 필요 없습니다
- 시야각은 `Dot >= cos(시야각 / 2)` 로 판정하고, 이때는 두 벡터 모두 길이 1 이어야 합니다
- 내적은 왼쪽과 오른쪽을 가리지 못합니다