내일배움캠프 29일차 TIL, 게임개발숙련

황오영·2024년 5월 27일
0

TIL

목록 보기
29/56
post-thumbnail
post-custom-banner

게임개발 숙련 강의 정리

  • 오늘은 강의 내용중에 아직 익숙하지 않은 인퍼테이스 관련 코드가있어서 플로우와 함께 정리 하려고 한다!

기능 : 플래이어 스탯 변화의 UI반영

  • 유니티 하이어라키창에서 구조는 이렇게 3개로 되어있다.
  • Health, Hunger,Stamin 전부 condtion 스크립트를 컴포넌트로 가지고 있고 이 스크립트는 UI의 업데이트 기능으로 작동한다.
using UnityEngine;
using UnityEngine.UI;

public class Condition : MonoBehaviour
{
    /// Value값 조절, 최대치 최소치 비율성정
    public float curValue;
    public float startValue;
    public float maxValue;
    public float passiveValue;
    public Image uiBar;

    private void Start()
    {
        curValue = startValue;
    }

    private void Update()
    {
        //UI 업데이트
        uiBar.fillAmount = GetPercentage();
    }
	//더해주는 코드
    public void Add(float amount)
    {
        curValue = Mathf.Min(curValue + amount, maxValue);
    }
	//뺴주는코드
    public void Subtract(float amount)
    {
        curValue = Mathf.Max(curValue - amount, 0.0f);
    }


    float GetPercentage()
    {
        return curValue / maxValue;
    }
}
  • 이 스크립트를 UICondition 스크립트에서 관리하고 이 정보를 Player에게 넘겨준다.
using UnityEngine;

public class UICondition : MonoBehaviour
{
    public Condition health;
    public Condition hunger;
    public Condition stamina;

    private void Start()
    {
        CharacterManager.Instance.Player.condition.uiCondition = this;
    }
}
  • 이렇게 PlayerCondtions에서 UICondition의 정보를 가지고 있게되서 처리하는것
  • 여기서 interface로 데미지 타입에 대해서 설정을 해준다.
using System;
using UnityEngine;

public interface IDamagable
{
    void TakePhysicalDamge(int damage);
}

public class PlayerConditions : MonoBehaviour, IDamagable
{
    public UICondition uiCondition;

    Condition health { get { return uiCondition.health; } }
    Condition hunger { get { return uiCondition.hunger; } }
    Condition stamina { get { return uiCondition.stamina; } }

    public float noHungerHealthDecay;

    public event Action onTakeDamage;

    private void Update()
    {
        hunger.Subtract(hunger.passiveValue * Time.deltaTime);
        stamina.Add(stamina.passiveValue * Time.deltaTime);

        if (hunger.curValue == 0.0f)
        {
            health.Subtract(noHungerHealthDecay * Time.deltaTime);
        }

        if (health.curValue == 0.0f)
        {
            Die();
        }
    }

    public void Heal(float amount)
    {
        health.Add(amount);
    }
    public void Eat(float amount)
    {
        hunger.Add(amount);
    }
    private void Die()
    {
        Debug.Log("플레이어 다이");
    }

    public void TakePhysicalDamge(int damge)
    {
        health.Subtract(damge);
        onTakeDamage?.Invoke();
    }
}
  • IDamagable 인퍼테이스를 선언해주고 사용 맨 밑에 TakePhysicalDamge를 선언하고 Action 이벤트로 OnTakeDamage를 선언하여 UI이벤트에 추가하여 사용한다.
public class DamageIndicator : MonoBehaviour
{
    public Image image;
    public float flashSpeed;

    private Coroutine coroutine;

    private void Start()
    {
        CharacterManager.Instance.Player.condition.onTakeDamage += Flash;
    }
    public void Flash()
    {
        if (coroutine != null)
        {
            StopCoroutine(coroutine);
        }

        image.enabled = true;
        image.color = new Color(1f, 105f / 255f, 105f / 255f);
        coroutine = StartCoroutine(FadeAway());
    }

    private IEnumerator FadeAway()
    {
        float startAlpha = 0.3f;
        float a = startAlpha;

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

        image.enabled = false;
    }
}
  • OnTakeDamge의 경우 코루틴으로 구성된 Flash 함수를 추가시켜서 빨간 점등효과를 추가.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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

    List<IDamagable> things = new List<IDamagable>();
    private void Start()
    {
        InvokeRepeating("DealDamage", 0, damageRate);
    }

    void DealDamage()
    {
        for (int i = 0; i < things.Count; i++)
        {
            things[i].TakePhysicalDamge(damage);
        }

    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.TryGetComponent(out IDamagable damagalbe))
        {
            things.Add(damagable);
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if(other.TryGetComponent(out IDamagable damagalbe))
        {
            things.Remove(damagable);
        }
    }
}
  • 마지막으로 오브젝트에 Trigger 이벤트를 추가시켜 damagabled을 받아오고 이를 things에 저장시켜두고 데미지를 받는 주기마다 실행

정리

  • Condtions에 실질적인 UI정보, 스탯정보를 들고있고 -> 이것을 총관리해주는 UIConditions에 들고 그것을 Player에게 전달 ->
    interface로 데미지 입은것을 선언하고 난뒤에 Action과 함께 같이실행 - > Action은 UI가 점등하는 효과이벤트 추가 -> 최종적으로 오브젝트에 Trigger부분에서 받아온 뒤 실행
  • 방식은 이해하겠는데.. 역시 인터페이스 사용하는것은 너무 어렵다 이번 내일배움캠프에서 꼭 숙달하고 싶은 부분이 이런 객체지향 프로그래밍인데 아직은 구조짜는것도 어렵고 코드를 최대한 많이 봐야알것같다.

오늘의 회고

  • 객체지향은 어렵다.. 코드 많이보고 구현많이 해보고 항상 고민또 고민해 봐야겠다.
  • 같은 조원분들이 TIL엄청 성실하게 쓰셔서 나도 같이 따라서 열심히 써야겠다!
  • 이번주 예비군 일정이 있어서 목요일이 과제 마감일인데 수요일에 마감해야해서 빠르게 해야겠다. 갑자기 예비군..
  • 새주의 시작! 벌써 6월이다 벌써 얼마 안남은것같다. 더욱더 성실하게 한 주를 보내야지
profile
게임개발을 꿈꾸는 개발자
post-custom-banner

0개의 댓글