GURU_unity_3주차 FPS 게임 제작(2)

2023. 7. 10. 23:03SWU_프로젝트/GURU - unity

이번 시간에 학습할 내용은 아래와 같다.

1. 무기제작

 

1. 무기제작

→ 목표
마우스의 오른쪽 버튼을 누르면 시선이 바라보는 방향으로 수류탄을 던지고 싶다. 
→ 순서
1.플레이어를 제외하고 물체에 닿으면 폭발하는 수류탄 오브젝트 만들기
2. 사용자의 마우스 오른쪽 버튼 입력받기
3. 발사 위치에 수류탄 생성하기
4. 생성된 수류탄에 시선(카메라) 방향으로 물리적인 힘 가하기

 

수류탄 오브젝트 생성

  • 수류탄 오브젝트를 만들기 위해 sphere 오브젝트를 생성한다.
  • 오브젝트의 이름은 Bomb로 설정한다.
  • 물리 효과를 시뮬레이션하기 위해 리지드바디 컴포넌트를 추가한다.

수류탄 기능 구현

  • 수류탄 기능을 구현할 스크립트를 생성하고 수류탄 오브젝트에 드래그해서 넣어준다.
  • 스크립트의 이름은 BombAction.cs로 설정한다.

아래와 같이 충돌 시에 호출되는 이벤트 함수인 OnCollisionEnter( ) 함수를 이용하여 충돌 처리 기능 구현한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BombAction : MonoBehaviour
{
// 충돌했을 때의 처리
private void OnCollisionEnter(Collision collision)
{
// 자기 자신을 제거한다.
Destroy(gameObject);
}
}

 

수류탄의 폭발 효과

 

유니티 Aset 스토어에서 FX Explosion Pack 에셋을 추가한다.

Unity에서 열기를 해준다.

위와 같이 download 및 import해주고, 임포트한 FX Explosion Pack 에셋에서 불필요한 Script 폴더를 삭제(선택 해)한다.

  • Explosion1 프리팹을 씬 뷰에 드래그해서 넣어준다.
  • 그림과 같이 아까 삭제한 Script폴더로 인한 오류를 해결하기 위해 빨간박스표시되어있는 더보기에서 Remove Component해준다.

  • 본체에 있는 손실된 스크립트와 자식 오브젝트인 PointLight 오브젝트에 있는 손실 스크립트를 삭제한다.
  • Explosion1 프리팹 하위 오브젝트인 Explosion -[Explosion6] 이라고 되어있는 게임 오브젝트를 선택한다.
  • 인스펙터 뷰의 파티클 시스템 컴포넌트에서 폭발 효과를 빠르게 재생하도록 Simulation Speed 항목을 2배로 변경해준다.

 

  • 하위 오브젝트 Decal 제거한다.

DestroyEffect라는 스크립트를 생성하고 Exploson1에 드래그해서 넣어준  아래와 같이 코드를 작성해보자.

public class DestroyEffect : MonoBehaviour
{
// 제거될 시간 변수
public float destroyTime = 1.5f;
// 경과 시간 측정용 변수
float currentTime = 0;
void Update()
{
// 만일 경과 시간이 제거될 시간을 초과하면 자기 자신을 제거한다.
if(currentTime > destroyTime)
{
Destroy(gameObject);
}
// 경과 시간을 누적한다.
currentTime += Time.deltaTime;
}
}

이펙트 생성 후에 지정된 시간이 경과하면 씬에서 제거되도록 스크립트를 작성하였다.

Assets에 폴더를 생성하고 Prefabs으로 폴더명을 수정한다.

만들어진 Prefabs폴더에 Exploson1을 드래그해서 넣고 프리팹을 생성한다.

나는 original prefab을 선택해주었다.
그리고 하이어라키 창에있는 Exploson1은 삭제해준다.

  • 스크립트 추가가 완료된 Explosion1 프리팹의 이름을 FX_Bomb로 변경한다.

이펙트 프리팹을 생성해보자.

public class BombAction : MonoBehaviour
{
// 폭발 이펙트 프리팹 변수
public GameObject bombEffect;
// 충돌했을 때의 처리
private void OnCollisionEnter(Collision collision)
{
// 이펙트 프리팹을 생성한다.
GameObject eff = Instantiate(bombEffect);
// 이펙트 프리팹의 위치는 수류탄 오브젝트 자신의 위치와 동일하다.
eff.transform.position = transform.position;
// 자기 자신을 제거한다.
Destroy(gameObject);
}
}

