본문 바로가기
게임 개발

[Unity] 디펜스게임 개발 - Hp Bar 최적화

by chobbo 2024. 7. 29.

문제 상황

 

생성되는 몬스터가 각각 자신의 World Space 캔버스를 가지고 있었다.

디펜스 게임 특성 상 몬스터의 수가 많을 수 밖에 없는데, 이 때 몬스터가 많아질수록

각각 가진 캔버스의 개수에 따라 드로우 콜이 발생하였다.

 

 

window > Analysis > Frame Debugger에서 드로우 콜 개수를 확인해보았더니

 

 

몬스터가 21마리일 때 드로우콜 21개가 발생하는 것을 확인할 수 있었다.

 

따라서 HP바 이미지을 오브젝트 풀링을 사용하여 미리 생성해두고

max 스폰 양이 20이라 20개 생성

 

Enemy가 스폰될 때 각각의 Enemy에 새로운 Hp바를 할당해주었다.

enemy = GameManager.Instance.Pool.SpawnFromPool((int)EEnemyType.Basic).ReturnMyComponent<Enemy>();
UIManager.Instance.UI_EnemyHpBar.SetHpBarToEnemy(enemy); // enemy 마다 Hp바 할당

 

모든 Hp바 이미지들을 가지고 있을 캔버스 내에 아래 함수를 선언해두었다.

public void SetHpBarToEnemy(Enemy enemy)
{
    HpBar hpBar = GameManager.Instance.Pool.SpawnFromPool((int)EOhterRcode.O_HpBar).ReturnMyComponent<HpBar>();
    hpBar.transform.SetParent(this.transform);
    hpBar.InitalizeHpBar(enemy);
}

 

아래는 각각의 Hp바 이미지가 가지고 있는 스크립트이다.

각 Enemy의 HealthSystem 이벤트를 구독 및 해제하여 Fill Image를 업데이트 해주었다.

using UnityEngine.UI;
using UnityEngine;

public class HpBar : PoolObject
{
    [SerializeField] private Image fillImage;

    private Enemy enemy;
    private Camera MainCamera;

    private void Awake()
    {
        if (MainCamera == null)
        {
            MainCamera = Camera.main;
        }
    }
    private void Update()
    {
        SetHpBarPosition();
        RotateHpBarToCam();
    }

    public void InitalizeHpBar(Enemy enemy)
    {
        this.enemy = enemy;
        fillImage.fillAmount = 1;
        enemy.HealthSystem.OnHealthChange += UpdateHpBar;
        enemy.HealthSystem.OnDie += DeActivateHpBar;
    }

    private void DeActivateHpBar()
    {
        gameObject.SetActive(false);
        transform.SetParent(GameManager.Instance.Pool.poolTransforms[3]);
        if (enemy != null)
        {
            enemy.HealthSystem.OnHealthChange -= UpdateHpBar;
            enemy.HealthSystem.OnDie -= DeActivateHpBar;
            enemy = null;
        }
    }

    private void UpdateHpBar(float healthPercentage)
    {
        fillImage.fillAmount = healthPercentage;
    }

    private void RotateHpBarToCam()
    {
        transform.LookAt(transform.position - MainCamera.transform.forward, MainCamera.transform.up);
    }

    private void SetHpBarPosition()
    {
        if (enemy != null)
            transform.position = enemy.transform.position + Vector3.up * 1.7f + Vector3.forward * -0.4f;
    }
}

 

 

모든 Hp바가 하나의 캔버스에 그려지고, 드로우 콜이 1개로 줄어든 모습을 볼 수 있다.