쯔꾸르식 유니티 게임 공부

07.카메라를 영역을 맵 화면으로 제한하기

ruripanda 2025. 1. 1. 21:22

본 강좌는 케이디님의 쯔꾸르풍 유니티 게임 만들기 강좌를 참고하여 만들었음을 알려드립니다

using UnityEditor.U2D.Aseprite;
using UnityEngine;
using UnityEngine.SceneManagement;

public class TransferMap : MonoBehaviour
{
    public string transferMapName;//이동할 맵의 이름

    public Transform target;
    public BoxCollider2D targetBound;

    private CameraManager theCamera;
    private MovingObjcet thePlayer; 
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        theCamera = FindAnyObjectByType<CameraManager>();
        thePlayer = FindAnyObjectByType<MovingObjcet>();//다수객체에서 MovingObjcet를 찾아온다
    }

    // Update is called once per frame
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.name == "Player")
        {
            thePlayer.currentMapName = transferMapName;
            theCamera.SetBound(targetBound);
            theCamera.transform.position = new Vector3(thePlayer.transform.position.x, thePlayer.transform.position.y, theCamera.transform.position.z);
            //카메라 스크립트의 경우 필자가 수정했다(플레이어 포지션.x ,플레이어 포지션.y, 카메라 포지션.z)로 이동하게 함
            thePlayer.transform.position = target.transform.position;
        }
    }
}​

 

using UnityEngine;
using UnityEngine.SceneManagement;

public class TransferScene : MonoBehaviour
{
    public string transferMapName; //이동할 맵의 이름

    private MovingObjcet thePlayer;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        thePlayer = FindAnyObjectByType<MovingObjcet>();
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.name == "Player")
        {
            thePlayer.currentMapName = transferMapName;
            SceneManager.LoadScene(transferMapName);
        }
    }
}

 

위 스크립트 2개는 원래 하나의 스크립트로 써 놨던 TransformMap스크립트다

구분을 위해서 Scene와 Map로 구분해놨다

using UnityEngine;

public class CameraManager : MonoBehaviour
{
    static CameraManager instance;

    public GameObject target;//카메라가 따라갈 대상
    public float moveSpeed;//카메라가 얼마나 빠른 속도로 대상을 추적할지
    private Vector3 targetPosition;//대상의 현재 위치 값

    public BoxCollider2D bound;//카메라 시야 범위

    private Vector3 minBound;//최소 시야범위
    private Vector3 maxBound;//최대 시야범위
    //박스 콜라이더 영역의 최소 최대 xyz값을 지님

    private float halfWidth;
    private float halfHeight;
    //카메라의 반너비, 반 높이 값을 지닐 변수

    private Camera theCamera;
    //카메라의 반 높이값을 구할 속성을 이용하기 위한 변수

    private void Awake()
    {
        if (instance != null)
        {
            Destroy(this.gameObject);
        }
        else
        {
            DontDestroyOnLoad(this.gameObject);
            instance = this;
        }
    }

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        theCamera = GetComponent<Camera>();

        minBound = bound.bounds.min;//minbound값을 넣는다
        maxBound = bound.bounds.max;//maxbound값을 넣는다
        halfHeight = theCamera.orthographicSize;//반 높이 값
        halfWidth = halfHeight * Screen.width / Screen.height;
    }

    // Update is called once per frame
    void Update()
    {
        if (target.gameObject != null)
        {
            targetPosition.Set(target.transform.position.x, target.transform.position.y, this.transform.position.z);

            this.transform.position = Vector3.Lerp(this.transform.position, targetPosition, moveSpeed * Time.deltaTime);
            //Time.deltaTime 초당 이동구현용 코드

            float clampedX = Mathf.Clamp(this.transform.position.x, minBound.x + halfWidth, maxBound.x - halfWidth);
            float clampedY = Mathf.Clamp(this.transform.position.y, minBound.y + halfHeight, maxBound.y - halfHeight);

            this.transform.position = new Vector3(clampedX,clampedY, this.transform.position.z);
        }
    }

    public void SetBound(BoxCollider2D newBound)
    {
        bound = newBound;
        minBound = bound.bounds.min;//minbound값을 넣는다
        maxBound = bound.bounds.max;//maxbound값을 넣는다
    }
}

 

sing UnityEngine;

public class Bound : MonoBehaviour
{
    private BoxCollider2D bound;

    private CameraManager theCamera;
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        bound = GetComponent<BoxCollider2D>();
        theCamera = FindAnyObjectByType<CameraManager>();
        theCamera.SetBound(bound);
    }
}

 

이번 강좌에서 작성된 스크립트

 

이번 강좌를 위해서 하나의 객체를 만들어 줄건데 카메라를 맵 영역에 가둘 오브젝트로 바운드를 만들었다

박스 콜라이더를 만들어서 맵의 크기 만큼 만들어 준다

박스 콜라이더에는 Is Trigger을 선택해줘야 중력값으로 캐릭터가 안 밀린다

이 두개의 코드는 카메라의 기준이 바운드를 넘지 못하게 잡아주는 수치다

반 넒이 만큼 더해주고, 반 넒이만큼 빼준다

이 코는 카메라의 반 높이값을 구할 속성을 이용하기 위한 함수

이렇게 코드를 작성해준다

여기서 중요한게 halfWidth변수는 반높이로

halfHeight와 Screen.width(게임 해상도)를 곱한 것이다

 

그리고 여기서 중요한게 원래 카메라 메니저에는 void start에 인스턴스가 들어가 있었다

이걸 새로운 함수

void Awake()에 넣어준다

위 함수는 어웨이크라고 부르면서 void start가 실행되기 전에 한번 실행되는 스크립트다

오브젝트가 비활성화 되어 있어도 실행되는 함수로 사용할때 한번 신경써주면 좋다

 

위 코드는 처음보는 코드일 것이다 이 함수 수치의 출처는

여기다

 

그리고 void Update에

위 함수를 추가해준다

 

여기서 Clamp()를 설명해주겠는데

 

 

Ai가 이렇게 설명해줬다

최대값과 최소값에 어떤 값을 가두는 함수다

 

예를 들어서 clamp(10, 0, 100)이라과 설정해두면

-100이라는 값을 입력해도 0이하이기 때문에 0을 반환하고

반대로 +999라는 값을 넣어도 최대허용 값이 100이므로 100만 나온다

 

즉 이 함수는

clampedX = Mathf.Clamp(기본 값, 최소값, 최대값)으로 설정된 것이다

clampedY도 똑같이 생각하면 된다

 

카메라가 밖으로 이동학하게 배치해도

 

이렇게 제한이 걸린다

 

다음은 맵에서 맵을 이동할때 바운드를 바꾸는 방법을 알아보자

 

 

일단 이동할 영역에 새롭게 바운드를 추가해준다

 

카메라 매니져에 위 함수를 추가해준다

다른 스크립트에서 바운드 선택을 수정하게 해주는 함수다

 

trarsferMap스크립트에 이 아래 변수를 추가해준다

이동할때 바운드를 수정하기 위해 변수를 만들어준다

 

그리고 이 코드를 작성해 넣고 

 

 

인스팩터에 새로운 바운드를 지정해준다

 

그럼 이렇게 벗어나지 않게 된다

 

다음은 씬을 이동할때 바운드를 수정해주는 법을 배워본다

 

새 스크립트를 작성해준다

 

 

 

이렇게 바운드를 씬에 배치하고 스크립트도 배치해준다

 

스크립트가 시작되었을때 바로 현 맵의 바운드로 바꿔준다

 

오늘 강좌는 이걸로 종료!