Skip to content

Instantly share code, notes, and snippets.

@Lambda1357
Last active January 24, 2023 00:17
Show Gist options
  • Save Lambda1357/4276281e8a37b2211a27786493d6a6cf to your computer and use it in GitHub Desktop.
Save Lambda1357/4276281e8a37b2211a27786493d6a6cf to your computer and use it in GitHub Desktop.
Doba's candy drop 360 회전 플랫폼 구현 로직

실제 객체들의 회전 구현 로직

MapLoopNormalPos

    private void Update()
    {
        normalizedPlayerPosition = NormalizeToLoopMap(playerTrans.position.x);

        if (playerTrans.position.x < frontMapBlock.position.x)
        {
            backMapBlock.position = new Vector3(frontMapBlock.position.x - mapSize.x, mapOffsetY, 0);
        }
        else
        {
            backMapBlock.position = new Vector3(frontMapBlock.position.x + mapSize.x, mapOffsetY, 0);
        }

        DoMapLoop();

        if (IsRepositionNeeded)
        {
            Reposition();
        }
    }

    private void DoMapLoop()
    {
        if ((playerTrans.position.x > (frontMapBlock.position.x + mapSize.x)) || (playerTrans.position.x < (frontMapBlock.position.x - mapSize.x)))
        {
            SwapBlocks();
        }
    }

    void SwapBlocks()
    {
        Transform _ = frontMapBlock;
        frontMapBlock = backMapBlock;
        backMapBlock = _;
    }

    private void Reposition()
    {
        Vector3 plResetPos = playerTrans.position;
        plResetPos.x = 0;

        Vector3 camResetPos = Camera.main.transform.position;
        camResetPos.x -= playerTrans.position.x;

        foreach (Transform repositionFollower in playerRepositionFollowers)
        {
            Vector3 destination = repositionFollower.position;
            destination.x -= playerTrans.position.x;

            repositionFollower.position = destination;
        }

        playerTrans.position = plResetPos;
        Camera.main.transform.position = camResetPos;
    }

실제 업데이트문과 메서드는 위와 같습니다 기본 컨셉트는 전체 맵을 절반으로 분리하여, 플레이어가 현재 올라와 있는 맵 블럭을 frontMapBlock으로, 그렇지 않은 맵을 backMapBlock으로 지정합니다 보스를 중앙에 두고 원형의 공간을 캐릭터가 질주하는 콘셉트이므로 실제 좌우로 배치된 맵의 양 끝을 이어야 합니다 그래서 위 코드에서 플레이어가 절반으로 자른 frontMapBlock의 왼편에 있다면 backMapBlock을 왼쪽에, 그 반대라면 오른편에 배치하여 플레이어가 어느 방향으로 이동하더라도 맵이 반복되는 것처럼 보이도록 처리하였습니다.

DoMapLoop()에서 플레이어가 현재 올라와있는 맵 블럭인 frontMapBlock에서 벗어난 좌표인지 검사하여 만약 그렇다면, SwapBlocks()을 호출합니다. SwapBlocks()frontMapBlockbackMapBlock을 바꾸어, 플레이어가 특정 방향으로 계속 이동하더라도 맵이 지속적으로 반복될 수 있도록 두 블럭을 서로 맞바꿉니다.

원경 표현 로직

farsightFov1

public class FarsightCamera : MonoBehaviour
{
    public Camera LeftFarCam, RightFarCam;

    public float camOffsetY = -3.0f;

    private void Start()
    {
        if (MapLooper.Instance)
        {
            Vector3 leftCamPos = LeftFarCam.transform.position;
            leftCamPos.x = -MapLooper.Instance.mapSize.x;
            leftCamPos.y = camOffsetY;
            LeftFarCam.transform.position = leftCamPos;

            Vector3 rightCamPos = RightFarCam.transform.position;
            rightCamPos.x = MapLooper.Instance.mapSize.x;
            rightCamPos.y = camOffsetY;
            RightFarCam.transform.position = rightCamPos;
        }
        else
            throw new Exception(this + ": MapLooper Not Found");
    }
}

맵 뒤편 원경을 비추는 방법은 훨씬 간단합니다.

기본적으로 한 디스플레이에 여러 카메라를 사용한 뒤, 카메라 컴포넌트의 Depth 값을 조정하여 여러번 렌더링하는 방식을 사용하였습니다.

발판과 같이 보여주고 싶은 부분만을 렌더링하는 카메라 둘을 메인카메라의 차일드로 생성하여, 맵의 길이만큼 카메라를 떨어뜨려놓는 좌표로 위치를 조정합니다. 위 이미지에서 보실 수 있는 것처럼, 메인 카메라는 플레이어를 중심으로 두기 위해 부드럽게 움직이면서, 맵의 양 끝단을 비추는 카메라가 절묘하게 맞물려 추가 카메라 이외의 특별한 로직 없이 원경이 그려지는 것을 볼 수 있습니다.

맵은 기본적으로 반복되기 때문에, 360도의 원형 맵을 기준으로 좌측 90도 지점과 우측 90도 지점의 상을 그린 뒤, 두 상을 겹쳐서 씬에서는 끊어진 지점을 마치 이어진 것처럼 그려내는 것입니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment