반응형
프로퍼티란?
객체 지향 프로그래밍 언어에서 객체의 속성을 의미하는 용어
프로퍼티와 캡슐화
캡슐화란?
데이터(변수)와 해당 데이터를 처리하는 메서드들을 하나로 묶어서 관리하는 것
특징
- 외부에서 직접적인 접근을 제한하고, 정해진 방법으로만 접근하도록 만드는 것이다
- "중요한 데이터를 보호하는 포장지"라고 생각하면 된다
예시
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();
}
}
}
여러 시스템이 상호작용하는 게임에서는
프로퍼티를 통한 자동화된 데이터 관리와 시스템 연동이
코드의 안정성과 유지보수성을 향상 시킬 수 있을 것이다
반응형
'유니티 > 문법' 카테고리의 다른 글
[Unity] 유니티 C#) async와 코루틴의 차이 (0) | 2025.01.22 |
---|---|
[Unity] 유니티 C#) async/await (0) | 2025.01.21 |
[Unity] 유니티C#) Struct ( 구조체 ) (1) | 2025.01.17 |
[Unity] 유니티 C#) Casting ( 형변환 ) (0) | 2025.01.16 |
[Unity] 유니티 C#) try-catch문 ( 예외처리 ) (1) | 2025.01.15 |