이제 다시 유니티 에디터로 돌아와 수류탄 오브젝트에 비어 있는 bombEffect 변수에 앞에서 만들었던 이펙트 프리팹(FX_Bomb)을 추가해준다.

 

 

이제 플레이어와 수류탄이 충돌하지 않도록 플레이어 캐릭터와 수류탄 오브젝트에 각각 Layer를 설정해줄 것이.

각각 이름에 맞게 레이어를 변경해준다.

Edit 메뉴에서 Project Settings를 들어가서 플레이어와 수류탄 사이의 충돌 체크를 해제시킨다.

아래 영상을 통해 가 적용한 효과들이 잘 나타나는 것을 확인할 수 있다.

무기 발사하기(투척)

  • Bomb 오브젝트를 프로젝트 뷰로 드래그해서 새로운 프리팹으로 생성한다.
  • 새 프리팹 생성이 완료됐으면 씬에 생성돼 있는 프리팹은 [Delete] 키를 눌러 삭제한다.

  • 수류탄 발사 위치 지정한다.
  • 빈 오브젝트(Create Empty) 생성 후, Player의 하위오브젝트로 지정해준다.
  • 이름을 firePosition으로 변경 후 Transform을 그림과 같이 지정한다.

project창에서 c#스크립트 PlayerFire을 생성하고 Player에다가 드래그해서 넣어준다.

 

이제 코드를 작성해보자.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerFire : MonoBehaviour
{
// 발사 위치
public GameObject firePosition;
// 투척 무기 오브젝트
public GameObject bombFactory;
void Update()
{
// 마우스 오른쪽 버튼을 누르면 시선이 바라보는 방향으로 수류탄을 던지고 싶다.
}
}

사용자의 마우스 우측 버튼 입력에 따라 수류탄을 발사하도록 PlayerFire.cs 스크립트 생성하고 ,특정 위치에서 발사될 수 있도록 발사 위치 변수 선언한다.

 

유니티의 마우스 입력 맵핑

무기 발사하기(수류탄)

  • 마우스 오른쪽 버튼의 입력이 감지되면 수류탄 프리팹을 생성햔다.
  • 프리팹의 위치는 발사 위치와 동일하도록 조정한다.
. . . (생략) . . .
void Update()
{
// 마우스 오른쪽 버튼을 누르면 시선이 바라보는 방향으로 수류탄을 던지고 싶다.
// 마우스 오른쪽 버튼을 입력받는다.
if (Input.GetMouseButtonDown(1))
{
// 수류탄 오브젝트를 생성한 후 수류탄의 생성 위치를 발사 위치로 한다.
GameObject bomb = Instantiate(bombFactory);
bomb.transform.position = firePosition.transform.position;
}
}
public class PlayerFire : MonoBehaviour
{
. . . (생략) . . .
// 투척 파워
public float throwPower = 15f;
void Update()
{
// 마우스 오른쪽 버튼을 입력받는다.
if (Input.GetMouseButtonDown(1))
{
. . . (생략) . . .
// 수류탄 오브젝트의 Rigidbody 컴포넌트를 가져온다.
Rigidbody rb = bomb.GetComponent<Rigidbody>();
// 카메라의 정면 방향으로 수류탄에 물리적인 힘을 가한다.
rb.AddForce(Camera.main.transform.forward * throwPower, ForceMode.Impulse);
}
}
}

내가 작성한 코드 전체를 캡쳐해봤다.

 

  • PlayerFire의 파라미터를 지정함 
  • Fire Position : firePosition 지정
  • Bomb Factory : Bomb 프리팹 지정

투척하는 영상을 올리려고 했는데 오류가 났다. 다시 수정해서 추후에 올리겠다.

 

 

무기 발사하기(총)

