Humility

아무리 노력해도 최고가 되지 못할 수 있다⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀그럼에도 노력하는자가 가장 겸손한 것 아닌가

공부하는 블로그

유니티/문법

[Unity] 유니티 C#) Property ( 프로퍼티 )

새벽_글쓴이 2025. 1. 20. 22:54
반응형

프로퍼티란?

객체 지향 프로그래밍 언어에서 객체의 속성을 의미하는 용어


프로퍼티와 캡슐화

캡슐화란?

데이터(변수)와 해당 데이터를 처리하는 메서드들을 하나로 묶어서 관리하는 것

 

특징

  • 외부에서 직접적인 접근을 제한하고, 정해진 방법으로만 접근하도록 만드는 것이다
  • "중요한 데이터를 보호하는 포장지"라고 생각하면 된다

 

예시

public class Player
{
    private int health; // 직접 접근 불가능
    
    // health는 이 메서드들을 통해서만 수정 가능
    public void TakeDamage(int damage)
    {
        health -= damage;
        if(health < 0) health = 0;
    }
    
    public void Heal(int amount)
    {
        health += amount;
        if(health > 100) health = 100;
    }
}

프로퍼티란?

필드(변수)에 접근할 때 사용하는 특별한 메서드

 

특징

  • 겉으로는 변수처럼 보이지만, 실제로는 메서드처럼 동작한다
  • 데이터를 읽고(get) 쓸 때(set) 추가적인 로직을 넣을 수 있다

 

예시

public class Player
{
    private int health; // 일반 변수

    // 프로퍼티
    public int Health
    {
        get { return health; } // 값을 읽을 때
        set 
        { 
            // 값을 쓸 때 추가 로직 수행
            if(value < 0)
                health = 0;
            else if(value > 100)
                health = 100;
            else
                health = value;
        }
    }
}

 

캡슐화는 데이터 보호를 위한 포장
프로퍼티는 포장을 안전하게 뜯는 도구

프로퍼티 사용법

기본 프로퍼티
private int health; // 백킹 필드

public int Health // 프로퍼티
{
    get { return health; }
    set { health = value; }
}

 

자동구현 프로퍼티
public float Speed { get; set; } // 백킹 필드가 자동으로 생성됨

 

읽기 전용
// 읽기전용
public string PlayerName { get; private set; }
// 또는
public float MaxHealth { get; } // 생성자에서만 설정 가능

 

계산된 프로퍼티
public float HealthPercentage
{
    get { return (health / maxHealth) * 100f; }
}

실제 사용예시

플레이어 체력 시스템
public class Player : MonoBehaviour
{
    [SerializeField] private float maxHealth = 100f;
    private float currentHealth;

    public float Health
    {
        get { return currentHealth; }
        set
        {
            currentHealth = Mathf.Clamp(value, 0f, maxHealth);
            UpdateHealthUI();  // UI 업데이트
            
            if(currentHealth <= 0)
                Die();
                
            // 체력 변경 시 이펙트 재생
            PlayHealthChangeEffect();
        }
    }

    private void Start()
    {
        Health = maxHealth;  // 초기화
    }
}

 

무기 시스템
public class Weapon : MonoBehaviour
{
    private int ammo;
    public int Ammo
    {
        get { return ammo; }
        set
        {
            ammo = Mathf.Max(0, value);  // 음수 방지
            UpdateAmmoUI();  // UI 업데이트
            
            // 탄약이 없을 때 자동 리로드
            if(ammo == 0)
                StartReload();
        }
    }
}

 

점수 시스템
public class ScoreManager : MonoBehaviour
{
    private int score;
    public int Score
    {
        get { return score; }
        set
        {
            if(value > score)  // 점수가 증가할 때만
            {
                PlayScoreAnimation();
                CheckHighScore(value);
            }
            score = value;
            UpdateScoreUI();
        }
    }
}

프로퍼티를 사용하는 이유

