프로젝트의 설정 메뉴를 구현하던 중 이상한 버그를 만났습니다.
Debug.Log
를 찍어보니 이벤트 연결이나 함수 호출 자체에는 아무런 문제가 없었습니다. 그런데도 두 시스템이 서로에게 이상한 영향을 주고 있었습니다.
문제의 원인은 아주 간단한 수학에 있었습니다. 바로 '값의 범위(Range)'가 서로 맞지 않았기 때문입니다.
비유하자면:
CameraManager
는 '시속(km/h)' 단위로 속도를 이해합니다. (예:sensitivity = 50f
)- UI 슬라이더는 '퍼센트(%)' 단위로만 값을 표시합니다. (0 ~ 1)
LoadSettings()
함수가 PlayerPrefs
에서 '시속 50km'라는 값을 가져와서 '퍼센트'만 표시하는 슬라이더에 억지로 넣으니, 슬라이더는 자기 최대치인 '100%(값: 1)'로 값을 잘라버렸습니다.
결과적으로, 설정창을 열었다 닫기만 해도 카메라 감도가 의도치 않게 '시속 1km'로 줄어드는 현상이 발생했던 것입니다.
이 문제를 해결하려면, 두 시스템이 서로 알아들을 수 있도록 단위를 변환해주는 과정이 필요합니다.
다행히 Unity의 Mathf
클래스는 이 과정을 위한 아주 편리한 함수들을 제공합니다.
SettingsMenu.cs
수정 코드public class SettingsMenu : UiBase
{
// 1. 카메라 감도의 실제 범위를 변수로 정의합니다.
[Header("감도 범위 설정")]
[SerializeField] private float _minCameraSensitivity = 1f;
[SerializeField] private float _maxCameraSensitivity = 10f;
// ...
private void LoadSettings()
{
// 2. 불러온 값을 슬라이더의 0~1 범위로 '정규화'합니다.
float savedSens = PlayerPrefs.GetFloat("CameraSensitivity", 3f);
_cameraSensitivitySlider.SetValueWithoutNotify(
Mathf.InverseLerp(_minCameraSensitivity, _maxCameraSensitivity, savedSens)
);
// ...
}
public void OnCameraSensitivityChanged()
{
if (GameManager.Instance?.CameraManager != null)
{
// 3. 슬라이더의 0~1 값을 실제 감도 범위로 '역정규화'합니다.
float actualSensitivity = Mathf.Lerp(
_minCameraSensitivity,
_maxCameraSensitivity,
_cameraSensitivitySlider.value
);
GameManager.Instance.CameraManager.Sensitivity = actualSensitivity;
}
}
public void OnApplyButton()
{
// 4. 저장할 때도 실제 감도 값을 저장합니다.
float actualSensitivity = Mathf.Lerp(
_minCameraSensitivity,
_maxCameraSensitivity,
_cameraSensitivitySlider.value
);
PlayerPrefs.SetFloat("CameraSensitivity", actualSensitivity);
// ...
}
// ...
}
,,,
Mathf.InverseLerp(최소, 최대, 현재값): 특정 범위 안에서 현재 값이 차지하는 비율(0~1)을 계산해줍니다. (실제 값 -> 슬라이더 값)
Mathf.Lerp(최소, 최대, 비율): 0~1 사이의 비율 값을 실제 값 범위에 맞게 변환해줍니다. (슬라이더 값 -> 실제 값)
UI와 실제 게임 로직 사이에서 값을 주고받을 때는, 각 시스템이 사용하는 값의 '단위'와 '범위'를 명확히 이해하고, 필요에 따라 정규화/역정규화하는 과정이 필수적이라는 것을 배웠습니다. 이 수정을 통해 모든 설정 관련 버그가 해결되었습니다.