→ 목표
마우스의 왼쪽 버튼을 누르면 시선이 바라보는 방향으로 총을 발사하고 싶다.
→ 순서
1. 사용자의 마우스 왼쪽 버튼 입력받기
2. 레이를 생성하고 발사될 위치와 진행 방향 설정하기
3. 레이가 부딪힌 대상의 정보를 저장할 변수 생성하기
4. 레이를 발사하고, 만일 부딪힌 물체가 있으면 피격 이펙트 표시하기
void Update()
{
. . . (생략) . . .
// 마우스 왼쪽 버튼을 누르면 시선이 바라보는 방향으로 총을 발사하고 싶다.
// 마우스 왼쪽 버튼을 입력받는다.
if (Input.GetMouseButtonDown(0))
{
// 레이를 생성한 후 발사될 위치와 진행 방향을 설정한다.
Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
// 레이가 부딪힌 대상의 정보를 저장할 변수를 생성한다.
RaycastHit hitInfo = new RaycastHit();
}
}
  • 마우스 왼쪽 버튼의 입력이 감지되면 소총 발사를 위한 레이를 생성한다.
  • 레이를 생성하면서 발사 위치와 레이 발사 방향을 설정한다.
  • 레이에 충돌한 대상의 정보를 저장할 구조체 변수(RaycastHit)도 생성한다.

RaycastHit 구조체 변수 멤버 변수에 대해 알아보자.

public class PlayerFire : MonoBehaviour
{
. . . (생략) . . .
// 피격 이펙트 오브젝트
public GameObject bulletEffect;
// 피격 이펙트 파티클 시스템
ParticleSystem ps;
void Start()
{
// 피격 이펙트 오브젝트에서 파티클 시스템 컴포넌트 가져오기
ps = bulletEffect.GetComponent<ParticleSystem>();
}
. . . (생략) . . .
}

발사 위치에 이펙트를 표시하기 위해 플레이어 생성 시에 파티클 시스템 컴포넌트를 미리 캐싱한다.

void Update()
{
. . . (생략) . . .
// 마우스 왼쪽 버튼을 입력받는다.
if (Input.GetMouseButtonDown(0))
{
. . . (생략) . . .
// 레이를 발사한 후 만일 부딪힌 물체가 있으면 피격 이펙트를 표시한다.
if(Physics.Raycast(ray, out hitInfo))
{
// 피격 이펙트의 위치를 레이가 부딪힌 지점으로 이동시킨다.
bulletEffect.transform.position = hitInfo.point;
// 피격 이펙트를 플레이한다.
ps.Play();
}
}
}

레이를 발사하여 부딪힌 대상의 표면에 피격 이펙트를 표시한다.

 

총 피격 이펙트 설정

 

  • 깃허브(GitHub)에서 ‘Effect.unitypackage’를 다운로드한다.
  • 유니티 에디터 상단의 [Assets] – [Import Package] – [Custom Package]를 선택한 후 다운로드한 파일을 선택한다.Workshop 폴더 하위의 Effects 폴더에 있는 Stone_BulletImpack.prefab 파일을 선택해 하이어라키 뷰로 드래그힌다.
  • 최초에 이펙트가 플레이어의 시야에 보일 수 없도록 그림과 같이 y축 위치 값을 ‘1,000’으로 변경한다.
  • Player 오브젝트의 PlayerFire 컴포넌트에 있는 bulletEffect 변수에 드래그해서 넣어준다.

화면에 조준선 UI 표시

 

깃허브에서 Crosshair.png 파일을 다운로드한 후 프로젝트 뷰의 Materials 폴더에 드래그해서 넣어준다.

인스펙터 뷰에서 Texture Type을 Sprite(2D and UI)로 선택하고 [Apply] 버튼을 선택한다.

 

  • 하이어라키 뷰에서 [+] 버튼 – [UI] – [Image]를 선택해 이미지 오브젝트를 생성한다.
  • Crosshair 스프라이트를 UI Image의 Source Image에 드래그해서 넣어주고, 너비와 높이를 각각 ‘30’으로 조정한다.

총 피격 이펙트의 방향 조정

 

피격 이펙트가 피격 위치에 수직으로 발생되도록 이펙트의 forward 방향을 레이가 충돌한 지점의 법선 방향과 일치시킨다.

void Update()
{
. . . (생략) . . .
// 마우스 왼쪽 버튼을 입력받는다.
if (Input.GetMouseButtonDown(0))
{
. . . (생략) . . .
if(Physics.Raycast(ray, out hitInfo))
{
. . . (생략) . . .
// 피격 이펙트의 forward 방향을 레이가 부딪힌 지점의 법선 벡터와 일치시킨다.
bulletEffect.transform.forward = hitInfo.normal;
// 피격 이펙트를 플레이한다.
ps.Play();
}
}
}