쫑가 과정

데미지 입는 효과 주기 / 캐릭터 깜빡이기 본문

Unity 따라 배우기/Topdown 2D RPG In Unity

데미지 입는 효과 주기 / 캐릭터 깜빡이기

쫑가 2022. 3. 8. 19:31

결과

도움을 받은 영상과는 코드가 다릅니다. 

영상에서는

이런 식으로 간격을 수동적으로 조건을 줬다. 이렇게 하면 나중에 깜빡이 간격 변경이 힘들고 보기도 별로라고 생각했다.

1. 깜빡이기.

깜빡이게 하는 건 쉽다. 

SpriteRenderer의 color를 이용.

private SpriteRenderer spriteRenderer;
        void Awake()
        {
            spriteRenderer = GetComponent<SpriteRenderer>();
        }
        void Update()
        {
		if (spriteRenderer.color == new Color(spriteRenderer.color.r, spriteRenderer.color.g, spriteRenderer.color.b, 1f);)
                {
                    spriteRenderer.color = new Color(spriteRenderer.color.r, spriteRenderer.color.g, spriteRenderer.color.b, 0f); 
                } 
                else if (spriteRenderer.color == new Color(spriteRenderer.color.r, spriteRenderer.color.g, spriteRenderer.color.b, 0f);)
                {
                    spriteRenderer.color = new Color(spriteRenderer.color.r, spriteRenderer.color.g, spriteRenderer.color.b, 1f);
                }
	}

투명도가 0이면 1로 만들고 1이면 0으로 만드는 조건문을 사용한다.

2. 깜빡이는 간격 정하기.

수정이 쉽게 만들고 싶다.

작성해 놓은 코드와 어우러지게 하는 부분이 어려웠다.

대미지 딜레이 코드

virtual protected void Update()
        {
            DamageDelay();
        }
protected void DamageDelay()
        {
            if (isDamage && damageDelay > 0)
            {
                damageDelay -= Time.deltaTime;
                if (damageDelay <= 0)
                {
                    isDamage = false;
                    damageDelay = initialDamageDelay;
                }
            }
        }

Update로 대미지 딜레이 시간이 감소하는 형태이다.

대미지 딜레이 시간이 감소하는 동안만 깜빡이게 해야 한다.

매 프레임마다 작동하기에 조건문 for 또는 while은 쓸 수가 없겠더라.

고민 끝에 나온 깜빡이는 조건문

// 데미지 딜레이 시간이 초기 딜레이시간 - 깜빡이 간격보다 작다
if (damageDelay < initialDamageDelay - damageFlashInterval)

대미지 딜레이 시간은 이미 작성한 코드로 알아서 줄어든다.

딜레이 시간이 특정 시간에 도달할 때마다 작동하게 하는 거다.

초기 딜레이 시간은 고정이기에 깜빡이 간격이 증가하게 만든다.

// 깜빡이 시간 변수
[SerializeField] protected float damageFlashInterval = 0f;
// 깜빡이 시간 초기 값 변수
private float initialDamageFlashInterval;
        protected void DamageDelayAction()
        {
            var flashView = new Color(spriteRenderer.color.r, spriteRenderer.color.g, spriteRenderer.color.b, 1f);
            var flashHide = new Color(spriteRenderer.color.r, spriteRenderer.color.g, spriteRenderer.color.b, 0f);
            // 데미지 딜레이 시간이 특정 값보다 작아질 때마다 작동
            if (damageDelay < initialDamageDelay - damageFlashInterval)
            {
            	// 깜빡이 간격이 증가.
                damageFlashInterval += initialDamageFlashInterval;
                
                if (spriteRenderer.color == flashView)
                {
                    spriteRenderer.color = flashHide; 
                } else if (spriteRenderer.color == flashHide)
                {
                    spriteRenderer.color = flashView;
                }
            }
            // 데미지 즉시 작동
            else if (damageDelay > initialDamageDelay * 0.99f)
            {
                spriteRenderer.color = flashHide;
            }
        }

3. 종합 코드

using System;
using UnityEngine;

namespace AllUnits
{
    public class Unit : MonoBehaviour
    {
        [SerializeField] protected float speed = 3f;
        [SerializeField] internal float maxHealth = 50f;
        [SerializeField] internal float currentHealth;
        [SerializeField] internal float damage = 5f;
        [SerializeField] internal float damageDelay = 2f;       
        [SerializeField] protected bool isDamage = false;
        // 이번에 추가된 변수
        [SerializeField] protected float damageFlashInterval = 0f;
        private float initialDamageDelay;
        private float initialDamageFlashInterval;
        protected SpriteRenderer spriteRenderer;
        //
        virtual protected void Awake()
        {
            spriteRenderer = GetComponent<SpriteRenderer>();
        }
        virtual protected void Start()
        {
            currentHealth = maxHealth;
            initialDamageDelay = damageDelay;
            // 깜빡이 간격 초기 값 저장.
            initialDamageFlashInterval = damageFlashInterval;
        }
        virtual protected void Update()
        {
            DamageDelay();
        }
        protected void DamageDelay()
        {
            if (isDamage && damageDelay > 0)
            {
                damageDelay -= Time.deltaTime;
                // 데미지 딜레이 때 작동.
                DamageDelayAction();
                if (damageDelay <= 0)
                {
                    isDamage = false;
                    damageDelay = initialDamageDelay;
                    damageFlashInterval = initialDamageFlashInterval;
                    // 데미지 딜레이 종료 후 투명도 1
                    spriteRenderer.color = new Color(spriteRenderer.color.r, spriteRenderer.color.g, spriteRenderer.color.b, 1f);
                }
            }
        }
        protected void DamageDelayAction()
        {
            var flashView = new Color(spriteRenderer.color.r, spriteRenderer.color.g, spriteRenderer.color.b, 1f);
            var flashHide = new Color(spriteRenderer.color.r, spriteRenderer.color.g, spriteRenderer.color.b, 0f);
            if (damageDelay < initialDamageDelay - damageFlashInterval)
            {
                damageFlashInterval += initialDamageFlashInterval;
                
                if (spriteRenderer.color == flashView)
                {
                    spriteRenderer.color = flashHide; 
                } else if (spriteRenderer.color == flashHide)
                {
                    spriteRenderer.color = flashView;
                }
            }
            else if (damageDelay > initialDamageDelay * 0.99f)
            {
                spriteRenderer.color = flashHide;
            }
        }
    }
}

4. 테스트

데미지 딜레이 시간 2, 깜빡이 간격 0.01

본인 입맛에 맞게 수정 가능하다.

 

Comments