[Unity Course 2] 05. 총 발사 로직 2
위키북스 출판사 이재현 저자님의 '절대강좌! 유니티' 책을 참고하여 필기한 내용입니다.
충돌 이벤트
Collider 컴포넌트를 포함한 오브젝트 간의 충돌이 발생하면 OnCollision~ , OnTrigger~ 함수 발생
콜백함수라고도 함, 콜백은 충돌감지시스템(back) 에서 호출(Call)한다는 것을 의미
| 함수명 | 호출 조건 | Is Trigger 옵션 |
| void OnCollisionEnter | 두 물체 간의 충돌이 일어나기 시작했을 때 | 언체크 |
| void OnCollisionStay | 두 물체 간의 충돌이 지속할 때 | 언체크 |
| void OnCollisionExit | 두 물체가 서로 떨어졌을 때 | 언체크 |
| void OnTriggerEnter | 두 물체 간의 충돌이 일어나기 시작했을 때 | 체크 |
| void OnTriggerStay | 두 물체 간의 충돌이 지속할 때 | 체크 |
| void OnTriggerExit | 두 물체가 서로 떨어졌을 때 | 체크 |
Collider 컴포넌트의 Is Trigger속성을 체크하면 충돌 감지는 되지만 물리적인 충돌은 일어나지 않음
**Is Trigger가 체크 된 Collider는 주로 감지 센서 역할에 자주 사용됨 (자동문, 스테이지 넘어가기)
Tag 활용
총알이 벽에 충돌했을 때, 벽의 관점에서 충돌된 오브젝트를 이름으로 확인할 수 있지만 Tag가 더 적절한 방법이다.
Bullet 오브젝트의 태그를 BULLET 이름으로 생성한다.


** Tag는 문자열로 비교하므로 대소문자를 정확히 지켜야함, 스크립트 작성시 대소문자 오류를 줄이기위해 대문자만 사용하는것도 방법(Sorting Layer, Layer도 적용됨)
새로운 RemoveBullet 스크립트를 생성하고 아래와 같이 작성한다.
using UnityEngine;
public class RemoveBullet : MonoBehaviour
{
// 추올이 시작할 때 발생하는 이벤트
private void OnCollisionEnter(Collision col)
{
// 충돌한 게임오브젝트의 태그값 비교
if(col.collider.tag == "BULLET")
{
// 충돌한 게임오브젝트 삭제
Destroy(col.gameObject);
}
}
}

OnCollisionEnter 콜백 함수
: Collision타입의 인자를 넘겨줌, Collision은 클래스이며 충돌한 게임오브젝트의 정보, 충돌 위치 및 충돌 속도 등 다양한 정보가 담김
Collision 클래스의 속성
| 속성 | 설명 |
| collider | 충돌한 게임오브젝트의 Collider 컴포넌트(읽기 전용) |
| contacts | 물체 간의 충돌 지점으로 물리 엔진에 의해 생성 |
| gameObject | 충돌한 게임오브젝트 |
| impulse | 충돌 시 발생한 충격량 |
| relative Velocity | 충돌한 두 객체의 상대적인 선 속도(읽기 전용) |
| rigidbody | 충돌한 게임오브젝트의 Rigdbody 컴포넌트(읽기 전용) |
| transform | 충돌한 게임오브젝트의 Transform 컴포넌트(읽기 전용) |
**coll.collider.tag = coll.gameObject.tag 둘다 결과값은 같다.
Destory 매서드는 두가지 방법으로 사용할 수 있는데
1. static void Destory(Object obj);
2. static void Destory(Object obj, float t);
두번째의 경우 몇초 후 삭제될건지를 지정하는 인자이다.
CompareTag 함수
coll.collider.tag, coll.gameObject.tag와 같이
문자의 속성을 가져오는 코드는 실행 시 해당 문자열의 복사본을 생성한다. 이 복사본은 특정 메모리에 할당되어 가비지 컬렉션의 대상이 된다.
가비지 컬렉션 : 메모리에 자동으로 할당된 저장공간을 일정 시간이 지난 후 더는 사용하지 않을때 자동으로 메모리를 해제하는 동작
이러한 동작은 잠재적인 렉을 유발하니 지금 사용하는 함수가 필요하다.
using UnityEngine;
public class RemoveBullet : MonoBehaviour
{
// 추올이 시작할 때 발생하는 이벤트
private void OnCollisionEnter(Collision col)
{
// 충돌한 게임오브젝트의 태그값 비교
if (col.collider.CompareTag("BULLET"))
{
// 충돌한 게임오브젝트 삭제
Destroy(col.gameObject);
}
}
}
CompareTag는 비교할 태그명을 tag인자로 넘겨주면 해당 게임오브젝트의 태그와 비교해 같으면 true값을 반환한다.
Bullet 오브젝트는 Prefab으로 만들어준다.
총알 발사 로직
총 모델의 하위에 빈 게임오브젝트를 생성하고 이름을 FirePos 라고 변경한다.

런 모드에서 수정한 속성
실행하기 전과 실행후의 플레이어의 동작이 다르므로 Run 모드에서 위치를 찾기

찾고나서 컴포넌트를 복사하기
에디터 모드로 돌아온 후

붙여넣기
기즈모의 활용
게임오브젝트들은 마우스로 클릭하거나 영역을 드래그해야 위치를 확인할 수 있는데
씬뷰에서만 보이게끔 코드로 작성할 수 있다.
using UnityEngine;
public class MyGizmos : MonoBehaviour
{
public Color _color = Color.yellow;
public float _radius = 0.1f;
private void OnDrawGizmos()
{
// 기즈모 색상 설정
Gizmos.color = _color;
// 구체 모양의 기즈모 생성, 인자는 (생성 위치, 반지름)
Gizmos.DrawSphere(transform.position, _radius);
}
}
새로운 스크립트인 MyGizmos를 생성하고 이를 FirePos 오브젝트에 드래그 앤 드롭한다.
또한 인스펙터창에서도 추가할 수 있다. 멀리있어도 위치가 어디 있는지 알 수 있으니 아주 유용한 기능이다.

using UnityEngine;
public class FireCtrl : MonoBehaviour
{
// 총알 프리팹
public GameObject bullet;
// 총알 발사 좌표
public Transform firePos;
private void Update()
{
// 마우스 왼쪽 버튼을 클릭했을 때 Fire함수 호출
if (Input.GetMouseButtonDown(0)){
Fire();
}
}
void Fire()
{
// Bullet 프리팹을 동적으로 생성(생성할 객체, 위치, 회전)
Instantiate(bullet, firePos.position, firePos.rotation);
}
}
새로운 FireCtrl 스크립트 생성 후 위와 같이 작성
이 스크립트는 Player 오브젝트에 드래그 앤 드롭

bullet은 프리팹으로 저장한 파일을 연결, FirePos는 하이어라키 뷰에서 연결
| GetMouseButton (int button) | 마우스 버튼을 클릭하고 있을 때 계속 발생 |
| GetMouseButtonDown (int button) | 마우스 버튼을 클릭했을 때 한 번 발생 |
| GetMouseButtonUp (int button) | 마우스 버튼을 놓았을 때 한 번 발생 |
0 : 왼쪽 버튼 , 1 : 오른쪽 버튼, 2 : 가운데 버튼
Instantiate 함수 : 게임오브젝트나 프리팹의 복사본을 만드는 함수로써 인자는 생성할 개체, 생성위치, 각도이다