ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 게임개발 4일차 (간단한 슈팅게임 2)
    게임 개발 2025. 5. 26. 19:34

    오늘은 간단하게 어제 작성한 코드를 리뷰해보려고 한다.

     

    유니티에서 스크립트 컴포넌트를 생성하면 기본적으로 MonoBehaviour클래스를 상속받는다.

    유니티에서 C#으로 게임오브젝트에 동작을 붙이기 위한 기본적인 틀이다.

     

    <MonoBehaviour의 함수들>

    Awake() : 오브젝트가 생성될 때 가장 먼저 실행

    OnEnable() : 오브젝트가 활성화될 때 실행

    Start() : 오브젝트가 활성화된 후 첫 프레임 전에 실행

    Update() : 매 프레임마다 실행

    FixedUpdate() : 물리 연산용으로 미리 정한 일정한 시간마다 실행됨 (Update로 프레임마다 실행되면 프레임드랍 등이 일어나면 연산이 잘못될 수 있기 때문)

    LateUpdate() : Update 이후에 실행. 주로 카메라 따라가게 할 때 실행한다고 함.

     

    멤버변수를 public으로 지정하면 인스펙터에서 따로 설정할 수 있고 코드보다 인스펙터의 값을 우선한다.

     


    3차원 벡터는 Vector3(x, y, z)를 사용한다.
    선언은 Vector3 a = new Vector3(1,2,3) 처럼 한다.

     

    <Vector3에서 사용하는 함수&속성>

    a.magnitude : 크기(float)

    a.normalized : 방향(벡터)

    Vector3.Distance(a, b) : a, b사이의 거리(float)

    Vector3.Normalize(a - b) : a-b의 방향(벡터)

    <자주 쓰는 기본 벡터>

    Vector3.zero : (0, 0, 0) 원점

    Vector3.one : (1, 1, 1) 

    Vector3.up (0, 1, 0) 위 방향
    Vector3.down (0, -1, 0) 아래 방향
    Vector3.left (-1, 0, 0) 왼쪽 방향
    Vector3.right (1, 0, 0) 오른쪽 방향

     

    <transform>

    transform은 오브젝트 생성하면 거의 무조건 붙어있는 컴포넌트이다.

    오브젝트의 위치, 크기, 회전을 다룬다.

    transform.position : 오브젝트의 현재 위치

    ex) transform.position = new Vector3(2f, 1f, 0f) : 오브젝트의 현재위치를 2,1,0으로 설정

     

    transform.localPosition : 부모기준 현재 위치

     

    transform.lotation : 회전시킬때 사용

    ex) transform.rotation = Quaternion.Euler(0f, 90f, 0f);
    // 유니티는 (x,y,z)를 바로 넣어주기보다 Quaternion으로 바꿔줘서 넣어줘야 빠르다.

     

    transform.eulerAngles : 회전 값을 확인할 때 사용

    ex) Vector3 angles = transform.eulerAngles;
    Debug.Log(angles);

     

     

     

    transform.localScale : 크기

    ex) transform.localScale = new Vector3(2,2,2) : 오브젝트를 (2,2,2)배로 키움

     

    transform.eulerAngles : 회전 값을 확인할 때 사용

     

     

    Time.deltaTime : 이전 프레임이 끝나고 이번 프레임이 시작되기까지 걸린 시간(초)

    transform.Translate : 오브젝트를 이동
    ex) transform.Translate(방향 * 속도 * 시간); transform.Translate(Vector3.right * 3f * Time.deltaTime)


    <입력관련 함수>
    Input.GetKey(KeyCode.X) : 키를 누르고 있는 동안 true
    Input.GetKeyDown(KeyCode.X) : 키를 딱 누른 순간 true
    Input.GetKeyUp(KeyCode.X) : 키를 떼는 순간 true

    Input.GetMouseButtonDown(Y) 해당 마우스 버튼을 눌렀을 때 한 번만 true
    Input.GetMouseButton(Y) 해당 버튼을 누르고 있는 동안 true
    Input.GetMouseButtonUp(Y) 해당 버튼을 뗐을 때 true
    Input.mousePosition 마우스의 현재 화면 위치 (Vector3)

    ex) Camera.main.ScreenToWorldPoint(Input.mousePosition) : 현재 마우스의 화면위치를 월드에서의 좌표로 바꿔줌

     

    <자주쓰는 입력>

    왼쪽 화살표 KeyCode.LeftArrow(A)
    오른쪽 화살표 KeyCode.RightArrow(D)
    위쪽 화살표 KeyCode.UpArrow(W)
    아래쪽 화살표 KeyCode.DownArrow(S)
    점프 (스페이스) KeyCode.Space
    공격 (Z키) KeyCode.Z
    대쉬 (Shift) KeyCode.LeftShift

    (참고 마우스 왼쪽클릭 0 오른쪽 클릭 1 휠 클릭 2)

     

    if (move.x < 0) GetComponent(SpriteRenderer).flipX = true;

    왼쪽으로 움직이고 있을 때 이 오브젝트의 SpriteRenderer컴포넌트(그림)를 가져와서 X축 반전시킴. 즉 왼쪽을 보게 만듬


    if (move.magnitude > 0) GetComponent<Animator>().SetTrigger("Move");

    움직이고 있으면 Animator 컴포넌트를 가져와서 Move 트리거를 발생시킴

    PlayerIdle (정지 상태)
       └─(Move 트리거 발생)→ PlayerRun (뛰기 상태)

     

    참고로 GameObject 가 컴포넌트들을 가지는 유니티 왼쪽에 자리잡은 오브젝트들의 클래스형 자료형이다.

     

     

    • 트리거(Collider.isTrigger = true) 는 물리 충돌 없이 겹침만 감지
    • 충돌(Collider.isTrigger = false) 는 실제 물리 충돌, 튕기는 효과 포함

     

    함수명 호출 시점 설명

    OnTriggerEnter2D(Collider2D collision) 트리거 충돌 처음 시작할 때 트리거(겹침) 감지
    OnTriggerStay2D(Collider2D collision) 트리거 안에 계속 있을 때 계속 겹쳐있을 때 반복 호출
    OnTriggerExit2D(Collider2D collision) 트리거에서 나갈 때 겹침 끝날 때 호출
    OnCollisionEnter2D(Collision2D collision) 충돌 시작할 때 트리거가 아닌 실제 충돌 감지
    OnCollisionStay2D(Collision2D collision) 충돌 계속될 때 계속 충돌 중일 때 반복 호출
    OnCollisionExit2D(Collision2D collision) 충돌 끝날 때 충돌 종료 시 호출

    ex) private void OnTriggerEnter2D(Collider2D collision) // 트리거(겹침)가 감지 됐을 때
        {
            if (collision.tag == "Wall") // 충돌한 오브젝트의 태그가 "Wall"이면
            {
                gameObject.SetActive(false); // 이 오브젝트를 비활성화 (오브젝트 풀링을 위한 처리)
            }
        }


    public Transform parent; 부모용 transform 변수 선언 (gameobject로는 안됨 transform.parent를 사용해야 하기 때문)

     

    void Start(){

    GameObject obj = Instantiate(prefab, parent); // 프리팹 생성 후 parent 밑에 배치
    obj.SetActive(false); // 처음엔 꺼둠 (비활성 상태)
    pool.Add(obj); // pool이라는 리스트에 넣어놓음

    }

     // 🧲 오브젝트를 꺼내서 사용할 때 호출
        public GameObject Get()
        {
            // 풀에서 비활성화된 오브젝트가 있는지 확인
            foreach (GameObject obj in pool)
            {
                if (!obj.activeInHierarchy) // 현재 씬에서 꺼져있는 오브젝트라면
                {
                    obj.SetActive(true);    // 다시 활성화해서
                    return obj;            // 반환
                }
            }

     

    // 오브젝트 풀에서 총알 가져오기
            GameObject newBullet = GetComponent().Get();
            if (newBullet != null)
            {
                // 총알 위치 지정 (플레이어 아래쪽 살짝)
                newBullet.transform.position = transform.position + new Vector3(0, -0.5f);

                // 총알에 방향 설정
                newBullet.GetComponent().Direction = worldPosition;
            }

     

    위 코드를 오브젝트 풀링이라고 한다. 자주 쓰는 총알 같은 걸 사용할 때마다 만들고 지우는 것보다 미리 많이 만들어두고 on/off 방식으로 하는게 훌륭하기 때문이다.

Designed by Tistory.