본문 바로가기

프로그래밍/Unity 3D

[Unity3D] 유니티 Circle Collider 2D 반사하기

게임 제작 중 반사 스킬로 CircleCollider2D가 또 다른 CircleCollider2D에 충돌했을 때의 반사되는 현상을 스크립트로 구현해봤습니다.

Trigger가 아니라면 자동으로 충돌하여 반사가 되지만 미사일, 스킬 같은 경우에는 스크립트로 통제해야하는 경우가 있으실 겁니다.

일정한 속도를 유지하거나 특정 물체에만 충돌해야 할경우 스크립트를 이용할 수밖에 없습니다.

그럴 경우에 아래에서 제가 구현한 반사 스크립트를 적용할 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        private void OnTriggerEnter2D(Collider2D col)
        {
            Vector2 dir = col.GetComponent<Rigidbody2D>().velocity;
            col.GetComponent<Rigidbody2D>().velocity = v2Rotate(-dir, 2*getAngle(dir, (transform.position - col.transform.position)));        
        }
        float getAngle(Vector2 vec1, Vector2 vec2)
        {
            float angle = (Mathf.Atan2(vec2.y,vec2.x) - Mathf.Atan2(vec1.y,vec1.x)) * Mathf.Rad2Deg;
            return angle;
        }
        Vector2 v2Rotate(Vector2 aPoint, float aDegree)
        {
            float rad = aDegree * Mathf.Deg2Rad;
            float s = Mathf.Sin(rad);
            float c = Mathf.Cos(rad);
            return new Vector2(
                aPoint.x * c - aPoint.y * s,
                aPoint.y * c + aPoint.x * s);
        }
cs

순차적으로 코드를 설명드리겠습니다.

반사체에 충돌체가 충돌하는 경우를 예로 들어보겠습니다.

위의 스크립트는 반사체의 컴포넌트입니다.


3번째 줄 : dir 에 충돌체가 가지는 속도를 저장합니다.

4번째 줄 : 충돌체의 속도를 반사되는 속도로 지정합니다. 아래에서 설명드리겠습니다.

v2Rotate(-dir, 2*getAngle(dir, (transform.position - col.transform.position)))

위의 코드를 보시면 총 두 가지의 사용자 정의 함수가 사용됩니다.

바로 getAnglev2Rotate입니다. 각각 float(degree 각도), Vector2를 반환합니다.

입사각 구하기

우선 getAngle함수로 두 벡터의 사이각을 구합니다.

인수 1 : dir , 3번째 줄에서 선언했던 충돌체의 벡터.

인수 2 : 반사체의 위치 - 충돌체의 위치 -> Vector3간의 연산입니다.  Vector2를 인수로 받으므로 z는 무시합니다. 아래그림을 참고해 주시기 바랍니다.

노란색 부분의 각도를 반환합니다. 그 각도가 바로 입사각입니다.

그리고 2를 곱합니다.

2를 곱하면 입사각 + 반사각이 됩니다.


벡터 회전하기

그 각도만큼 v2Rotate함수를 이용해 회전합니다.

이 때 v2Rotate의 첫번째 인수는 기존벡터의 반대방향입니다.


v2Rotate(-dir, 2*getAngle(dir, (transform.position - col.transform.position)))

위의 코드를 다시 우리말로 한 마디로 정리하자면

입사각+반사각 만큼 기존 벡터의 역벡터를 회전한 것을 반환한다

입니다.


이렇게 간단하게 두 CircleCollider2D간의 반사를 구현할 수 있습니다.

생각해낸 과정은 좀 간단하지 않았습니다만..

감사합니다.