1. 데이터 보호

  • 외부에서 직접적인 변수 접근을 제한하여 안전성 확보
  • 잘못된 값이 설정되는 것을 방지할 수 있음

 

2. 유연한 데이터 처리

  • 값을 읽거나 쓸 때 추가적인 로직 실행 가능
  • 계산된 값을 반환하거나 데이터 변환 가능

 

3. 코드 유지보수

  • 내부 구현을 변경해도 외부 코드에 영향을 주지 않음
  • 디버깅과 로깅이 용이

프로퍼티의 장점

1. 데이터 일관성 유지

public float Health
{
    get { return health; }
    set 
    {
        // 값의 범위 검증
        health = Mathf.Clamp(value, 0f, maxHealth);
        
        // 연관된 시스템 업데이트
        UpdateHealthUI();
        CheckGameOver();
        
        // 이벤트 발생
        OnHealthChanged?.Invoke(health);
    }
}

 

2. 자동화된 기능 연동

public bool IsInvincible
{
    get { return isInvincible; }
    set 
    {
        isInvincible = value;
        
        // 시각적 효과 자동 적용
        playerRenderer.material = value ? invincibleMaterial : normalMaterial;
        
        // 무적 상태에 따른 콜라이더 조정
        playerCollider.enabled = !value;
        
        // 관련 파티클 시스템 제어
        if(value)
            invincibleEffect.Play();
        else
            invincibleEffect.Stop();
    }
}

 

3.디버깅 및 로깅 용이

public Vector3 Position
{
    get { return transform.position; }
    set 
    {
        // 위치 변경 추적
        Debug.Log($"[{Time.time}] Position changed: {transform.position} -> {value}");
        
        // 비정상적인 위치 감지
        if(float.IsNaN(value.x) || float.IsNaN(value.y) || float.IsNaN(value.z))
        {
            Debug.LogError("Invalid position detected!");
            return;
        }
        
        transform.position = value;
    }
}

 

4. 확장성과 유연성

public int Level
{
    get { return level; }
    set 
    {
        int oldLevel = level;
        level = value;
        
        // 레벨업 시 추가 효과
        if(level > oldLevel)
        {
            // 스탯 증가
            IncreaseStats();
            
            // 새로운 스킬 해금
            UnlockNewSkills();
            
            // 레벨업 효과 재생
            PlayLevelUpEffect();
            
            // 업적 시스템 연동
            AchievementManager.Instance.CheckLevelAchievements(level);
        }
    }
}

 

5. 인터페이스와의 호환성

public interface IDamageable
{
    float Health { get; set; }
}

public class Enemy : MonoBehaviour, IDamageable
{
    public float Health 
    {
        get => health;
        set 
        {
            health = value;
            if(health <= 0)
                Die();
        }
    }
}

 

6. 성능 최적화

private Vector3 _cachedPosition;
public Vector3 AveragePosition
{
    get 
    {
        // 매 프레임마다가 아닌, 일정 시간마다 계산
        if(Time.time - lastCalculationTime > updateInterval)
        {
            _cachedPosition = CalculateAveragePosition();
            lastCalculationTime = Time.time;
        }
        return _cachedPosition;
    }
}

 

7. 데이터 바인딩과 이벤트 처리

public event Action<int> OnScoreChanged;
private int score;
public int Score
{
    get { return score; }
    set 
    {
        if(score != value)
        {
            score = value;
            OnScoreChanged?.Invoke(score);
            
            // 하이스코어 갱신
            if(score > PlayerPrefs.GetInt("HighScore"))
                PlayerPrefs.SetInt("HighScore", score);
                
            // UI 업데이트
            scoreText.text = score.ToString();
        }
    }
}

 

여러 시스템이 상호작용하는 게임에서는
프로퍼티를 통한 자동화된 데이터 관리와 시스템 연동이
코드의 안정성과 유지보수성을 향상 시킬 수 있을 것이다
반응형