본문 바로가기

유니티/확장 프로젝트[3D]

3D 미니 프로젝트 2 - 2 ] 아이템 수집 및 장착, 교체

지난 포스팅에서는 골드메탈님의 에셋과 강의를 통해 캐릭터의 움직임과 애니메이션을 구현하였다.

 

이제는 RPG에서는 빠질 수 없는 요소인 아이템에 대해 구현 해 보도록 하겠다.

 

이 영상을 참고하여 진행하였다. (강좌가 매우 훌륭하니 게임 제작을 하고 싶으면 이 분의 강의를 보는 것을 추천한다.)

 


아이템 생성

 

필드에 떨어진 아이템에 다가가 습득을 하는 기능을 먼저 구현 해 보도록 하자

 

우선 골드메탈님의 에셋에서 아이템 프리팹을 하나 가져 와 준다.

 

그리고 있어 보이게 아래 사진과 같이 아이템 오브젝트의 각도를 Z축으로 기울여 준다.

 

떨어진 아이템 세팅

 

이렇게 기울여 준 다음, 자식에 빈 오브젝트를 하나 생성 해 준다.


빛 효과 추가

 

아이템을 먹음직스럽게(?) 만들어 주기 위해 부가적인 효과들을 추가 해 보겠다.

 

생성한 빈 오브젝트에 Light 컴포넌트를 추가 해 준다.

 

Light 컴포넌트

그리고 위와 같이 아이템 색깔과 유사한 색, 범위(Range) 그리고 빛의 강도(Intensity)를 조절 해 준다.

 

빛을 생성하는 것이기에 땅에 가깝게 해 주어야 빛이 반사되어 보일 것이다. 위치를 조절하면서 적절하게 세팅 해 준다.

 

빛 적용 모습

그럼 위 사진과 같이 빛이 생기게 된다. (너무 작게 캡쳐해서 화질이 좋지 않다..)


파티클 효과 추가

 

빛도 추가 했지만 뭔가 허전 해 보일수도 있다.

 

명색이 장비 아이템이니 효과를 하나 더 추가 해 보도록 하자.

 

이번에는 아이템 자식에 빈 오브젝트를 하나 추가 해 준 다음, Particle System을 추가 해 준다.

 

Particle은 말 그대로 입자들이 뿜어져 나오게 설정하는 것이다.

 

처음 만들게 되면 웬 분홍색 색종이들이 뿜어져 나오게 됨을 볼 수 있다.

분홍색 색종이?

가장 먼저 Renderer로 달려 간다.

Renderer

위 사진처럼 Renderer → Material 에 가서 Line을 검색하면 Default-Line이 나올 것이다.

 

앞으로 이 것을 많이 애용할 것이다.

 

Default-Line 적용 모습

Default-Line을 적용하면 위 사진과 같이 나오게 된다.

 

이제 세부적인 세팅을 해 주도록 하자.

 

속도 조절

Limit Velocity over Lifetime 에 들어 가 준다.

 

여기서는 Drag에 주목 해 주면 된다. Drag를 높은 값으로 설정 할 수록 입자들이 힘에 눌려서 멀리 나가지 못하게 된다.

 

지금 만드는 것은 그렇게 좋은 아이템이 아니니 적당하게 1을 넣어 억제 해 준다. (좋은 아이템은 마음껏 뻗어 나가게 하면 될 것이다!!)

 

주기에 따른 크기 설정

Size over Lifetime에 들어가서 시간에 따라 입자 크기가 줄어들게 만들어 준다.

 

원하는 그래프 모양으로 설정 해 주면 된다.

 

방출량 설정

Emission에 들어가서 입자를 얼마나 뿜어 낼 것인지 설정 해 준다.

모양 설정

Shape에서는 입자가 퍼져 나가는 형태를 설정할 수 있다.

 

이번 아이템에는 위로 콘 형태로 퍼져 나가게 설정하였다.

 

주기에 따른 색 설정

그리고 입자가 생성되고 사라지는 시점에서의 색 디테일을 설정 해 준다.

 

시점별 색 설정

처음에는 주황빛을 띠는 노란색을 설정 해 주었으며, 점점 투명도가 올라가고 흰색이 되게끔 설정 해 주었다.

 

그렇게 하면 아래와 같이 입자들이 나오게 된다.

입자 설정 후


아이템 정보 세팅

 

 

아이템에도 정보가 있다.

 

어떤 아이템인지, 아이템 종류가 무엇인지 등등 정보를 저장 할 스크립트가 필요하다.

 

따라서 Item.cs로 코드를 하나 만들어 준다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Item : MonoBehaviour
{
    public enum Type { Armor, Coin, Weapon }; // 열거형 타입
    public Type type;
    public int value;


    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        transform.Rotate(Vector3.up * 50 * Time.deltaTime);
    }
}

Type은 enum으로 자체적으로 만들어 준다.

 

enum은 객체처럼 만들어 주어야 사용 가능한 점에 주의해야 한다.

 

Update() 에는 아이템이 뱅글뱅글 돌게 해 주었다. (있어 보이게!)

 

