[Unity Course 2] 05. 총 발사 로직 3
위키북스 출판사 이재현 저자님의 '절대강좌! 유니티' 책을 참고하여 필기한 내용입니다.
총알 발사 궤적 효과 만들기 - Trail Renderer
Trail Renderer

bullet 에 Trail renderer 생성하기

Trail.png 파일은 04.Image에 드래그해서 옮기고, BulletTrail이라는 이름으로 머티리얼을 새로 생성한다.


방금 만든 머티리얼을 Bullet의 Trail Renderer에 연결한다.
BulletTrail 의 Shader 는 Mobile/Particles/Additive 로 변경하고 아까 옮겼던 Trail이미지를 연결한다.
Trail Renderer 컴포넌트의 Time 속성은 동적으로 생성된 메시의 지속시간, 값이 크면 긴 궤적이 되고 값이 작을 수 록 궤적의 길이가 짧아진다. 이 값은 0.7로 설정하고 노드의 넓이를 아래와 같이 적절히 조절한다



Min Vertex Distance 속성은 생성하는 버텍스 가느이 최솟값을 설정하는 것으로 값이 작을 수록 조밀한 폴리곤을 생성
**물체가 직선으로만 이동하면 값을 크게해서 폴리곤 개수를 줄이고, 곡선으로 이동한다면 값을 작게하여 부드러운 궤적을 표현해야한다.
Trail Renderer 컴포넌트의 Color 속성에서 Blend 모드로 아래와 같이 Color 값과 Alpha 값을 수정한다.


프리팹의 변경 내용 조회 및 저장

지금까지 변경한 하이어라키에 있는 Bullet 프리팹을 저장 할 수 있다. (변경된 내용과 함께 보여줌)
변경된 내용을 클릭하면 어떤 속성이 변경되었는지 자세히 확인할 수 있다.

지금까지 만든 총알은 많이 커서 bullet 프리팹에서 Scale사이즈를 0.3, 0.3, 0.3으로 바꾼다.
파티클 활용하기
벽에 총알이 충돌했을 때 불꽃이 튀는 효과 구현하기

에셋 임포트 하기

받은 폴더는 Prefabs에 이동하기

SparksEffect 하이어라키 뷰에 드롭
RemoveBullet 스크립트를 아래와 같이 변경
using UnityEngine;
public class RemoveBullet : MonoBehaviour
{
// 스파크 파티클 프리팹을 연결할 함수
public GameObject sparkEffeck;
// 충돌이 시작할 때 발생하는 이벤트
private void OnCollisionEnter(Collision coll)
{
// 충돌한 게임오브젝트의 태그값 비교
if (coll.collider.CompareTag("BULLET")){
// 스파크 파티클을 동적으로 생서
Instantiate(sparkEffeck, coll.transform.position, Quaternion.identity);
// 충돌한 게임오브젝트 삭제
Destroy(coll.gameObject);
}
}
}
Quaternion.identity 로 설정하여 회전 없이 생성하였다.
***유니티에서 사용하는 각도의 단위는 Quaternion이다.

충돌 지점과 법선 벡터
Bullet 과 Wall 의 정확한 충돌 지점과 해당 접점에서의 법선 벡터를 구해 스파크 파티클을 회전
RemoveBullet 스크립트 수정
using UnityEngine;
public class RemoveBullet : MonoBehaviour
{
// 스파크 파티클 프리팹을 연결할 함수
public GameObject sparkEffeck;
// 충돌이 시작할 때 발생하는 이벤트
private void OnCollisionEnter(Collision coll)
{
// 충돌한 게임오브젝트의 태그값 비교
if (coll.collider.CompareTag("BULLET")){
// 첫번째 충돌 지점의 정보 추출
ContactPoint cp = coll.GetContact(0);
//충돌한 총알의 법선 벡터를 쿼터니언 타입으로 변환
Quaternion rot = Quaternion.LookRotation(-cp.normal);
// 스파크 파티클을 동적으로 생성
Instantiate(sparkEffeck, cp.point, rot);
// 충돌한 게임오브젝트 삭제
Destroy(coll.gameObject);
}
}
}
충돌 지점의 정보는 아래의 함수를 통해 알 수 있다.
public ContactPoint GetContact(int index)
pubic int GetContact(ContactPoint[] contacts)
**하나의 충돌 지점 정보만 필요하다면 GetContact, 모든 충돌 지점의 정보가 필요하다면 GetContacts 함수
// 첫번째 충돌 지점의 정보 추출
ContactPoint cp = coll.GetContact(0);
우리는 하나의 충돌 지점만 필요하기에 GetContactPoint함수 사용, 첫번째 충돌 지점을 의미하는 0 인덱스를 인자로 넘김
ContactPoint 구조체
| 속성 | 설명 |
| normal | 충돌 지점의 법선 |
| otherCollider | 충돌 지점의 다른 Collider |
| point | 충돌 지점의 위치 |
| separation | 충돌한 두 Collider 간의 거리 |
| thisCollider | 충돌 지점의 첫 번째 Collider |
쿼터니언(Quaternion)
: 유니티에서 사용되는 각도의 단위, 수학용어로는 복소수 4차원 벡터, 말그대로 각도 4개의 원소로 표현한 것으로 인스펙터 뷰를 Debug모드로 변경하고 Transform 컴포넌트를 보면 4개의 원소로 구성된 것을 확인가능

오일러를 내부적으로 Quaternion 타입으로 변형하여 사용
오일러는 3차원 공간의 절대 좌표를 기준으로 물체가 얼마나 회전했는지 측정하는 방식
오일러 각을 이용한 회전 방식은 X, Y, Z축 차례대로 회전되는데 2개의 축이 겹쳐지면 어느 축으로도 회전하지 않고 잠기는 짐벌락 현상이 발생
짐벌락 방지를 위해 유니티에서는 쿼터니언을 사용해 처리
Quaternion.LookRatation 함수의 반환 값은 Quaternion 타입이며 인자로 전달한 벡터의 방향을 Quaternion 타입으로 변환시키는 역할
ContactPoint.point 속성으로 충돌 지점의 접점의 좌표를 알아냄
**충돌 지점의 접점 정보는 Collision.contacts 속성으로도 알 수 있지만, contacts 속성은 가비지 컬렉션을 발생시키기 때문에 GetContact, GetContacts 함수 사용 권장


Looping 을 언체크
실행해보면 스파이크가 튀고 2초후 사라지지만 오브젝트는 남아있음을 확인할 수 있다. 코드를 통해 소멸로직 작성
using UnityEngine;
public class RemoveBullet : MonoBehaviour
{
// 스파크 파티클 프리팹을 연결할 함수
public GameObject sparkEffeck;
// 충돌이 시작할 때 발생하는 이벤트
private void OnCollisionEnter(Collision coll)
{
// 충돌한 게임오브젝트의 태그값 비교
if (coll.collider.CompareTag("BULLET")){
// 첫번째 충돌 지점의 정보 추출
ContactPoint cp = coll.GetContact(0);
//충돌한 총알의 법선 벡터를 쿼터니언 타입으로 변환
Quaternion rot = Quaternion.LookRotation(-cp.normal);
// 스파크 파티클을 동적으로 생성
GameObject spark = Instantiate(sparkEffeck, cp.point, rot);
// 일정 시간이 지난 후 스파크 파티클을 삭제
Destroy(spark, 0.5f);
// 충돌한 게임오브젝트 삭제
Destroy(coll.gameObject);
}
}
}
객체를 spark 변수에 저장후 Destory 함수를 사용하여 삭제