목표: 플레이어 기본 체력(100)을 바탕으로 몬스터에게 공격을 받으면 체력이 닳아야한다.
우선 체력바 구현을 위해 UI → Slider 생성
필요없는 Handle Slide Area는 제거
Slider의 Value 값(0~1)을 조절하여 HP가 깍히도록 할 예정
하트 아이콘을 좌측에 배치하고
현재 HP와 경계 및 가시성 향상을 위해 Background를 검은색으로(화살표 표시)
HP 영역은 Background 보다 작게 설정(좌, 우, 위, 아래)
체력을 표시할 HealthText는 UI 기준 우측하단에 배치하면 UI 설정은 끝난다.
public class PlayerStatData
{
[field: SerializeField] public float MaxHealth { get; private set; } = 100f;
[field: SerializeField] public float CurrentHealth { get; private set; } = 100f;
}
public class PlayerSO : ScriptableObject
{
... 중략
[field: SerializeField] public PlayerStatData StatData { get; private set; }
}
최대 체력을 설정하여 ScriptableObject에서 관리한다.
PlayerCondtion.cs를 만들어 플레이어에 붙혀주고
public class PlayerCondition : MonoBehaviour
{
public PlayerStatData playerStatData;
public BugStats bugStats;
public Slider healthBar;
public TextMeshProUGUI healthText;
private float currentHealth;
private float maxHealth;
private void Start()
{
currentHealth = playerStatData.CurrentHealth;
maxHealth = playerStatData.MaxHealth;
}
private void Update()
{
HpUpdate();
}
public void HpUpdate()
{
if (healthBar != null)
{
healthBar.value = currentHealth / maxHealth;
healthText.text = $"{currentHealth}/{maxHealth}";
}
}
public float GetCurrentHealth()
{
return currentHealth;
}
public void TakeDamage(float damage)
{
currentHealth -= damage;
Debug.Log($"플레이어가 {bugStats.bugName}에게 {damage}의 공격을 받았습니다. 현재 체력: {currentHealth}");
if (currentHealth < 0)
{
Destroy(gameObject);
Debug.Log("사망");
}
}
}
currentHealth, maxHealth 변수를 선언해서
시작시 초기화를 진행 update에서 변화된 value값을 반영해준다.
GetCurrentHealth() 메서드는 몬스터가 공격시 현재 체력을 호출하기 위한 메서드
TakeDamage 메서드는 몬스터에게 공격받을 시 체력 감소 메서드
using Unity.VisualScripting;
using UnityEngine;
public class BugAttackingState : BugState
{
private BugStats bugStats;
private float attackCoolTime = 2.0f;
private float lastAttackTime;
public override void Enter()
{
bugStats = bug.bugStats;
Debug.Log("버그 공격");
lastAttackTime = 0;
}
public override void Update()
{
lastAttackTime += Time.deltaTime; // 경과시간누적
if (lastAttackTime > attackCoolTime) // 쿨타임이 지났는지 확인
{
PlayerAttackDamage();
lastAttackTime = 0; // 마지막 공격 시간 업데이트
bug.ChangeState(bug.chasingState);
Debug.Log("플레이어 공격중");
}
}
public override void Exit() { }
... 중략
}
몬스터 공격 상태 패턴 스크립트
가장 어려웠던 부분은 Update 부분인데
update에서 호출하다보니 몬스터가 공격을 하는 조건을 걸어야 했는데
(그렇지 않으면 매프레임마다 공격하므로 플레이어 바로 die..)
처음에는 Time.time(에디터 실행후 경과시간)을 기준으로 로직을 구성했으나
여전히 의도대로 되지않아 튜터님께 Help 요청..
결론은 debug 결과 실제로는 생각대로 작동하지 않았다.
(내가 생각한 것과 다를 수 있으니 Debug의 중요성을 말씀하심)
Time.deltaTime(이전 프레임이 끝나고 현재 프레임 시작되기까지 걸린 시간)으로 로직을 수정했다.
관련 코드 해석
lastAttackTime(마지막 공격 이후 시간)을 처음 진입시 0으로 초기화 해주고
update에서 매프레임마다 Time.deltatime을 누적하고
attackCoolTime 보다 커지면 공격 실행 후 lastAttackTime 0으로 초기화 되면서
추적 로직으로 전환, 이후 2초 이상 경과시 다시 공격모드로 전환되는 원리
'개발일지 > 최종프로젝트' 카테고리의 다른 글
241226(목) [사운드 구현하기] (0) | 2024.12.26 |
---|---|
241224(화) [Light2D, Sorting Group, 공격모션 수정] (0) | 2024.12.24 |
241218(수) [Prefab 동적생성하기] (0) | 2024.12.18 |
241217(화) [Fade In / Out] (0) | 2024.12.17 |
241216(월) [공격 기능, 몬스터에게 데미지 주기] (1) | 2024.12.16 |