using UnityEngine; public class Projectile : MonoBehaviour { public float m_Speed = 12f; public int m_MaxBounce = 3; public float radius = 0.1f; Vector2 dir; Vector2 prevPos; int bounceCount; public void Set() { dir = transform.up.normalized; bounceCount = m_MaxBounce; } void Update() { prevPos = transform.position; float moveDist = m_Speed * Time.deltaTime; transform.position += (Vector3)(dir * moveDist); } private void OnTriggerEnter2D(Collider2D collision) { if (bounceCount <= 0) { gameObject.SetActive(false); return; } Vector2 currentPos = transform.position; Vector2 moveVec = currentPos - prevPos; float distance = moveVec.magnitude; Vector2 moveDir = distance > 0 ? moveVec / distance : dir; // CircleCast로 정확한 충돌 지점(centroid)과 법선 탐색 RaycastHit2D[] hits = Physics2D.CircleCastAll(prevPos, radius, moveDir, distance); RaycastHit2D hit = new RaycastHit2D(); bool found = false; foreach (var h in hits) { if (h.collider == collision) { // 자기 자신(시작 위치에서 걸리는 경우) 제외 로직이 필요할 수 있으나, // distance > 0 체크 등으로 보완. 여기서는 가장 먼저 닿는 지점을 찾음. hit = h; found = true; break; } } Vector2 normal; Vector2 targetPos; if (found) { normal = hit.normal; // CircleCast의 centroid는 충돌 시의 원의 중심 위치입니다. targetPos = hit.centroid; } else { // fallback: ClosestPoint Vector2 closestRef = collision.ClosestPoint(prevPos); normal = (prevPos - closestRef).normalized; if (normal == Vector2.zero) { normal = (prevPos - (Vector2)collision.bounds.center).normalized; } targetPos = closestRef + normal * radius; } // 반사 dir = Vector2.Reflect(dir, normal).normalized; bounceCount--; // 회전 float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg - 90f; transform.rotation = Quaternion.Euler(0, 0, angle); // 위치 보정 transform.position = targetPos; } }