10. 적 캐릭터 제작(2)

MOON·2022년 7월 20일
0

유니티_3D_SpaceShooter

목록 보기
10/11
post-thumbnail

혈흔 효과

플레이어가 쏜 총알이 몬스터에 명중했을 때 몬스터가 피를 흘리는 혈흔 효과(Blood Effect) 구현

Resources 폴더 만들기 (복수형에 주의)
Resources 폴더에 있는 모든 애셋은 런 타임에서 직접 불러와 사용할 수 있는 특징이 있지만, 빌드 할 때 실행 파일에 모두 포함 -게임에서 사용하지 않은 리소스가 있으면 안됨

MonsterCtrl.cs
CreateBloodEffect() 함수 추가

private GameObject bloodEffect;

적어 혈흔 효과를 할당할 변수를 선언한다.

ShowBloodEffect()함수를 사용하여 혈흔효과를 나타내자.
OnCollisionEnter() 함수를 수정하여 충돌 관련 함수를 코드를 바꾸어보자.

GetContact(0)을 통해 첫 충돌지점을 가져온다.
(-) 기호를 붙여 총에 맞으면 피가 반대 방향으로 튀기게 할수있게 한다.
ShowBloodEffect(pos,rot)을 통해 함수를 실행한다.

이제 ShowBloodEffect() 함수 수정한다.

Instantiate를 통해 총에 맞으면 혈흔효과를 생성한다.
Destroy() 함수를 통해 1초후에 사라지게 한다.


데칼 - 바닥에 뿌려지는 혈흔 효과

몬스터가 총을 맞고 흘린 혈흔 자국을 데칼 기법을 활용하여 구현
데칼(Decal) : 물체의 표면에 어떤 그림이나 무늬를 그려넣는 방식

  • 흔히 총단 자국, 폭발 후 바닥의 그을림, 벽에 붙어 있는 포스터등에 사용

GameObject - 3D Object - Quad를 하나 생성

  • 이름 : BloodDecal / x 축 회전 : 90도

BloodEffect 폴더 안의 BloodDecal 이미지 파일을 04.Images로 옮김
새로운 머터리얼 생성 (BloodDecal)
BloodDecal 머터리얼 쉐이더를 Unit/Transparent로 변경
BloodDecal 텍스쳐를 연결
BloodDecal 머터리얼을 씬뷰의 Quad에 연결

이제 MonsterCtrl.cs를 수정해서 바닥에 혈흔 효과를 내보자.

새로운 게임오브젝트 blood2를 생성하여 크기를 랜덤하게 조정한다.

씬뷰의 BloodDecal를 프리펩으로 만든다.
MonsterCtrl.cs스크립트의 노출된 전역변수에 생성된 BloodDecal 프리펩을 연결




몬스터 공격능력 부여

몬스터 콤포넌트 추가

플레이어가 공격 데미지를 입어 생명력이 줄어드는 로직 구현
몬스터 양쪽 손에 Collider를 추가하여 몬스터가 공격 애니메이션을 수행 할 때 플레이어의 Collider와 충돌 시켜 데미지를 입히는 방식

씬 뷰의 Monster를 선택 한후 L_wrist / R_wrist를 동시에 선택 한 후 Sphere Collider와 Rigidbody 컴포넌트 두개를 동시에 추가한다.

  • 2개를 동시에 선택한 후 추가하면 똑같이 동시에 컴포넌트가 추가됨

2개를 동시 지정한 한 PUNCH 태그를 만든 후에 태그 지정
2개를 동시 지정한 후 Is Kinematic / Is Trigger 속성을 다음과 같이 지정

Is Kinematic 속성에 체크를 하면 물리 시뮬레이션을 하지 않게 설정하는 것임
운동역학(Kinematic)이란 물리 엔진의 시뮬레이션 연산으로 이동 및 회전하는 것이 아니라 스크립트 혹은 애니메이션에 의해 Transform 컴포넌트의 속성 값을 변화시켜 이동 및 회전을 말하는 것임
몬스터가 공격 모드가 되면 attack 애니메이션 클립에 의해 공격을 한다.

충돌 함수 사용하기 위해 Player에 Capsule Collider 와 Rigidbody컴포넌트를 추가하자

이제 PlayerCtrl.cs 스크립트를 수정하자.

플레이어의 초기 생명값을 100으로 지정해주며, 현재 생명값도 변수를 지정해준다.

Start() 함수는 코루틴으로 처리 가능하다.
Trigger을 체크했으므로 OnTriggerEnter() 함수로 동작이 가능하다.

추가로 플레이어의 죽음을 위해 PlayerDie()함수를 통해 실행하자.
우선 Start() 함수 코드부터 수정하자.

초기 회전 속도를 0으로 했다가 0.3초 후 80으로 변경한다.

OnTriggerEnter() 함수 추가
PlayeDie() 함수 추가하여 코드를 실행해보자.

만약 현재 체력이 0이상이고 PUNCH태그 달린 오브젝트에 충돌이 일어나면
현제 체력에서 10에 체력이 감소하게 됩니다.

만약 현재 체력이 0이하이면 PlayerDie()함수를 실행시킨다.

함수가 실행되면서 "Player DIe !"를 출력한다.



몬스터 공격 중지

특정 레이어간의 충돌 감지

