🎮 Game Dev (게임개발)/PC (데스크탑, 노트북, 터치패널)
[3D 액션게임] 10. 수류탄 구현하기
- -
🔔 유튜브 크리에이터 골든메탈님의 유니티강의 3D 쿼터뷰 액션게임 [BE5] 를 보고 공부하여 작성한 게시글입니다! 🔔
🧷 1. 오브젝트 만들기
- 던지는 수류탄 오브젝트 만들기
- Assets/QuarterView 3D Action BE5/Prefabs/Weapon Grenade.prefab 의 수류탄 꺼내옵니다.
- Assets/QuarterView 3D Action BE5/Particles/Grenade Explosion.prefab 을 부착시켜줍니다.
- Mesh Object에 TrailRenderer을 생성해 던질 때 이펙트를 자기의 입맛에 맞게 디자인 해줍시다.
- 수류탄에 Rigidbody, SphereCollider을 만들고, 새로운 스크립트인 "Grenade"를 넣어줍시다.
- 이후 나만의 프리팹으로 저장하면 됩니다.
- 던지는 수류탄 스크립트
public class Grenade : MonoBehaviour
{
public GameObject meshObj;
public GameObject effectObj;
public Rigidbody rigid;
}
- 우선은 Grenade 스크립트에 meshobject, effectobj, rigidbody를 담을 변수를 생성하였습니다.
- 던지는 수류탄에 맞게, 객체를 변수에 담아 저장해줍시다.
일단은 수류탄 오브젝트는 이렇게 만든 것으로 끝입니다. 다음은 플레이어가 수류탄을 투척하는 기능을 만들 것이에요.
🧷 2. 수류탄 투척 기능
- 수류탄 투척 키 설정
/*Player script, 추가되는 부분만 넣었습니다. */
public class Player : MonoBehaviour
{
bool gDown;
void GetInput()
{
gDown = Input.GetButtonDown("Fire2");
}
}
- 수류탄 투척 키는 Fire2, 마우스 오른쪽 키입니다. 왼쪽키보드 alt도 포함입니다. (default 설정)
- 수류탄 투척 기능
/*Player script, 추가되는 부분만 넣었습니다. */
public class Player : MonoBehaviour
{
public GameObject grenadeObj;
void Update()()
{
Grenade();
}
void Grenade()
{
if (hasGrenades == 0)
return;
if(gDown && !isReload && !isSwap) {
Ray ray = followCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit rayHit;
// out 키워드는, 반환값을 주어진 변수에 저장하는 키워드
if (Physics.Raycast(ray, out rayHit, 100))
{
Vector3 nextVec = rayHit.point;
nextVec.y = 15;
// 인스턴트 수류탄 생성
GameObject instantGrenade = Instantiate(grenadeObj, transform.position, transform.rotation);
Rigidbody rigidGrenade = instantGrenade.GetComponent<Rigidbody>();
rigidGrenade.AddForce(nextVec, ForceMode.Impulse);
rigidGrenade.AddTorque(Vector3.back * 10, ForceMode.Impulse);
hasGrenades--;
grenades[hasGrenades].SetActive(false);
}
}
}
}
- 우선 던질 수류탄을 받아올 GameObject를 저장 합니다.
- 이 후, Turn() 함수에서, Ray를 통해 마우스 클릭시 총을 쏜것 처럼 수류탄도 Ray를 가져와 마우스 클릭하는 Vector3를 받아옵니다
- 인스턴트 수류탄을 생성한 후, 레이를 쏜 곳의 벡터로 물리힘을 줍니다.
- 또한 수류탄이 회전하면서 날라가게 AddTorque를 통해 회전력도 주어습니다.
- 이후, 가지고 있는 수류탄의 갯수와, 장착된 수류탄은 비활성화됩니다.
🧷 3. 수류탄 폭파 기능
- 수류탄 터질 때 이펙트 활성화
/*Grenade script, 추가되는 부분만 작성하였습니다.*/
public class Grenade : MonoBehaviour
{
void Start()
{
StartCoroutine(Explosion());
}
IEnumerator Explosion()
{
yield return new WaitForSeconds(3f);
// 속도
rigid.velocity = Vector3.zero;
// 회전 속도
rigid.angularVelocity = Vector3.zero;
meshObj.SetActive(false);
effectObj.SetActive(true);
}
- 코루틴을 사용하여, 3초후에 터지도록 유도합시다.
- 터질 때, 속도와 회전 속도는 0으로 만듭니다.
- 수류탄의 mesh는 없애고, 터지는 effect는 활성화 시킵니다.(이펙트는 처음에 비활성화 시켜놓아야합니다.)
- 수류탄 터질 때, 피격 적 범위 파악
/*Grenade script, 추가되는 부분만 작성하였습니다.*/
public class Grenade : MonoBehaviour
{
IEnumerator Explosion()
{
// 피격범위 레이캐스트
// SphereCastAll: 구체모양의 레이캐스팅 (모든 오브젝트)
RaycastHit[] rayHits =
Physics.SphereCastAll(transform.position,
15, Vector3.up, 0f,
LayerMask.GetMask("Enemy"));
foreach(RaycastHit hitObj in rayHits) {
hitObj.transform.GetComponent<Enemy>().HitByGrenade(transform.position);
}
Destroy(gameObject, 5);
}
}
- SphereCaseAll 이라는 레이캐스트를 통하여, 수류탄을 받는 모든 Enemy의 정보를 rayHits로 담아옵시다.
- 이후 Enemy에서 구현될 HitByGrenade()함수를 실행시켜줍시다. (매개변수로 수류탄의 포지션이 들어갑니다.)
- 이후 수류탄은 지워줍시다. (이펙트가 3초후에 터지니, 그 이후인 5초로 설정 하였습니다.)
- 피격 및 넉백 기능
/*Enemy script, 추가되는 부분만 작성하였습니다.*/
public class Enemy : MonoBehaviour
{
public void HitByGrenade(Vector3 explosionPos)
{
curHealth -= 100;
Vector3 reactVec = transform.position - explosionPos;
StartCoroutine(OnDamage(reactVec, true));
}
IEnumerator OnDamage(Vector3 reactVec, bool isGrenade)
{
if(curHealth > 0) {
mat.color = Color.white;
}
else {
mat.color = Color.gray;
gameObject.layer = 12;
// 죽었을 시, 넉백
if (isGrenade)
{
reactVec = reactVec.normalized;
reactVec += Vector3.up * 3;
rigid.freezeRotation = false; // freezeRotation
rigid.AddForce(reactVec * 5, ForceMode.Impulse);
rigid.AddTorque(reactVec * 15, ForceMode.Impulse);
}
else
{
reactVec = reactVec.normalized;
reactVec += Vector3.up;
rigid.AddForce(reactVec * 5, ForceMode.Impulse);
}
Destroy(gameObject, 4);
}
}
}
- HitByGrenade()를 만들어 피격 시 100데미지를 줍시다. 이후 넉백을 주기위한 reactVec에 값을 넣어줍니다.
- OnDamage()함수에서, bool값의 isGrenade변수를 매개변수로 받아들여, 수류탄으로 죽은지 판단합니다. 수류탄으로 죽었을시 넉백에선 더 큰 값을 넣어주었습니다.
- 이 때, 적에게 freezeRation을 주었기에, 죽을 땐 해제해줍시다.
++ 버그로 주의할 점은, 필드의 아이템 수류탄의 value값, 던지는 수류탄의 Grenade script값의 오브젝트 저장 등이 잘 되어있어야지 잘 작동합니다. 저는 한동안 고생했습니다 ㅠㅠ ++
이번 시간엔 수류탄의 던지는 기능을 배워봤는데요.
이제야 게임을 만드는 순서를 어렴풋이 알 것 같았습니다. 그리고 게임을 만들 시
총을 쏜다던지, 수류탄을 던지는 것, 무기를 휘두르는 행위의 조건들은 모두 플레이어가 맡고
총에서는 총알을 나가는 행동, 망치는 휘두르는 행동, 수류탄이 터지는 행위 같은것은 각각
총, 망치, 수류탄이 맡는 것으로 보아 정말 게임도 우리 현실에서 사용하는 것과 같이 스크립트를 만들어 간다는
것을 알게 되었습니다.
++ 이 강좌에서 추가적으로 넣고 싶은 기능은 수류탄 터질 때, 범위거리에 따른 수류탄의 데미지를 다르게 주고싶다는 점이였습니다.
출처: 골든메탈님 유튜브
https://www.youtube.com/watch?v=FyJYWRIq0Ss&list=PLO-mt5Iu5TeYkrBzWKuTCl6IUm_bA6BKy&index=10
'🎮 Game Dev (게임개발) > PC (데스크탑, 노트북, 터치패널)' 카테고리의 다른 글
[3D 액션게임] 12. 다양한 몬스터 만들기 (0) | 2022.04.07 |
---|---|
[3D 액션게임] 11. 목표를 추적하는 AI 만들기 (0) | 2022.04.07 |
[3D 액션게임] 09. 피격 테스터 만들기 (0) | 2022.04.05 |
[3D 액션게임] 08. 플레이어 물리엔진 고치기 (0) | 2022.04.04 |
[3D 액션게임] 07-1. 원거리 무기 재장전시 모션캔슬 (0) | 2022.04.04 |
Contents
소중한 공감 감사합니다