아이템 정보 세팅

코드에 아이템 종류와 아이템 코드를 넣어 준다.

 

그리고 아이템 자체의 tag도 weapon을 만들어 넣어 준다.

아이템 태그 설정


아이템 물리 설정

 

 

RPG 게임에서 보스를 잡는 순간에 아이템이 팡 터지면서 사방으로 퍼지는 모습을 본 적 있을 것이다.

 

그렇게 만들기 위해서는 아이템에 RigidBody를 넣어 주어야 한다.

 

물리 효과를 넣으면 Collider도 넣어 주어 아이템이 땅 위에 잘 있게끔 해 주어야 한다.

 

Collider 설정

Collider를 넣어 준다.

 

그런데 사진에 보면 Collider가 두 개 있음을 볼 수 있다.

 

가운데 있는 작은 것은 땅을 지탱하는 용도이고, 밖에 있는 큰 구는 플레이어가 다가갔을 때 인식하여 아이템을 습득하게 되는 범위이다.

 

따라서 밖에 있는 Collider는 isTrigger를 체크 해 주어 Trigger로 처리해야 한다.

 

이제 플레이어에서 아이템에 닿았을 때, 아이템을 습득할 수 있는 코드를 추가 해 보도록 하겠다.

 


아이템 수집 및 장착

 

아이템 수집과 장착은 같이 진행해야 한다.

 

우선 플레이어에 들어 가 준다.

 

플레이어 자식 계층

플레이어 오른 손 까지 들어 가 준 다음, WeaponPoint라는 Empty Object를 만들어 준다.

 

이 오브젝트 하위 오브젝트에 무기들을 넣어 줄 것이다.

 

아이템 장착 모습

이렇게 무기를 미리 장착하고 있는 모습을 만들어 준 다음, 아이템을 먹고 장착을 하면 활성화를 시키는 것이다.

 

이제 코드를 만들어 아이템을 먹고, 장착하는 것을 만들어 보자.

 

플레이어 코드를 열어 아래와 같이 입력 상태 변수를 추가 해 주고, 몇몇 개의 변수들을 추가 해 준다.

 

bool iDown; // 습득 키가 눌렸는가?

//무기 관련
public GameObject[] WeaponList; // 활성화 할 무기 리스트
public bool[] hasWeapons; // 어떤 무기를 가지고 있는가?

GameObject nearObject; // 근처에 떨어져 있는 아이템 오브젝트
GameObject cntEquipWeapon; // 현재 장착하고 있는 무기

int cntindexWeapon = -1; // 현재 끼고 있는 무기 index, 초기 값은 -1로 해 준다.

iDown은 습득 키가 눌렸는지 여부를 나타내는 bool 변수이며, WeaponList는 아까 미리 만들어 두었던 무기들이 들어갈 GameObject 배열이다.

 

그리고 hasWeapons는 해당 무기를 얻었는지 여부를 나타내는 bool 배열이다.

 

nearObject는 플레이어 근처에 있는 Object의 정보를 임시로 담는 오브젝트이다.

 

cntEquipWeapon은 현재 장착하고 있는 무기가 들어갈 게임오브젝트 변수이다.

 

cntindexWeapon은 위에 있는 두 배열에 들어갈 index이다.

 

 

input 함수에 iDown에 들어 갈 input 설정을 해 준다.

void InputKey()
    {
    	// 전에 했던 것들은 생략

        iDown = Input.GetButtonDown("InterAction");

    }

기본적으로 아이템 습득은 'e' 키이다. 여기서는 아이템 습득 뿐 아니라 상호작용 역할도 할 예정이다.

(지형 조사, NPC와 대화 등)

 

이제 키를 설정 해 주도록 하자. (GetKey(KeyCode.E)로 해도 되긴 하지만.. 설정을 해 두는 것도 좋다.)

 

Edit → Project Settings → Input Manager 에서 기존 숫자에서 1을 더한 숫자를 적어 준 다음, 아래 사진과 같이 InterAction 키를 만들어 준다.

InterAction 키 설정

Positive Button에 e를 넣어주면 된다.

 

 private void OnTriggerStay(Collider other)
    {
        if (other.gameObject.tag == "weapon")
        {
            nearObject = other.gameObject;
        }
    }

private void OnTriggerExit(Collider other)
    {
        if(other.gameObject.tag == "weapon")
        {
            nearObject = null;
        }
    }

이제, 플레이어 코드에 OnTriggerStay, Exit를 만들어 준다.

 

말 그대로 닿아 있는 것이 유지될 때는 Stay, 빠져 나가면 Exit이다.

 

Stay일 때는 nearObject에 해당 오브젝트를 넣어 준다.

 

상호작용이기 때문에 여러 오브젝트들이 있을 수 있어 tag를 설정하여 구분 해 주는 것이다.

 

 

이제 플레이어 코드에 새롭게 InterAction() 함수를 만들어 준다.

