먼저 Bounce Threshold가 원인인지 가른다
Unity 6.5 문서에서 Bounce Threshold는 상대 선형 속도가 임계값보다 낮은 충돌을 비탄성으로 처리하는 전역 Physics 2D 값이다. 공이 벽에 닿을 때마다 멈춘다고 해서 무조건 이 값 탓은 아니다. 마찰, Bounciness, 겹친 Collider, Sleep, 모서리 형상도 따로 봐야 한다.
Unity 6000.5.3f1 빈 프로젝트에서 마찰 0, Bounciness 1, Bounce Combine Maximum인 공과 세로 벽을 만들었다. 측정한 기본 임계값은 1.0이었다. 0.005초 고정 스텝으로 세 번 반복한 핵심 결과는 이랬다.
기본 1.0 · 법선 속도 0.5 → 충돌 뒤 0.0 (반사 없음)
시험 0.1 · 법선 속도 0.5 → 충돌 뒤 -0.5 (완전 반사)
기본 1.0 · 법선 속도 2.0 → 충돌 뒤 -2.0 (완전 반사)전체 속도 말고 접촉 법선 성분을 기록한다
빗겨맞을 때 공의 전체 속도만 보면 원인을 놓친다. 실험에서 속도 (0.5, 2.0)의 크기는 약 2.06이었지만 세로 벽을 향한 법선 성분은 0.5였다. 기본 임계값에서는 x만 0으로 죽고 y=2.0은 유지됐다. 임계값을 0.1로 낮추자 x는 -0.5로 반사됐다.
아래 Probe를 공에 잠깐 붙여 실제 게임의 충돌 속도를 모은다. 여러 접촉점이 있는 모서리는 로그를 따로 분류한다.
using UnityEngine;
public sealed class BounceProbe2D : MonoBehaviour
{
private void OnCollisionEnter2D(Collision2D hit)
{
if (hit.contactCount == 0) return;
Vector2 normal = hit.GetContact(0).normal.normalized;
float normalSpeed = Mathf.Abs(
Vector2.Dot(hit.relativeVelocity, normal));
Debug.Log($"normal={normalSpeed:F3}, total={hit.relativeVelocity.magnitude:F3}, contacts={hit.contactCount}");
}
}0.001을 복사하지 말고 게임 속도에서 값을 정한다
재현에서는 정상적으로 튕겨야 할 최소 법선 속도 0.5보다 낮은 0.1을 시험값으로 썼다. 이 수치는 모든 게임의 정답이 아니다. 먼저 공과 벽의 PhysicsMaterial2D에 Friction 0, 필요한 Bounciness, 의도한 Bounce Combine이 들어갔는지 확인한다. 그다음 로그에서 정상 반사가 필요한 최소 법선 속도를 찾고, 그보다 낮은 Bounce Threshold를 Project Settings > Physics 2D에서 시험한다.
코드로 고정해야 한다면 초기 씬이 뜨기 전에 한 번 적용하고, 왜 그 값인지 측정 기준을 주석으로 남긴다.
Bounce Threshold는 전역 값이므로 공 하나만 보지 말고 상자 더미, 착지, 느린 접촉도 다시 돌린다. 이번 실험에서는 Default Contact Offset을 0.01에서 바꾸지 않았다. 접촉 거리 설정을 반발 임계값 해결책처럼 함께 움직일 이유가 없었다.
using UnityEngine;
public static class ArcadeBounceSetup
{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void ApplyMeasuredThreshold()
{
// 이 게임에서 정상 반사가 필요한 최소 법선 속도는 0.5였다.
Physics2D.bounceThreshold = 0.1f;
}
}Continuous와 수동 Reflect는 다른 문제다
같은 저속 충돌에서 Collision Detection을 Discrete에서 Continuous로 바꿔도 결과는 0.0 그대로였다. Continuous는 빠른 물체가 Collider를 통과하는 경로를 줄이는 선택지이지, 낮은 속도를 탄성 충돌로 바꾸는 스위치가 아니다.
시험 임계값 0.1에서도 Bounciness를 0으로 두면 공은 튕기지 않았다. 엔진 반사를 쓸 거라면 머티리얼 탄성을 0으로 만들고 첫 접촉점 하나로 Vector2.Reflect를 강제하지 않는다. 완전한 커스텀 이동을 택할 때는 다중 접촉, 모서리, 고정 스텝을 포함한 별도 설계로 다룬다.
직접 재현
검증일
검증 환경Unity 6000.5.3f1 (c2eb47b3a2a9), Windows 10 22H2, empty project, batchmode/nographics/noUpm, Physics2D Script simulation at a 0.005-second step; three independent Editor processes
정적 세로 벽과 동적 원형 공을 둔 통제 프로젝트에서 7개 조건을 별도 Editor 프로세스 3회로 반복했다. 측정한 기본 Bounce Threshold 1.0에서는 법선 속도 0.5가 0으로 죽었고, 시험값 0.1에서는 -0.5로 반사됐다. 전체 속도 2.06인 빗겨맞기와 Continuous 조건도 분리했으며, 타임스탬프를 뺀 세 결과는 완전히 같았다.