☸ 약한 참조 싱글톤

HSD·2025년 3월 18일
0

팀 프로젝트

목록 보기
7/8

✤ 약한참조 싱글톤이란?

원래 싱글톤은 크게 시작될때 바로 생성과 처음 사용될때에 생성이 있다.
여기서 문제점은 이 싱글톤들은 생성된 시점부터 사라지지않고 메모리를 차지한다. 그래서 약한참조 싱글톤이 있다.

using System;
using UnityEngine;

public class DamageableManager
{
    private int strDamage = 1;
    private int strMaxHealth = 1;

    private int agiDamage = 1;
    private int agiCritDamage = 1;
    private int agiCritChance = 1;

    private int vitMaxHealth = 1;
    private int vitDefense = 1;

    private static WeakReference<DamageableManager> instance;

    private DamageableManager() { }

    public static DamageableManager Instance
    {
        get
        {
            if (instance == null || !instance.TryGetTarget(out var singleton))
            {
                singleton = new DamageableManager();
                instance = new WeakReference<DamageableManager>(singleton);
            }
            return singleton;
        }
    }

    public void CalculateTotalDamage(CharacterStats myStats, CharacterStats enemyStats, float attackPower)
    {
        float totalDamage;

        totalDamage = GetDamage(myStats) * attackPower;

        if (CanCrit(myStats))
        {
            totalDamage *= (GetCritDamage(myStats) / 100);
        }
        totalDamage = CheckTargetDefense(totalDamage, enemyStats);

        enemyStats.DecreaseHealth((int)totalDamage);
    }

    public bool CanCrit(CharacterStats myStats)
    {
        if (GetCritChance(myStats) > UnityEngine.Random.Range(0, 100))
        {
            return true;
        }
        return false;
    }

    public float CheckTargetDefense(float totalDamage, CharacterStats enemyStats)
    {
        totalDamage -= totalDamage * (GetDefense(enemyStats) / (GetDefense(enemyStats) + 50));

        return totalDamage;
    }

    #region Get Stats
    public int GetDamage(CharacterStats Stats)
    {
        return Stats.damage.GetValue() +
              (Stats.strength.GetValue() * strDamage + Stats.agility.GetValue() * agiDamage);
    }

    public float GetDefense(CharacterStats stats)
    {
        return stats.defense.GetValue() +
               stats.vitality.GetValue() * vitDefense;
    }

    public int GetMaxHealth(CharacterStats stats)
    {
        return stats.maxHealth.GetValue() +
               stats.vitality.GetValue() * vitMaxHealth + stats.strength.GetValue() * strMaxHealth;
    }

    public int GetCritChance(CharacterStats stats)
    {
        return stats.critChance.GetValue() +
               stats.agility.GetValue() * agiCritChance;
    }

    public int GetCritDamage(CharacterStats stats)
    {
        return stats.critDamage.GetValue() +
               stats.agility.GetValue() * agiCritDamage;
    }
    #endregion
}

데미지 계산을 static Class로 하였는데 이는 계속 메모리누수가 발생할 수 있어서 피하고 싶었다.
그래서 약한 참조 싱글톤을 생성하여 관리하도록 하였다.

  • 약한참조 싱글톤은 GC(가비지 컬렉터)가 삭제할 수 있는 싱글톤이다.
    그래서 사용하지 않을 때에는 GC가 삭제해주기에 메모리 누수를 방지 할 수 있다.

  • 하지만 반대로 GC가 삭제하기에 nullError가 일어날 가능성이 있다.
    그래서 nullCheck을 해줘야 안전하게 사용 가능하다.

  • 약한참조이기에 static Class처럼 이전 내용이 저장되지않는다.
    그래서 이전의 행동과 같은 데이터가 많이 필요없고 데미지 계산이 위주이기 때문에 약한참조 싱글톤을 제작하였다.

  • 하지만 나중에 저장해야 하는 시스템을 만든다고 하면 언제든 static class로도 돌아갈 수 있도록 준비는 해둬야겠다.

✤ 마무리

약한 참조 싱글톤은 처음 써보는데 메모리 누수 방지 역할을 한다는 거에 일단 마음이 너무 편안해 졌다.
요즘 뭔가 최적화... 최적화...만을 찾고 있는데 딱 좋은 예시가 들어와 준 것 같아서 너무좋다.
물론 사용할 때에 주의가 필요하겠지만 내가 주의를 잘하면 해결될 문제이다.
(static 메모리 누수는 내가 주의 할 수 없다...)

0개의 댓글