게임개발 숙련 강의 정리
- 오늘은 강의 내용중에 아직 익숙하지 않은 인퍼테이스 관련 코드가있어서 플로우와 함께 정리 하려고 한다!
기능 : 플래이어 스탯 변화의 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월이다 벌써 얼마 안남은것같다. 더욱더 성실하게 한 주를 보내야지