[Unity 응용] 7. 아이템 구현에 대하여
※참고사항※
해당 포스트는 본업 개발자가 정성껏 포스팅한 포스트가 아닙니다!
평범한 고등학생이 유니티를 배우면서 적어나가는 포스트라는 점을 이해해 주십사 하고 청하는 바입니다.
(잘못된 정보는 댓글로 감사히 받겠습니다!)
저번 포스팅에서 예고했듯이 이번 포스팅은 이전까지 배웠던 내용들을 응용해서 간단한 아이템을 먹고 사용하는 것을 구현해보도록 하겠습니다!
목차
1. UI 만들기
2. 로직 구현하기
2-1. 플레이어 이동
2-2. 아이템 먹기
2-3. 아이템 사용하기
1. UI 만들기
일단 UI를 만들어봅시다.
(아래와 같이 대충 만드시면 됩니다!)
어찌저찌 UI를 만들었다면 모든 오브젝트에 Collider가 필요합니다.
(저는 캡슐 모양 아이템이니 캡슐 콜라이더를 사용하겠습니다!)
콜라이더를 설정했다면 아이템이라는 "Tag"를 추가할겁니다.
(지금은 종류가 1개지만 아이템의 종류가 많다고 가정하면 "Tag"로 관리하는 것이 편하기 때문입니다!)
참고)
유니티가 기본적으로 제공하는 태그
- Respawn
- Finish
- EditorOnly
- MainCamera
- Player
- GameController
아래와 같이 태그를 추가해주세요!
태그를 추가했다면 플레이어 오브젝트에게는 기본적으로 제공하는 Player 태그를 붙여주세요!
이제 로직을 짜러갑시다.
2. 로직 구현하기
일단 이전에 플레이어에게 추가했던 스크립트는 remove 해주세요.
(플레이어 오브젝트를 클릭 후 지워야 하는 컴포넌트에 우클릭 하신 뒤 Remove Component를 눌러주세요!)
그 다음 스크립트를 추가해서 Player라고 이름을 지어봅시다.
다른 하나도 추가해서 Item이라고 지어봅시다.
2-1. 플레이어 이동
일단 Player 스크립트입니다.
Player라면 움직여야겠죠?
이동하는 코드를 짜보겠습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[SerializeField] // 변수를 직렬화 해줍니다. (이 내용은 나중에 알아보겠습니다!)
private float speed;
[SerializeField]
private int item_num;
private Rigidbody2D rigid;
private void Awake()
{
// 변수 초기화
speed = 5f;
item_num = 0;
rigid = GetComponent<Rigidbody2D>();
// Z축 고정
rigid.freezeRotation = true;
}
private void Update()
{
// 입력을 받은 뒤에
float h = Input.GetAxisRaw("Horizontal");
// 이동하게 함
rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);
// 이동 속도를 제한함 (velocity -> rigid의 현재 속도)
if (rigid.velocity.x > speed) { rigid.velocity = new Vector2(speed, rigid.velocity.y); }
else if (rigid.velocity.x < speed * (-1)) { rigid.velocity = new Vector2(speed * (-1), rigid.velocity.y); }
// 이동을 멈췄을 시 플레이어도 멈추게 해줌
if (Input.GetButtonUp("Horizontal")) // 좌우 이동 버튼을 때었을 때
{
// normalized -> 벡터 크기를 1로 만든 상태 (단위벡터 / 방향에 따른 이동 속도가 같아지게 하기 위함)
rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y); // 속도를 줄임 (현재 속도에 계속 0.5를 곱해줌)
}
}
}
근데 이러면 Update 메소드에 너무 많은 내용이 있죠?
그럼 "이동"하게 만드는 코드는 메소드를 만들어 묶어봅시다!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[SerializeField] // 변수를 직렬화 해줍니다. (이 내용은 나중에 알아보겠습니다!)
private float speed;
[SerializeField]
private int item_num;
private Rigidbody2D rigid;
private void Awake()
{
// 변수 초기화
speed = 5f;
item_num = 0;
rigid = GetComponent<Rigidbody2D>();
// Z축 고정
rigid.freezeRotation = true;
}
private void Update()
{
// 메소드를 만들었다면 호출하는 것을 잊지 마세요!
Move();
}
// 이동을 담당하는 Move라는 메소드를 만들어서 이동에 관련한 코드를 모두 몰아넣어줌
private void Move()
{
// 입력을 받은 뒤에
float h = Input.GetAxisRaw("Horizontal");
// 이동하게 함
rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);
// 이동 속도를 제한함 (velocity -> rigid의 현재 속도)
if (rigid.velocity.x > speed) { rigid.velocity = new Vector2(speed, rigid.velocity.y); }
else if (rigid.velocity.x < speed * (-1)) { rigid.velocity = new Vector2(speed * (-1), rigid.velocity.y); }
// 이동을 멈췄을 시 플레이어도 멈추게 해줌
if (Input.GetButtonUp("Horizontal")) // 좌우 이동 버튼을 때었을 때
{
// normalized -> 벡터 크기를 1로 만든 상태 (단위벡터 / 방향에 따른 이동 속도가 같아지게 하기 위함)
rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y); // 속도를 줄임 (현재 속도에 계속 0.5를 곱해줌)
}
}
}
이러면 Update 메소드는 굉장히 깔끔해지게 됩니다.
이쯤에서 중간 점검하겠습니다.
일단 Player에게는 Player 스크립트를, Item에게는 Item 스크립트를 추가해주세요!
위와 같이 제어를 해주고나면 저번에 배웠을 때처럼 오브젝트가 날뛰지 않게 됩니다!
(이제 절반 이상은 왔습니다!)
2-2. 아이템 먹기
이어서 콜라이더를 이용해서 아이템을 먹어보겠습니다.
(위에서 추가하지 않았다면 모든 오브젝트에 모양에 맞는 콜라이더를 추가해주세요!)
private void OnCollisionEnter2D(Collision2D collision)
{
// 닿은 오브젝트의 태그가 "Item"일 때 실행
if (collision.gameObject.tag == "Item")
{
item_num++;
// 코드의 실행이 잘 되는지 보기 위한 출력문 없어도 실행에는 관계가 없음
print("아이템을 먹었습니다! 아이템 개수 :" + item_num);
}
}
아이템을 먹는 로직은 생각보다 간단하죠?
이러면 아이템이 무한대로 먹어지는 거 아닌가요?
하시는 눈치 좋으신 분들이 있을겁니다.
이걸 위해서 우리는 Item이라는 스크립트를 만들었죠!
Item 스크립트로 넘어갑시다!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Item : MonoBehaviour
{
public string type; // 지금은 사용하지 않지만 나중에 아이템의 종류가 많아졌을 때 아이템을 구별할 수 있게 해주는 변수입니다!
private void OnCollisionEnter2D(Collision2D collision)
{
// Player 태그를 가진 오브젝트에 닿으면 자기 자신을 파괴함
if (collision.gameObject.tag == "Player") { Destroy(this.gameObject); }
}
}
사실 이건 Player 스크립트에서도 처리할 수 있긴 한데요.
저는 이런 식으로 사용하는 것을 좋아하는 지라
이런 식으로 사용해보겠습니다.
이제 코드를 저장해주고 실행해봅시다!
(실행 전에 아이템의 개수를 늘렸습니다!)
2-3. 아이템 사용하기
마지막으로 아이템을 사용해보도록 하겠습니다.
(아이템 사용은 로직만 구현하면 됩니다!)
// 아이템 사용 코드가 있는 메소드만 따왔습니다!
private void Update()
{
// 메소드를 만들었다면 호출하는 것을 잊지 마세요!
Move();
// E 키를 누르면 아이템 사용
if (Input.GetKeyDown(KeyCode.E)) { ItemUse(); }
}
private void ItemUse()
{
// 아이템 개수가 0개면 실행하지 않음
if (item_num <= 0) { print("아이템이 없어요 ㅠㅠ"); return; }
// 이 아래의 코드부턴 아이템을 실질적으로 사용하는 코드입니다.
item_num--;
// 이 아래에는 아이템의 효과를 넣으면 되는데요.
// 아직은 이렇다할 효과랄게 없어서 그냥 print() 뿐인 점 양해 부탁드립니다.
print("아이템을 사용했다!!!");
}
이제 저장하고 실행해보도록 하겠습니다!
위와 같이 아이템이 있을 때만 사용하고 없으면 없다고 출력하는 모습을 보여줍니다.
Player
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[SerializeField] // 변수를 직렬화 해줍니다. (이 내용은 나중에 알아보겠습니다!)
private float speed;
[SerializeField]
private int item_num;
private Rigidbody2D rigid;
private void Awake()
{
// 변수 초기화
speed = 5f;
item_num = 0;
rigid = GetComponent<Rigidbody2D>();
// Z축 고정
rigid.freezeRotation = true;
}
private void Update()
{
// 메소드를 만들었다면 호출하는 것을 잊지 마세요!
Move();
// E 키를 누르면 아이템 사용
if (Input.GetKeyDown(KeyCode.E)) { ItemUse(); }
}
// 이동을 담당하는 Move라는 메소드를 만들어서 이동에 관련한 코드를 모두 몰아넣어줌
private void Move()
{
// 입력을 받은 뒤에
float h = Input.GetAxisRaw("Horizontal");
// 이동하게 함
rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);
// 이동 속도를 제한함 (velocity -> rigid의 현재 속도)
if (rigid.velocity.x > speed) { rigid.velocity = new Vector2(speed, rigid.velocity.y); }
else if (rigid.velocity.x < speed * (-1)) { rigid.velocity = new Vector2(speed * (-1), rigid.velocity.y); }
// 이동을 멈췄을 시 플레이어도 멈추게 해줌
if (Input.GetButtonUp("Horizontal")) // 좌우 이동 버튼을 때었을 때
{
// normalized -> 벡터 크기를 1로 만든 상태 (단위벡터 / 방향에 따른 이동 속도가 같아지게 하기 위함)
rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y); // 속도를 줄임 (현재 속도에 계속 0.5를 곱해줌)
}
}
// 아이템 사용을 위한 코드를 모아둠
private void ItemUse()
{
// 아이템 개수가 0개면 실행하지 않음
if (item_num <= 0) { print("아이템이 없어요 ㅠㅠ"); return; }
// 이 아래의 코드부턴 아이템을 실질적으로 사용하는 코드입니다.
item_num--;
// 이 아래에는 아이템의 효과를 넣으면 되는데요.
// 아직은 이렇다할 효과랄게 없어서 그냥 print() 뿐인 점 양해 부탁드립니다.
print("아이템을 사용했다!!!");
}
private void OnCollisionEnter2D(Collision2D collision)
{
// 닿은 오브젝트의 태그가 "Item"일 때 실행
if (collision.gameObject.tag == "Item")
{
item_num++;
// 코드의 실행이 잘 되는지 보기 위한 출력문 없어도 실행에는 관계가 없음
print("아이템을 먹었습니다! 아이템 개수 :" + item_num);
}
}
}
Item
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Item : MonoBehaviour
{
public string type; // 지금은 사용하지 않지만 나중에 아이템의 종류가 많아졌을 때 아이템을 구별할 수 있게 해주는 변수입니다!
private void OnCollisionEnter2D(Collision2D collision)
{
// Player 태그를 가진 오브젝트에 닿으면 자기 자신을 파괴함
if (collision.gameObject.tag == "Player") { Destroy(this.gameObject); }
}
}
이상으로 포스팅을 마치겠습니다.
다음 포스팅에서는 플레이어 점프를 구현해 보겠습니다!