유니티(Unity)

프리팹

염두리안 2025. 4. 21. 17:46
728x90
반응형

스크립트 흐름

  • 컨트롤러 스크립트
    • 플레이어 컨트롤러 : 버튼 입력에 따라 좌우로 이동
    • 화살 컨트롤러 : 화면 위에서 아래로 떨어짐
  • 제너레이터 스크립트
    • 화살 제너레이터 : 화살을 1초에 한 개씩 생성
  • 감독 스크립트
    • 플레이어가 화살에 맞으면 HP 게이지를 줄임

 

배경 레이어 번호와 화면 관계 : 배경 레이어(0) - 플레이어 레이어(1) - UI 레이어(2) ← 사용자의 눈 👀

  • [오브젝트] - [Inspector] - [Additonal Settings] - [Order in Layer] 로 레이어 순서 변경 가능

 

화살표 키를 누르면 플레이어 움직이기

  • GetKeyDown : 키가 눌렸는지 검출하기 위해 Input 클래스의 GetKeyDown 메서드 사용 | 매개변수로 전다한 키가 눌리는 순간 true를 한 번만 반환
// 왼쪽 화살표가 눌렸을 때
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
	transform.Translate(-2, 0, 0); // 왼쪽으로 「2」 움직인다
}

// 오른쪽 화살표가 눌렸을 때
if (Input.GetKeyDown(KeyCode.RightArrow))
{
	transform.Translate(2, 0, 0); // 오른쪽으로 「2」 움직인다
}

 

화살 떨어뜨리기(Physics 사용 X)

  • Physics 기능 : 유니티가 중력을 계산해주므로 스크립트를 사용하지 않고도 화살을 떨어뜨릴 수 있음
    • 하지만 직접적인 움직임(정밀한 표현 등)을 처리하기가 어려움
  • 화면 밖으로 나가는 오브젝트를 소멸시키는 이유? 화살이 보이지 않는 곳에서 계속 떨어지면 컴퓨터 역시 계속 계산을 해야 하기 때문에 메모리가 낭비됨 ~> Destory를 사용해 소멸시킴
// 프레임마다 등속으로 낙하시킨다
transform.Translate(0, -0.1f, 0);

// 화면 밖으로 나오면 오브젝트를 소멸시킨다
if (transform.position.y < -5.0f)
{
        Destroy(gameObject);
}

 

충돌 판정하기

  • 충돌 판정 → 충돌을 감지하는 부분 | 충돌 반응 → 충돌 감지 후 다음 움직임을 정하는 붑분
  • 엄밀한 충돌 판정 : 오브젝트 모양대로 충돌 판정 | 원을 사용한 충돌 판정 : 오브젝트 형상을 단순하게 원이라 가정 후 판정
    • 예제에선 원의 중심 좌표, 반지름을 이용해 충돌 판정
public class ArrowController : MonoBehaviour
{
    GameObject player;

    void Start()
    {
        this.player = GameObject.Find("player"); 
    }

    void Update()
    {
        // 프레임마다 등속으로 낙하시킨다 
        transform.Translate(0, -0.1f, 0);
        
        // 화면 밖으로 나오면 오브젝트를 삭제한다 
        if (transform.position.y < -5.0f)
        {
            Destroy(gameObject);
        }

        // 충돌 판정
        Vector2 p1 = transform.position;              // 화살의 중심 좌표
        Vector2 p2 = this.player.transform.position;  // 플레이어의 중심 좌표
        Vector2 dir = p1 - p2;
        float d = dir.magnitude;
        float r1 = 0.5f;  // 화살의 반경
        float r2 = 1.0f;  // 플레이어의 반경

        if (d < r1 + r2)
        {
            // 충돌한 경우는 화살을 지운다
            Destroy(gameObject);
        }
    }
}

 

