PlayerHealth.cs
앞서 정의한 feature 는 아래와 같다.
- LivingEntity를 확장할 것.
- LivingEntity의 생명체 기본기능을 구현할 것.
- 체력이 변경되면 Slider에 반영
- 피격시 효과음 재생
- 사망시 다른 컴포넌트 비활성화
- 사망시 효과음과 애니메이션 재생
- 아이템 감지 및 사용
자주 반복하여 알겠듯이, Awake 함수는 스크립트가 처음 로드될 때 수행된다.
Awake
호출 시점: 스크립트가 처음 로드될 때 호출됩니다.
주요 용도: 초기화 작업을 수행합니다. 다른 스크립트나 컴포넌트에 접근하기 전에 필요한 설정을 할 수 있습니다.
특징: 게임 오브젝트가 비활성화된 상태에서도 호출됩니다.
OnEnable
호출 시점: 게임 오브젝트가 활성화될 때마다 호출됩니다.
주요 용도: 게임 오브젝트가 활성화될 때마다 수행해야 하는 작업을 처리합니다.
특징: 게임 오브젝트가 활성화될 때마다 반복적으로 호출됩니다.
private void Awake() {
// 사용할 컴포넌트를 가져오기
playerAudioPlayer = GetComponent<AudioSource>();
playerAnimator = GetComponent<Animator>();
playerMovement = GetComponent<PlayerMovement>();
playerShooter = GetComponent<PlayerShooter>();
}
PlayerCharacter 게임오브젝트에서, Animator 컴포넌트와 AudioSource 컴포넌트와 PlayerMovement 컴포넌트와 PlayerShooter 컴포넌트를 가져온다.
(PlayerMovement, PlayerShooter 컴포넌트가 필요한 이유는, 캐릭터가 움직일 수 없도록/총을 쏠 수 없도록 해당 컴포넌트를 꺼야하기 때문이다.)
OnEnable에서는, PlayerHealth 컴포넌트가 활성화될때마다 체력상태를 리셋하는 처리를 구현하자.
LivingEntity 클래스의 OnEnable() 메서드를 Override하여 구현한다.
protected override void OnEnable() {
// LivingEntity의 OnEnable() 실행 (상태 초기화)
base.OnEnable();
}
override 메서드를 선언할 때 접근 제한자는 반드시 원래 메서드의 접근 제한자와 일치해야 합니다. 따라서 OnEnable 메서드가 원래 protected로 선언되어 있다면, override할 때도 protected로 선언해야 합니다.
예를 들어, LivingEntity 클래스에서 OnEnable 메서드가 protected로 선언되어 있다면, 이를 override할 때도 protected로 선언해야 합니다.
OnEnable은 부활기능을 염두에 두었다. Awake에 PlayerShooter/PlayerMovement 활성화코드를 넣지 않았기 때문이다.
참고로 PlayerShooter/PlayerMovement 비활성화코드는 PlayerHealth.Die() 에서 구현할 것이다.
RestoreHealth를 보자. 사실 체력회복기능은 부모클래스인 LivingEntity에 이미 정의되어있으니 그대로 쓰면 된다.
다만 체력바 갱신을 해야한다는 점에 유의하자. 이 점은 기존 LivingEntity에서 케어되지 않은 부분이니, 확장해야하는 것이 당연하다.
public override void RestoreHealth(float newHealth) {
// LivingEntity의 RestoreHealth() 실행 (체력 증가)
base.RestoreHealth(newHealth);
healthSlider.value = health; // 갱신된 체력으로 체력 슬라이더 갱신
}
OnDamage를 보자.
당연히, 부모인 LivingEntity의 OnDamage를 override하고,
부모측에서 이미 구현된 부분은 체력감소 및 사망처리 실행이며
자식측에서 확장되어야 할 부분은 효과음재생 및 체력바 갱신이다.
public override void OnDamage(float damage, Vector3 hitPoint, Vector3 hitDirection) {
// LivingEntity의 OnDamage() 실행(데미지 적용)
if(!dead) {
playerAudioPlayer.PlayOneShot(hitClip); // 피격 소리 재생
}
base.OnDamage(damage, hitPoint, hitDirection);
healthSlider.value = health; // 갱신된 체력으로 체력 슬라이더 갱신
}
Die를 보자.
부모측에서 이미 구현된 부분은 사망처리 실행이며,
자식측에서 확장할 부분은 사망애니메이션 재생, 사망효과음 재생, 체력슬라이더 비활성화, 다른 조작들에 대해 무반응하게 바꾸는 부분이다.
// 사망 처리
public override void Die() {
// LivingEntity의 Die() 실행(사망 적용)
base.Die();
healthSlider.gameObject.SetActive(false); // 체력 슬라이더 비활성화
playerAudioPlayer.PlayOneShot(deathClip); // 사망 소리 재생
playerAnimator.SetTrigger("Die"); // 사망 애니메이션 재생
playerMovement.enabled = false; // 플레이어 조작 불가
playerShooter.enabled = false; // 플레이어 조작 불가
}
OnTriggerEnter를 보자.
트리거 충돌한 상대방 게임오브젝트가 Item인지 여부를 판단하고, 아이템 사용처리를 구현한다.
private void OnTriggerEnter(Collider other) {
// 아이템과 충돌한 경우 해당 아이템을 사용하는 처리
IItem item = other.GetComponent<IItem>();
if (item != null) {
item.Use(gameObject); // 아이템 사용
playerAudioPlayer.PlayOneShot(itemPickupClip); // 아이템 습득 소리 재생
}
}
완성
최종 script는 아래와 같다.
using UnityEngine;
using UnityEngine.UI; // UI 관련 코드
// 플레이어 캐릭터의 생명체로서의 동작을 담당
public class PlayerHealth : LivingEntity {
public Slider healthSlider; // 체력을 표시할 UI 슬라이더
public AudioClip deathClip; // 사망 소리
public AudioClip hitClip; // 피격 소리
public AudioClip itemPickupClip; // 아이템 습득 소리
private AudioSource playerAudioPlayer; // 플레이어 소리 재생기
private Animator playerAnimator; // 플레이어의 애니메이터
private PlayerMovement playerMovement; // 플레이어 움직임 컴포넌트
private PlayerShooter playerShooter; // 플레이어 슈터 컴포넌트
private void Awake() {
// 사용할 컴포넌트를 가져오기
playerAudioPlayer = GetComponent<AudioSource>();
playerAnimator = GetComponent<Animator>();
playerMovement = GetComponent<PlayerMovement>();
playerShooter = GetComponent<PlayerShooter>();
}
protected override void OnEnable() {
// LivingEntity의 OnEnable() 실행 (상태 초기화)
base.OnEnable();
healthSlider.gameObject.SetActive(true); // 체력 슬라이더 활성화
healthSlider.maxValue = startingHealth; // 슬라이더의 최대값을 시작 체력으로
healthSlider.value = health; // 슬라이더의 값도 시작 체력으로 초기화
// 플레이어 조작을 받는 컴포넌트들 활성화
playerMovement.enabled = true; // 플레이어 움직임 활성화
playerShooter.enabled = true; // 플레이어 슈터 활성화
}
// 체력 회복
public override void RestoreHealth(float newHealth) {
// LivingEntity의 RestoreHealth() 실행 (체력 증가)
base.RestoreHealth(newHealth);
healthSlider.value = health; // 갱신된 체력으로 체력 슬라이더 갱신
}
// 데미지 처리
public override void OnDamage(float damage, Vector3 hitPoint, Vector3 hitDirection) {
// LivingEntity의 OnDamage() 실행(데미지 적용)
if(!dead) {
playerAudioPlayer.PlayOneShot(hitClip); // 피격 소리 재생
}
base.OnDamage(damage, hitPoint, hitDirection);
healthSlider.value = health; // 갱신된 체력으로 체력 슬라이더 갱신
}
// 사망 처리
public override void Die() {
// LivingEntity의 Die() 실행(사망 적용)
base.Die();
healthSlider.gameObject.SetActive(false); // 체력 슬라이더 비활성화
playerAudioPlayer.PlayOneShot(deathClip); // 사망 소리 재생
playerAnimator.SetTrigger("Die"); // 사망 애니메이션 재생
playerMovement.enabled = false; // 플레이어 조작 불가
playerShooter.enabled = false; // 플레이어 조작 불가
}
private void OnTriggerEnter(Collider other) {
// 아이템과 충돌한 경우 해당 아이템을 사용하는 처리
IItem item = other.GetComponent<IItem>();
if (item != null) {
item.Use(gameObject); // 아이템 사용
playerAudioPlayer.PlayOneShot(itemPickupClip); // 아이템 습득 소리 재생
}
}
}
컴포넌트설정
해야겠지? 조상님이 적용해주는거 아니잖아.
'Development > Unity Engine' 카테고리의 다른 글
[Retro유니티] HUD Canvas 및 GameManager.cs (0) | 2024.12.28 |
---|---|
[Retro유니티] NavMesh를 통한 길찾기 구현 및 Enemy.cs 완성 (0) | 2024.12.28 |
[Unity] 기본 Editor 변경: Visual Studio -> VSCode (0) | 2024.12.24 |
[Retro유니티] UI 슬라이더 사용을 통한 체력바 구현 & PlayerHealth.cs (0) | 2024.12.24 |
[Retro유니티] 다형성 및 Action, Delegate를 통한 Event 구현: Virtual/Abstract/Interface 차이 (0) | 2024.12.19 |