기록 보관소

[Unity/유니티] 기초-3D 쿼터뷰 액션 게임: 피격 테스터 만들기[B46] 본문

유니티 프로젝트/3D 쿼터뷰 액션게임

[Unity/유니티] 기초-3D 쿼터뷰 액션 게임: 피격 테스터 만들기[B46]

JongHoon 2022. 3. 30. 20:06

개요

유니티 입문과 독학을 위해서 아래 링크의 골드메탈님의 영상들을 보며 진행 상황 사진 또는 캡처를 올리고 배웠던 점을 요약해서 적는다.

현재는 영상들을 보고 따라하고 배우는 것에 집중할 것이며, 영상을 모두 보고 따라한 후에는 개인 프로젝트를 설계하고 직접 만드는 것이 목표다.

https://youtube.com/playlist?list=PLO-mt5Iu5TeYI4dbYwWP8JqZMC9iuUIW2 

 

유니티 강좌 기초 채널 Basic

유니티 개발을 처음 시작하시는 입문자 분들을 위한 기초 채널. [ 프로젝트 ] B00 ~ B12 (BE1) : 유니티 필수 기초 B13 ~ B19 (BE2) : 2D 플랫포머 B20 ~ B26 (BE3) : 2D 탑다운 대화형 RPG B27 ~ B37 (BE4) : 2D 종스크롤

www.youtube.com


3D 쿼터뷰 액션 게임: 피격 테스터 만들기[B46]

1. 오브젝트 생성

피격 테스터로 사용할 Cube 생성
Enemy 스크립트 파일 생성
스크립트 파일 넣어주기


2. 충돌 이벤트

총알 프리펩들의 태그를 Bullet으로 설정
그리고 Is Trigger 체크를 해준다

//Bullet 스크립트 파일

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

public class Bullet : MonoBehaviour {
	public int damage;

	void OnCollisionEnter(Collision collision) {
		if (collision.gameObject.tag == "Floor")    //탄피
			Destroy(gameObject, 3); //3초 뒤에 사라지기
	}

	void OnTriggerEnter(Collider other) {	//총알을 isTrigger로 바꾸었으므로
		if(other.gameObject.tag == "Wall")   //총알
			Destroy(gameObject);
	}
}
//Enemy 스크립트 파일

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

public class Enemy : MonoBehaviour {
	public int maxHealth;
	public int curHealth;

	Rigidbody rigid;
	BoxCollider boxCollider;

	void Awake() {
		rigid = GetComponent<Rigidbody>();
		boxCollider = GetComponent<BoxCollider>();
	}

	void OnTriggerEnter(Collider other) {
		if (other.tag == "Melee") {
			Weapon weapon = other.GetComponent<Weapon>();
			curHealth -= weapon.damage;

			Debug.Log("Range : " + curHealth);
		}
		else if (other.tag == "Bullet") {
			Bullet bullet = other.GetComponent<Bullet>();
			curHealth -= bullet.damage;

			Debug.Log("Range : " + curHealth);
		}
	}
}

Test Enemy 설정
아이템을 배치해두고
망치로 큐브를 때리니 큐브의 체력이 콘솔창에 출력되었다
총으로 쏜 것도 정상적으로 출력되었다.

  • 추가적으로, Weapon 스크립트 파일에서 근접 무기를 처리하는 코루틴 함수가 0.3초동안만 콜라이더를 활성화 시켜서 정상적으로 처리되지 않았다. 그래서 콜라이더와 이펙트를 0.4초로 살짝 늘려주었더니 위 캡처처럼 처리되었다.

3. 피격 로직

Enemy 관련 레이어 2개 추가
Physics 설정. 죽은 적만 수정해주었다.
Test Enemy를 Enemy 레이어로 설정

//Enemy 스크립트 파일

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

public class Enemy : MonoBehaviour {
	public int maxHealth;
	public int curHealth;

	Rigidbody rigid;
	BoxCollider boxCollider;
	Material mat;

	void Awake() {
		rigid = GetComponent<Rigidbody>();
		boxCollider = GetComponent<BoxCollider>();
		mat = GetComponent<MeshRenderer>().material;
	}

	void OnTriggerEnter(Collider other) {
		if (other.tag == "Melee") {
			Weapon weapon = other.GetComponent<Weapon>();
			curHealth -= weapon.damage;
            
			StartCoroutine(OnDamage());
		}
		else if (other.tag == "Bullet") {
			Bullet bullet = other.GetComponent<Bullet>();
			curHealth -= bullet.damage;
            
			StartCoroutine(OnDamage());
		}
	}

	IEnumerator OnDamage() {
		mat.color = Color.red;
		yield return new WaitForSeconds(0.1f);

		if (curHealth > 0) {
			mat.color = Color.white;
		}
		else {
			mat.color = Color.gray;
			gameObject.layer = 12;	//Enemy Dead 레이어로 변경
			Destroy(gameObject, 4);
		}
	}
}
  • Material은 GetComponent<Material>로 할 수 없고, Mesh Renderer 컴포넌트를 통해서 접근이 가능하다. 그래서 GetComponent<MeshRenderer>().material;로 선언해야한다.

피격 당하니 빨갛게 변했다
체력이 모두 닳으니 죽어서 회색으로 변했다
Layer가 변경된 모습. 때려도 반응이 없다
4초 뒤 사라졌다


4. 넉백 추가

//Enemy 스크립트 파일

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

public class Enemy : MonoBehaviour {
	public int maxHealth;
	public int curHealth;

	Rigidbody rigid;
	BoxCollider boxCollider;
	Material mat;

	void Awake() {
		rigid = GetComponent<Rigidbody>();
		boxCollider = GetComponent<BoxCollider>();
		mat = GetComponent<MeshRenderer>().material;
	}

	void OnTriggerEnter(Collider other) {
		if (other.tag == "Melee") {
			Weapon weapon = other.GetComponent<Weapon>();
			curHealth -= weapon.damage;
			Vector3 reactVec = transform.position - other.transform.position;

			StartCoroutine(OnDamage(reactVec));
		}
		else if (other.tag == "Bullet") {
			Bullet bullet = other.GetComponent<Bullet>();
			curHealth -= bullet.damage;
			Vector3 reactVec = transform.position - other.transform.position;
			Destroy(other.gameObject);

			StartCoroutine(OnDamage(reactVec));
		}
	}

	IEnumerator OnDamage(Vector3 reactVec) {
		mat.color = Color.red;
		yield return new WaitForSeconds(0.1f);

		if (curHealth > 0) {
			mat.color = Color.white;
		}
		else {
			mat.color = Color.gray;
			gameObject.layer = 12;  //Enemy Dead 레이어로 변경

			reactVec = reactVec.normalized;
			reactVec += Vector3.up;
			rigid.AddForce(reactVec * 5, ForceMode.Impulse);

			Destroy(gameObject, 4);
		}
	}
}

총알 맞기 직전
맞은 후 총알이 사라졌다
계속 때리다가 죽으니 살짝 튀어오르면서 뒤로 빠졌다