몬스터 몸체에 추가된 Capsule Collider와 양손에 추가된 Sphere Collider와 움직일 때 마다 지속적인 불필요한 충돌을 만들어 내는 문제가 발생함

특정 Collider간의 충돌이 발생하지 않도록 설정해야 함
물리엔진 특성은 레이어로 판단하기 때문에 서로 다른 레이어로 설정해야 함
Inspector뷰의 상단에 Layers -> Edit Layer를 선택함
MONSTER_BODY / MONSTER_PUNCH 레이어를 만든다.


몬스터의 레이어를 MONSTER_BODY로 바꾼다.
하위 오브젝트도 함께 바꿀것인가? -> 반드시 No, this object only 를 선택

몬스터 양손의 레이어를 MONSTER_PUNCH로 바꾼다.


Physics Manager 설정

PhysicsManager에서 서로다른 레이어간의 물리적 충돌을 제외시킴
충돌이 발생하는 레이어간의 정보를 표시함
MONSTER_BODY / MONSTER_PUNCH를 언체크 한다.
두 레이어 간의 물리적 충돌은 일어나지 않음

Edit - Project Settings - Physics

수 많은 Rig(본, 뼈대)들은 GameObject이며, 각각의 Transform 컴포넌트를 포함하고 있다. 런타임시 많은 연산을 하기 때문에 최적화가 필요하다. 실제 게임에서 필요한 Rig(양손)만 남겨놓고 다른것은 노출되지 않도록 함
Optimize Game Object 를 체크
Extra Transforms to Expose 에서 L_wrist / R_writst 를 체크하고 Apply


몬스터 공격 중지

플레이어의 hp가 0이면 몬스터는 공격 행동을 멈추고 추적도 중지해야 함
몬스터는 계속 공격을 할 때 캐릭터가 죽었다는 것을 알려야 한다. -> 몬스터가 여러마리일 경우 모든 몬스터에게 전달해야 한다.

Scene에서 특정 게임오브젝트를 참조하기 위해 태그 사용을 활용함
MONSTER라는 태그를 추가하고 Monster의 태그로 설정


스크립트 수정 (PlayerCtrl.cs)
PlayerDie() 함수 업데이트

SendMessage : 첫번째 인자로 전달한 함수명과 동일한 함수가 해당 게임오브젝트의 스크립트에 있다면 실행하라.
SendMessageOptions.DontRequireReceiver : 호출한 함수가 없더라도 함수가 없다는 메세지를 반환하지 않겠다. -> 빠른 실행을 위해서 반드시 필요함

스크립트 수정 (MonsterCtrl.cs)
OnPlayerDie() 함수 추가

private readonly int hashPlayerDie = Animator.StringToHash("PlayerDie");

위에 변수를 선언하며 정수형태로 해시 값을 변경해준다.

코루틴 함수 모두 정지 (몬스터의 상태와 행동을 수행)
네비게이션 기능 멈춤 (추적 중지)
상태 전이로 춤추는 애니메이션 수행

Animator 뷰 편집

Monster@Ganam Style 애니메이션 상태 추가
(혹은 Ganam Style)
그림과 같이 상태 전이 만들기
Trigger타입의 변수 IsPlayerDie 만들기

지금까지 만든 몬스터를 프리펩으로 만든다.
프리펩 옵션 창이 나오면 “Original Prefab”을 선택
프리펩으로 만든 몬스터를 여러마리 배치 함
실행 시켜서 몬스터들의 동작을 확인한다.


애니메이션 재생 속도 조절

MonsterAnim콘트롤러를 열고 float 타입의 파라미터를 생성한다 : Speed
Speed 속성은 애니메이션의 재생 속도를 의미함
기본값 1 (정상 재생 속도), 0.5(절반의 속도로 재생)

이제 MonsterCtrl 스크립트를 수정한다.

private readonly int hashSpeed = Animator.StringToHash("Speed");

위에 코드를 적어 정수형 해시값으로 변경한다.

anim.SetFloat(hashSpeed, Random.Range(0.8f, 1.2f));

OnPlayerDie() 함수에 적어주면 된다.


몬스터 공격 중지와 사망 - Delegate/Event

PlayerCtrl.cs 스크립트 수정

델리게이트와 이벤트를 선언한다.

지금까지 작성했던 코드들을 조금씩 수정해보자.
MonsterCtrl.cs 스크립트 수정

MonsterCtrl.cs 스크립트 수정 (2) : 변수 선언 부분 (아래 사진)


MonsterCtrl.cs 스크립트 수정 (3)
OnEnable() / OnDisable() / Start()


MonsterCtrl.cs 스크립트 수정 (4) : IEnumerator CheckMonsterState()

MonsterCtrl.cs 스크립트 수정 (5) : IEnumerator CheckMonsterState()


MonsterCtrl.cs 스크립트 수정 (6) : OnCollisionEnter()


MonsterCtrl.cs 스크립트 수정 (7)

길었던 코드 수정, 정리가 끝이 났다.
대부분 그대로이긴 한데 추가한 부분도 있고 보기 쉽게 정리 했다고 보면 된다.



몬스터 사망 처리

Animator 뷰 편집

die 애니메이션 클립 추가
Trigger타입의 “Die” 변수 만들기
상태 전이 화살표 만들기

붕 떠 있는 몬스터 바로 잡기

이것으로 가장 복잡했던 적 캐릭터 제작(2)를 마쳤다.

profile
나만의 공간

0개의 댓글