프리팹 만들기

  • 프리팹? 설계도와 같은 것... 같은 오브젝트를 많이 만들고 싶을 때 주로 사용
    • 장점 : 변경사항이 있을 때 프리팹 파일만 수정하면 되므로 비교적 편하게 수정이 가능하다!
  • 설계도로 쓰고 싶은 오브젝트를 [Hierarchy]에서 [Project]로 드래그&드롭 => 프리팹 생성 완료 | 이때 프리팹 제작시 사용했던 오브젝트가 쓸 일이 없을 땐 지워도 무관
  • Time.deltaTime : 프레임과 프레임 사이의 시간 차이를 delta에 모으고 합계 1초 이상이 되면 비움... 그래서 1초마다 한번씩 화살이 생성됨
    • Instantiate : 매개변수로 프리팹을 전달하면 반환값으로 프리팹 인스턴스를 돌려줌 | 이 메서드를 사용해 화살 인스턴스 생성
public class ArrowGenerator : MonoBehaviour
{
    public GameObject arrowPrefab;	// 생성할 화살 프리팹
    float span = 1.0f;	// 화살 생성 주기
    float delta = 0;		// 흐른 시간 누적 타이머

    void Update()
    {
        this.delta += Time.deltaTime;
        if (this.delta > this.span)	// 1초마다 한 번 실행
        {
            this.delta = 0;
            GameObject go = Instantiate(arrowPrefab);   	// 프리팹에서 새 화살 생성
            int px = Random.Range(-6, 7);
            go.transform.position = new Vector3(px, 7, 0);
        }
    }
}
  • 이 코드는 공장 오브젝트(빈 오브젝트)를 만들어 적용 - [Arrow Prefab]에 프리팹 이미지를 넣으면 끝

 

UI 만들기 : UI부품을 Scene 뷰에 배치 - UI를 갱신하는 감독 스크립트 작성 - 빈 오브젝트를 만드록 작성한 스크립트를 적용

  • [Hierarchy] - [UI] - [Image] 하면 Canvas 아래에 Image 생성 완료
    • 그 이미지에 적용할 소스 이미지 드래그&드롭(예제에선 hpGauge)
  • 앵커 포인트 설정 : 화면 크기가 바뀔 때 어디를 원점으로 해서 UI 부품 좌표를 다시 계산하는가? | 적절히 설정하면 실행하는 기기의 화면 크기에 의존하지 않는 UI 제작 가능
  • HP 게이지 줄여나가기 : Fill Amount 변수 값을 바꾸면 이미지 표시 영역을 줄이거나 늘릴 수 있음
    • Horizontal : 가로 방향으로 이미지를 잘라냄
    • Vertical : 세로 방향으로 이미지를 잘라냄
    • Radial 90 : 90도 선형으로 이미지를 잘라냄
    • Radial 180 : 반원형으로 이미지를 잘라냄
    • Radial 360 : 원형으로 이미지를 잘라냄
    • 예제에선 다음과 같이 설정

감독 스크립트 : 감독 스크립트 작성하기 → 빈 오브젝트 만들기 → 빈 오브젝트에 감독 스크립트 적용

// HP 게이지를 관리하는 컨트롤러로, 게임 중 플레이어가 데미지를 입었을 때 HP를 10% 감소시키는 역할
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // UI를 사용하므로 잊지 않고 추가한다

public class GameDirector : MonoBehaviour
{
    GameObject hpGauge;

    void Start()
    {
        this.hpGauge = GameObject.Find("hpGauge");
    }

    public void DecreaseHp()
    {
        this.hpGauge.GetComponent<Image>().fillAmount -= 0.1f;	// 10% 감소
    }
}

 

HP가 줄었다고 감독에게 알리기

if (d < r1 + r2)
{
	// 감독 스크립트에 플레이어와 화살이 충돌했다고 전달
    GameObject director = GameObject.Find("GameDirector");	// 호출
    director.GetComponent<GameDirector>().DecreaseHp();
    
    // 충돌했다면 화살을 지운다
    Destroy(gameObject);
}
728x90
반응형