<목표>
1. Component를 제작해보자.
- 총과 총을 쏘는 Shooter Component를 제작한다.
2. Raycast 를 사용해서 사격감지를 하자.
3. Particle 을 사용해서 시각효과를 만들자.
4. CoRoutine을 사용해 처리중간에 대기시간을 삽입하자.
5. C# 인터페이스를 사용해 통일된 Damage 메서드를 구현하자
6. IK를 사용해서 슈터 구현시, 캐릭터가 총을 자연스럽게 잡게 하자.
인터페이스
일반적으로 Player는 Monster, 상대Player, 상자, 울타리 등등 다양한 오브젝트를 공격할 수 있다.
각 Object들은 공격받았을 시 반응이 다를 수 있다.
최악의 구현법은, 공격함수에서 공격대상 Object를 일일이 검사하고 if문으로 각 서로다른 반응을 구현하는 것이다.
세련된 방법은 Interface를 활용하는 것이다.
공격당한 다양한 타입의 Object를 하나의 Interface로 추상화하여 다룰 수 있다.
공격받을 수 있는 모든 물체를, IDamageable 인터페이스로 구현하여
총을 쏠 때 "목표물이 어떤 타입의 물체인지" 정확히 알 필요 없이 공격처리가 동작하게 구현하자.
C#의 인터페이스는 어떤 메서드를 구현토록 강제하는 계약이다.
인터페이스를 상속한 클래스는 반드시 해당 인터페이스의 메서드를 구현할 의무가 주어진다.
느슨한 커플링
어떤 스크립트가 IItem을 상속한 클래스에서 인스턴스화된 객체에 접근했다고 가정하자.
IItem을 상속한 클래스는 Use 메서드를 구현할 의무가 주어진다고 가정하자.
그럼 Duck Typing 을 인터페이스로 구현하는 셈이 된다.
void OnTriggerEnter(Collider other){
IItem item = other.GetComponent<IItem>();
if(item != null){ // item이 ammoPack인지, healthPack인지 신경쓰지 않음. 그냥 IItem을 상속한 클래스의 인스턴스라면 됨.
item.Use();
}
}
실제로는 IItem을 상속한 클래스가 수백종류는 될 수 있다. 따라서 인터페이스를 통한 구현은 정말로 필수적이다.
인터페이스의 이러한 특징이 느슨한 커플링이라고 불리는 이유는, 어떤 코드가 특정 클래스의 구현에 결합되지 않아 유연히 변경가능한 상태를 가지기 때문이다.
-> OnTriggerEnter 는, item이 HealthPack인지 AmmoPack인지 영향을 더이상 받지 않게 짜여져있다.
마찬가지로, 우리는 IDamageable을 Loose Coupling으로 구현할 것이다.
using UnityEngine;
// 데미지를 입을 수 있는 타입들이 공통적으로 가져야 하는 인터페이스
public interface IDamageable {
// 데미지를 입을 수 있는 타입들은 IDamageable을 상속하고 OnDamage 메서드를 반드시 구현해야 한다
// OnDamage 메서드는 입력으로 데미지 크기(damage), 맞은 지점(hitPoint), 맞은 표면의 방향(hitNormal)을 받는다
void OnDamage(float damage, Vector3 hitPoint, Vector3 hitNormal);
}
IDamageable 인터페이스를 상속한 클래스는 OnDamage를 구현할 의무가 주어진다.
그 보상으로, 총을 쏘는 Player 오브젝트는, OnDamage() 메서드를 실행할 때, 목표물의 타입을 체크할 필요가 없다(단, null체크는 필요하다).
Gun Object 만들기
Gun과 Shooter는 분리되어 구현할 것이다. 확장성 및 간결함 때문이다. 총을 여러 가지 구현할 수도 있으니까.
먼저, Gun을 배치할 기준점이 될 자식 Game Object를 추가한다.
위치를 보정한다. 이것은 상대위치일 것이다.
그 후, Gun Prefab을 드래그 한다.
Gun Pivot은 Gun Game Object 구현의 기준점이다. 항상 우측 팔꿈치에 위치할 것이다.
Model: 총의 3D모델
Left Handle: 왼손이 갈 위치
Right Handle: 오른손 "
Fire Position: 탄 발사 위치
탄알의 궤적은 Line Renderer가 필요하다. Line Renderer는 주어진 점들을 이은 선을 그리는 Component이다.
총을 쏘는 순간 잠시동안만 켜고 즉시 꺼질 것을 기대하기 때문에, LineRenderer 컴포넌트 체크해제부터 하고,
선을 그리지 못하게 Positions의 Size필드를 0으로 지정했다.
그리고 Audio Source를 추가하자.
그 후, Particle 효과를 추가하자. 총구화염 및 탄피배출 효과를 추가할 것이다.
Unity에서 연기/화염재 등의 시각효과는 Particle System Component를 사용한다.
기본적으로 여러 작은 Sprite Image를 랜덤하게 휘날리는 식으로 동작한다.
MuzzleFlashEffect 과 ShellEjectEffect를 미리 만들어서 제공하였으니, 이걸 추가한다.
각 Position은 (0, 0.08, 0.2) 및 (0.01, 0.09, -0.02) 로 한다.
그 후, Gun 스크립트를 추가하자.
다음 공부때는, Gun 스크립트를 완성할 것이다.
'Development > Unity Engine' 카테고리의 다른 글
[Retro유니티] Shooter 구현 - IK를 사용한 손/발 위치와 총 위치 <-> Animation 대응 (1) | 2024.12.19 |
---|---|
[Retro유니티] Gun 스크립트 - Coroutine을 사용한 Shot, Reload 구현 (0) | 2024.12.19 |
[Retro유니티] Cinemachine 을 통한 연출구현 (0) | 2024.12.15 |
[Retro유니티] 캐릭터 이동 구현 (1) | 2024.12.15 |
[Retro유니티] Upper Body 레이어 확인, Avatar Mask 적용 (0) | 2024.12.13 |