void InterAction()
    {
        if(iDown && nearObject != null && !isJump && !isSwap)
        {
            // 무기에 닿고 있고(근처 오브젝트가 null이 아님), 점프 상태가 아닐 때, 상호작용 버튼을 누르게 되면 아이템을 습득하게 된다.
            // 이것을 응용하여 NPC와도 대화를 하게끔?

            if(nearObject.tag == "weapon")
            {
                Item item = nearObject.GetComponent<Item>();
                int weaponIndex = item.value; // value를 index로 설정 할 것!

                hasWeapons[weaponIndex] = true;
                Destroy(nearObject);
            }

        }
    }

만약 습득 키(e 키)가 눌리면서, nearObject가 존재하고, 점프중, 회피 중이 아닐 때, 상호작용이 진행된다.

 

만약 nearObject의 tag가 weapon이면 Item 코드를 가져와서 아이템 코드를 배열의 index로 넣어준다.

 

그리고 해당 무기를 얻었다는 것을 표시하기 위해 hasWeapons[weaponIndex] 를 true로 바꾸어 준다.

 

그리고 nearObject를 없애 주어 아이템을 습득했다는 것을 시각적으로 보여 준다.


아이템 장착, 변경

 

 

이제 아이템을 장착하는 함수를 만들어 보자

 

아이템은 fps 게임처럼, 1,2,3번 버튼을 누르면 바뀌게끔 해 주도록 하자

bool sDown1; // 1번 장비
bool sDown2; // 2
bool sDown3; // 3


void InputKey()
{
    // 나머지는 스킵
    
    sDown1 = Input.GetButtonDown("Swap1");
    sDown2 = Input.GetButtonDown("Swap2");
    sDown3 = Input.GetButtonDown("Swap3");

}

1,2,3번 버튼을 설정 한다. (아까처럼 Project Settings에 들어 가 주어 설정한다.)

 

void Swap()
{
    if (sDown1 && (!hasWeapons[0] || cntindexWeapon == 0)) // 1번을 눌렀을 때, 습득을 안했거나, 이미 같은 것을 장착하고 있을 때
        return; // 실행 x
    if (sDown2 && (!hasWeapons[1] || cntindexWeapon == 1)) // 2번을 눌렀을 때, 습득을 안했거나, 이미 같은 것을 장착하고 있을 때
        return; // 실행 x
    if (sDown3 && (!hasWeapons[2] || cntindexWeapon == 2)) // 3번을 눌렀을 때, 습득을 안했거나, 이미 같은 것을 장착하고 있을 때
        return; // 실행 x

    int weaponIndex = -1;
    if (sDown1) weaponIndex = 0;
    if (sDown2) weaponIndex = 1;
    if (sDown3) weaponIndex = 2;

    if ((sDown1 || sDown2 || sDown3) && !isJump && !isSwap && !isDodge) // 1~3번 키가 눌리면서 점프중이 아닐 때! + 무기를 먹었을 때!
    {
        if(cntEquipWeapon != null) // 이미 다른 무기를 끼고 있을 때!
        {
            cntEquipWeapon.SetActive(false); // 먼저 해제!
        }
        cntEquipWeapon = WeaponList[weaponIndex];
        cntindexWeapon = weaponIndex;
        cntEquipWeapon.SetActive(true);

        isSwap = true;
        anim.SetTrigger("DoSwap");

        Invoke("SwapOut",0.3f);

    }
}

void SwapOut() // 스왑 딜레이 설정!
{
    isSwap = false;
}

Swap() 함수이다.

 

처음에는 만약 같은 무기를 장착하고 있거나 무기를 습득하지 않았을 경우에는 Swap() 함수를 바로 종료시킨다.

 

처음에 종료되지 않고 버튼이 눌렸으면 WeaponIndex를 아이템 코드에 맞게 설정 해 준다.

 

이미 끼고 있는 무기가 있다면 (cntEquipWeapon != null), 먼저 무기를 해제 해 준다.

 

그리고 장착할 무기를 넣어 주고, 활성화 해 준다.

 

Swap 전용 애니메이션도 발동시켜 주고, Swap애니메이션이 끝나면 isSwap을 false로 만들어 준다.

(isDodge, isJump와 같은 이유로 isSwap을 사용하였다.) 

 

 

아이템 습득부터, 아이템 장착, 변경까지 너무 한번에 와서 헷갈릴 수도 있다.

 

아이템 습득, 장착 정리

따라서 그림으로 아이템 습득, 장착에 대한 흐름을 정리 해 보았다.

 


Swap 애니메이션 설정

 

애니메이션 설정은 간단하다. (에셋이 있기 때문..)

 

Any State 아래에 애니메이션 추가

 

 

Any State 아래에 Swap 애니메이션을 넣어 주고, Trigger 조건을 DoSwap으로 만들어서 Any State → Swap 조건으로 넣어 준다.

 

이렇게 하면 애니메이션 설정도 끝났다.


구현 짤

 

움짤

이번 내용은 좀 길었던 것 같다.

 

이제 다음에는 무기를 이용한 공격을 구현 해 보도록 하겠다.