Collision를 사용하지 않고 충돌 감지하기



[스토리]

탁구 게임 개발 중에 탁구공의 물리 적용에 관련해서 며칠째 애를 먹는 중이다.

탁구공의 Physics가 영 말을 듣지 않는데,

현재 물리력에 작용중인 요소는 탁구공의 RigidBody, Collider 그리고 Physics Material이다.

별다른 스크립팅 없이 Unity에서 자체로 제공하는 Physics을 개선 하는데는 Physics Material을 수정하는 것이 가장 빨랐다.

1차 프로토타입 피드백 이후 현실성보다는 탁구공을 더 쉽게 즐길 수 있게 하기 위해 Physics에 보정이 필요하다고 느꼈다.


하지만, 현재는 프로젝트에 Unity에서 제공하는 Physics 사용하고 있기 때문에 여기서 보정을 들어가기란 어렵다고 판단.

탁구공의 충돌 감지부터 다시 만드는 재설계 프로세스에 돌입했다.


자체적인 충돌을 배제하기 위해서 Collision을 사용하지 않는다.

▶ 탁구공의 Collider는 그대로 두고, 라켓의 Collider를 Trigger = true 시킨다.



* 유감이지만 탁구 게임 보다는 충돌 처리가 보편적으로 찾는 내용일 것이라 예상하기에 충돌 처리에 관해서 다루겠다.



1. 설계

원리는 간단하다. 두 물체 사이에 Raycast를 적용할 수 있다는 원리를 활용한다.

탁구공이 움직일 때 매 프레임마다 Raycast를 Check하여 Ray가 hit하게 된 Object를 확인하는 것이다.


Step 1) 현재 frame의 공의 위치와 이전 frame의 공의 위치를 확보하여 그 사이에 Raycast를 적용한다.

Step 2) Raycast에 hit된 Object의 tag를 비교한다.

Step 3) 충돌이 되길 원하는 Obejct가 감지되면 처리하고자 하는 함수를 불러온다.



2. 소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    private Vector3 preBallPosition; // 이전 Frame의 공의 위치를 저장
    private RaycastHit hit; // Raycast에 hit된 객체를 불러온다.
    private void FixedUpdate()
    {
        if ((preBallPosition != null))
        {
            // 현재 위치에서 공의 진행방향으로 Ray를 쏜다.
            // 마지막 Parameter: Ray의 길이는 제한적이여야 하기 때문에 한 프레임동안 움직인 공의 거리를 계산한다.
            if (Physics.Raycast(transform.position, (preBallPosition - transform.position), out hit, Vector3.Distance(preBallPosition, transform.position)))
            {
                // 탁구 라켓에 맞으면
                if (hit.transform.CompareTag("PlayerRacket"))
                {
                    // Do what you want.
                }
            }
        }
        // BallPosition을 저장한다.
        preBallPosition = transform.position;
    }
cs


* Physics에 관련된 작업을 할 때는 Update보다는 FixedUpdate를 사용하는 편이다. *


* Unity Forum에서 설명했으니 참조 *




+ Recent posts