유니티(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
반응형