Unity숙련주차

유니티 개발 숙련 2. 플레이어에게 데미지 주기

1vdlrwnsv1 2025. 3. 5. 15:43

캠프파이어 불 안에 들어갔을때 체력이 닳게 만들것

using System.Collections.Generic;
using UnityEngine;

public class CampFire : MonoBehaviour
{
    public int damage;
    public float damageRate;

    private HashSet<IDamageable> things = new HashSet<IDamageable>();

    private void Start()
    {
        InvokeRepeating(nameof(DealDamage), 0, damageRate);
    }

    void DealDamage()
    {
        foreach (var thing in things)
        {
            thing.TakePhysicalDamage(damage);
        }
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.TryGetComponent(out IDamageable damageable))
        {
            things.Add(damageable);
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.TryGetComponent(out IDamageable damageable))
        {
            things.Remove(damageable);
        }
    }
}

불 오브젝트에 콜라이더 컴포넌트를 넣고 isTrigger 체크

 

변수

  • damage: 한 번의 공격이 줄 피해량
  • damageRate: 피해를 주는 주기 (초 단위)
  • things: 캠프파이어에 닿아 있는 객체 목록을 저장

Start() 에서 피해 반복 실행

  • InvokeRepeating("DealDamage", 0, damageRate);
  • InvokeRepeating("함수이름",시작시간,반복주기); 
    • DealDamage()를 damageRate 간격으로 반복 실행

 

DealDamage()

  • things에 저장된 모든 IDamageable 객체에 damage만큼 피해를 줌

 

트리거에 닿으면 객체 추가 (OnTriggerEnter)

  • Collider가 IDamageable을 가지고 있으면 things 목록에 추가

트리거에서 벗어나면 객체 제거 (OnTriggerExit)

  • Collider가 벗어나면 things에서 제거

 

데미지를 받으면 화면이 빨개지는거 구현

 

using System.Collections;
using UnityEngine;
using UnityEngine.UI;

public class DamageIndicator : MonoBehaviour
{
    public Image image;
    public float flashSpeed;
    private Coroutine coroutine;


    // Start is called before the first frame update
    void Start()
    {
        CharacterManager.instance.player.condition.onTakeDamage += Flash;
    }
    public void Flash()
    {
        if(coroutine != null)
        {
            StopCoroutine(coroutine);
        }
        image.enabled = true;
        image.color = new Color(1f, 100f/255f, 100f/255f);
        coroutine = StartCoroutine(FadeAway());
    }
    private IEnumerator FadeAway()
    {
        float startAlpha = 0.3f;
        float a = startAlpha;

        while(a > 0)
        {
            a -= (startAlpha / flashSpeed) * Time.deltaTime;
            image.color = new Color(1f, 100f/255f, 100f/255f, a);
            yield return null;
        }

        image.enabled = false;
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

변수

 

  • image: 데미지 효과를 표시할 UI Image
  • flashSpeed: 화면의 붉은 효과가 사라지는 속도
  • coroutine: 효과가 진행 중일 때 기존 효과를 중지하기 위한 변수

 

Start()플레이어가 데미지를 받을 때 Flash() 실행

 

  • CharacterManager.instance.player.condition.onTakeDamage 이벤트에 Flash() 등록
  • 플레이어가 데미지를 받으면 자동으로 Flash() 실행
    • Start()는 게임이 시작될 때 한 번 실행
    • CharacterManager.instance.player.condition.onTakeDamage는 플레이어가 데미지를 받을 때 호출되는 이벤트
    • onTakeDamage += Flash; → 데미지를 받으면 Flash()가 실행되도록 연결
      • CharacterManager.instance.player.condition.onTakeDamage += Flash;
      • 이 코드가 실행되면 플레이어가 공격받을 때 자동으로 Flash()가 실행
      • onTakeDamage 이벤트는 플레이어가 데미지를 입을 때 실행되는 함수 목록을 저장함
      • += 연산자로 Flash()를 여기에 추가하면, 데미지를 입을 때마다 Flash()도 같이 실행됨

 

데미지 효과 표시 Flash()

  • 기존 효과가 진행 중이면 중단 (StopCoroutine(coroutine))
  • image를 활성화하고, 색상을 **붉은색 (RGB(1, 100/255, 100/255))**으로 설정
  • FadeAway() 코루틴 시작 → 화면의 붉은 효과가 점점 사라짐
    • float startAlpha = 0.3f;
      • 이미지 처음 투명도 0.3으로 설정.
    • float a = startAlpha;
      • a에 시작 투명도값 할당.
    • while(a > 0)
      • a가 0보다 클 때까지 반복.
    • a -= (startAlpha / flashSpeed) * Time.deltaTime;
      • a를 매 프레임마다 감소.
    • image.color = new Color(1f, 100f/255f, 100f/255f, a);
      • 색상은 빨강, 초록, 파랑 고정, 알파값은 a.
      • Color(R, G, B, 투명도);
    • yield return null;
      • 한 프레임 대기 후 반복.
    • image.enabled = false;
      • 알파값 0 이하로 되면 이미지 비활성화.

 

Damage를 5로 damageRate를 1로 설정하고 불 안에 들어가면 1초마다 피가 5씩까이며 화면이 빨개지는 모습