개요
Unity의 Mathf 클래스(class)는 수학 연산을 위한 다양한 함수(function)를 제공합니다. 특히 값 제한, 부동소수점 비교 등 게임 개발에서 자주 사용하는 함수(function)들을 포함합니다.
부동소수점 오차란?
부동소수점(float)은 정확한 값을 표현하지 못하고 근사치를 사용합니다. 따라서 연산 결과가 예상과 다를 수 있습니다.
부동소수점 오차 예제
float a = 0.1f + 0.2f;
Debug.Log(a); // 0.30000001 (정확히 0.3이 아님!)
float b = 1.0f - 0.9f;
Debug.Log(b); // 0.09999999 (정확히 0.1이 아님!)
1. Mathf.Clamp() - 값 제한
Mathf.Clamp()는 값을 지정된 범위 내로 제한합니다.
기본 사용법
using UnityEngine;
public class PlayerController : MonoBehaviour
{
void Update()
{
// 플레이어의 X 위치를 -8과 8 사이로 제한
float clampedX = Mathf.Clamp(transform.position.x, -8f, 8f);
transform.position = new Vector3(clampedX, transform.position.y, transform.position.z);
}
}
간단한 사용법
using UnityEngine;
public class PlayerController : MonoBehaviour
{
void Update()
{
// 한 줄로 위치 제한
transform.position = new Vector3(
Mathf.Clamp(transform.position.x, -8f, 8f),
transform.position.y,
transform.position.z
);
}
}
HP 제한 예제
using UnityEngine;
public class HealthSystem : MonoBehaviour
{
public float health = 100f;
public float maxHealth = 100f;
void Update()
{
// HP를 0과 maxHealth 사이로 제한
health = Mathf.Clamp(health, 0f, maxHealth);
}
public void TakeDamage(float damage)
{
health -= damage;
health = Mathf.Clamp(health, 0f, maxHealth);
}
}
2. Mathf.Clamp01() - 0~1 범위 제한
Mathf.Clamp01()는 값을 0과 1 사이로 제한합니다. UI fillAmount 등에 유용합니다.
기본 사용법
using UnityEngine;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public Image hpGauge;
public void DecreaseHp()
{
// HP 감소
hpGauge.fillAmount -= 0.2f;
// 0과 1 사이로 제한 (fillAmount는 0~1 사이 값)
hpGauge.fillAmount = Mathf.Clamp01(hpGauge.fillAmount);
}
}
부동소수점 오차 처리
using UnityEngine;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public Image hpGauge;
public void DecreaseHp()
{
hpGauge.fillAmount -= 0.2f;
// 부동소수점 오차 방지: 매우 작은 값(0.001 이하)을 0으로 처리
if (hpGauge.fillAmount < 0.001f)
{
hpGauge.fillAmount = 0f;
}
// 0과 1 사이로 제한
hpGauge.fillAmount = Mathf.Clamp01(hpGauge.fillAmount);
}
}
Clamp01 vs Clamp 비교
float value = 1.5f;
// Clamp01: 0~1 사이로 제한
float clamped01 = Mathf.Clamp01(value); // 1.0
// Clamp: 지정된 범위로 제한
float clamped = Mathf.Clamp(value, 0f, 1f); // 1.0 (동일한 결과)
3. Mathf.Approximately() - 부동소수점 비교
Mathf.Approximately()는 부동소수점 오차를 고려하여 두 값을 비교합니다.
문제 상황
// ❌ 문제: 정확한 비교는 부동소수점 오차로 인해 실패할 수 있음
float a = 0.1f + 0.2f; // 0.30000001
if (a == 0.3f) // false! (예상과 다름)
{
Debug.Log("같음");
}
해결 방법
// ✅ 해결: Mathf.Approximately() 사용
float a = 0.1f + 0.2f; // 0.30000001
if (Mathf.Approximately(a, 0.3f)) // true (오차를 고려)
{
Debug.Log("같음");
}
실제 사용 예제
using UnityEngine;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public Image hpGauge;
public void DecreaseHp()
{
hpGauge.fillAmount -= 0.2f;
// 부동소수점 오차를 고려한 비교
if (hpGauge.fillAmount <= 0f || Mathf.Approximately(hpGauge.fillAmount, 0f))
{
// HP가 0이거나 거의 0인 경우 게임 오버
GameOver();
}
}
void GameOver()
{
Debug.Log("Game Over!");
}
}
4. 부동소수점 오차 처리 패턴
패턴 1: 작은 값 처리
// 매우 작은 값을 0으로 처리
if (hpGauge.fillAmount < 0.001f)
{
hpGauge.fillAmount = 0f;
}
패턴 2: Approximately 사용
// 부동소수점 오차를 고려한 비교
if (Mathf.Approximately(value, targetValue))
{
// 값이 거의 같음
}
패턴 3: 범위 체크
// 범위 내에 있는지 확인
float epsilon = 0.001f;
if (Mathf.Abs(value - targetValue) < epsilon)
{
// 값이 거의 같음
}
5. 다른 Mathf 고급 함수(function)들
Mathf.Abs() - 절댓값
float value = -5.5f;
float abs = Mathf.Abs(value); // 5.5
Mathf.Max() / Mathf.Min() - 최댓값/최솟값
float max = Mathf.Max(10f, 20f, 30f); // 30
float min = Mathf.Min(10f, 20f, 30f); // 10
Mathf.Lerp() - 선형 보간
// a와 b 사이를 t 비율로 보간 (0~1)
float result = Mathf.Lerp(0f, 10f, 0.5f); // 5.0
Mathf.SmoothStep() - 부드러운 보간
// Lerp보다 부드러운 보간
float result = Mathf.SmoothStep(0f, 10f, 0.5f);
6. 실제 사용 예제
예제 1: 화면 경계 제한
using UnityEngine;
public class PlayerController : MonoBehaviour
{
void Update()
{
Move();
// 화면 경계 제한
float clampedX = Mathf.Clamp(transform.position.x, -8f, 8f);
transform.position = new Vector3(clampedX, transform.position.y, transform.position.z);
}
void Move()
{
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Translate(-0.2f, 0, 0);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Translate(0.2f, 0, 0);
}
}
}
예제 2: HP 시스템
using UnityEngine;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public Image hpGauge;
public void DecreaseHp()
{
// HP 감소
hpGauge.fillAmount -= 0.2f;
// 부동소수점 오차 방지
if (hpGauge.fillAmount < 0.001f)
{
hpGauge.fillAmount = 0f;
}
// 0과 1 사이로 제한
hpGauge.fillAmount = Mathf.Clamp01(hpGauge.fillAmount);
// 게임 오버 체크 (부동소수점 오차 고려)
if (hpGauge.fillAmount <= 0f || Mathf.Approximately(hpGauge.fillAmount, 0f))
{
GameOver();
}
}
void GameOver()
{
Debug.Log("Game Over!");
}
}
7. 정리
주요 Mathf 함수(function)
| 함수(function) | 용도 | 예제 |
|---|---|---|
Mathf.Clamp(value, min, max) |
값 범위 제한 | Clamp(health, 0, 100) |
Mathf.Clamp01(value) |
0~1 범위 제한 | Clamp01(fillAmount) |
Mathf.Approximately(a, b) |
부동소수점 비교 | Approximately(a, 0.3f) |
Mathf.Abs(value) |
절댓값 | Abs(-5.5f) = 5.5 |
Mathf.Max(a, b) |
최댓값 | Max(10, 20) = 20 |
Mathf.Min(a, b) |
최솟값 | Min(10, 20) = 10 |
부동소수점 오차 처리
- 작은 값 처리:
if (value < 0.001f) value = 0f; - Approximately 사용:
Mathf.Approximately(a, b) - 범위 체크:
Mathf.Abs(a - b) < epsilon
베스트 프랙티스
- Clamp 사용: 값이 범위를 벗어나지 않도록 제한
- Approximately 사용: 부동소수점 비교 시 사용
- 오차 처리: 작은 값은 명시적으로 0으로 처리
- Clamp01 활용: UI fillAmount 등에 유용
연습 문제
-
플레이어의 위치를 화면 경계(-10, 10) 내로 제한하는 코드를 작성하세요.
-
HP가 0 이하로 내려가지 않도록 Mathf.Clamp를 사용하는 코드를 작성하세요.
-
두 float 값이 거의 같은지 비교하는 함수(function)를 Mathf.Approximately를 사용하여 작성하세요.
-
fillAmount가 0에 가까울 때 게임 오버를 처리하는 코드를 작성하세요.