Coding Feature.

[Unity 3D] 3D 퐁 만들기 #8 공이 벽 또는 플레이어를 뚫고 지나가는 버그 해결, 카메라 이동 효과 구현 본문

Toy Project/MICRO-PONG [Unity3D]

[Unity 3D] 3D 퐁 만들기 #8 공이 벽 또는 플레이어를 뚫고 지나가는 버그 해결, 카메라 이동 효과 구현

codingfeature 2024. 1. 21. 23:04

지금까지 게임을 개발하면서 생긴 버그가 있었습니다.

 

바로 아래 그림과 같이 속도가 높아지면서 공이 플레이어 또는 벽을 뚫고 지나가는 경우가 발생하는 것입니다!

 

 

위 버그가 발생하는 원인을 곰곰히 생각해보니,

먼저 공이 빠른 속도로 플레이어를 향해 다가오고,

플레이어가 공을 쳤을때 공의 방향 벡터가 랜덤으로 회전되면서 새로운 공의 경로가 지정됩니다.

 

이때 새로 지정된 공의 방향 벡터가, 우연히 공과 가장 가까운 벽으로 향하도록 지정되면서 공은 벽을 뚫고 지나가게 되는 것입니다.

 

이를 해결하기 위해 벽의 Collider를 더 두껍게 만들어보기도 했으나 소용이 없었습니다.

 

몇 가지 해결 방안(벽과 가까울 경우 공의 경로가 맵 내부로 향하도록 벡터를 조절하는 등)을 구현해보고 높은 속도에서 실험을 해봤지만 결국 아래 해결 방안이 가장 깔끔하고 잘 되었습니다..!

 

해결방안은 각 프레임마다 공을 이동시키는 데, 이동된 공이 맵 외부에 있는 경우 다시 그 전 프레임의 위치로 이동시키고, 공의 이동 벡터를 180도 회전시키는 것입니다.

 

우선 게임 매니저에서 각 벽의 Game Object를 받아옵니다.

 ..
    public GameObject wallBottom;
    public GameObject wallLeft;
    public GameObject wallRight;
    public GameObject wallTop;

 

 

그리고 공 스크립트의 Update 함수에서 다음과 같이 공이 맵 밖으로 나갔는지 확인하게 됩니다.

    void Update()
    {
        transform.Translate(ballMovementVector.normalized * ballSpeed * Time.deltaTime);
        ballLine.transform.position = new Vector3(ballLine.transform.position.x, ballLine.transform.position.y, transform.position.z);
        if (transform.position.x < GameManager.Instance.wallLeft.transform.position.x
            || transform.position.x > GameManager.Instance.wallRight.transform.position.x
            || transform.position.y < GameManager.Instance.wallBottom.transform.position.y
            || transform.position.y > GameManager.Instance.wallTop.transform.position.y)
        {
            Debug.Log("Out of Bound!!");
            transform.Translate(-1 * ballMovementVector.normalized * ballSpeed * Time.deltaTime);
            RotateBallVector(180f);
        }
    }
    ...

 

만약 Translate 함수를 통해서 공을 이동시켰을 때 맵의 외부에 있는 경우(if 조건문), 다시 원래 위치로 이동시킵니다. 이는 앞서 Translate에 넣었던 값을 -1 만큼 곱하고 다시 Translate 시켜서 해결했습니다.

그리고 원래 이동하던 방향이 맵 외부를 향한 것이므로, 이전에 작성했던 RotateBallVector() 함수를 사용해서 180도 회전시킵니다.

 

추가로, 공이 빠른 속도로 이동할 때 플레이어의 판을 뚫는 버그도 발생해서, 이는 플레이어의 Collider를 두껍게 만들어 줌으로써 해결했습니다!

 

 

 

위와 같이 공 속도를 빠르게 설정해서 테스팅을 해보아도 공이 벽을 뚫고 튕겨나가지 않는 것을 확인하였습니다!

 

 

그리고 위 GIF를 보시면 아시겠지만 카메라도 플레이어의 위치에 따라서 조금씩 이동하는 효과를 구현해보았습니다.

public class CameraManager : MonoBehaviour
{
..
    Vector3 originalPlayerPosition;
    Vector3 originalCameraHolderPosition;
    
    public float CameraMovementRatio;
..

    private void Start()
    {
..
        originalPlayerPosition = Player.transform.position;
        originalCameraHolderPosition = CameraHolder.transform.position;
    }

    private void Update()
    {
        ChangeCameraHolderPosition((Player.transform.position - originalPlayerPosition) * CameraMovementRatio);
    }
..

    public void ChangeCameraHolderPosition(Vector3 localPosition)
    {
        CameraHolder.transform.position = originalCameraHolderPosition + localPosition;
    }
}

 

ChangeCameraHolderPosition 함수를 구현하고, 인자에 플레이어의 원래 위치와 현재 위치의 차이 값을 전달해주어 그 만큼 카메라 홀더를 이동시켜줌으로써 구현하였습니다.

 

 

 

다음에는 Firebase를 이용해서 온라인 스코어보드를 구현해보겠습니다!