public class RewardAndPortalStone : MonoBehaviour, IInteractable
{
[SerializeField] protected int NPCCode;
protected Outlinable outlinable;
[Header("윤곽선 설정")]
[SerializeField] protected Color outlineColor = new Color(1f, 0.7f, 0f, 1f);
[SerializeField] protected float outlineWidth = 5f;
private void Awake()
{
outlinable = GetComponent<Outlinable>();
if (outlinable == null)
outlinable = gameObject.AddComponent<Outlinable>();
outlinable.RenderStyle = RenderStyle.Single;
outlinable.OutlineParameters.Color = outlineColor;
outlinable.OutlineParameters.DilateShift = outlineWidth;
outlinable.OutlineParameters.BlurShift = 1f;
outlinable.AddAllChildRenderersToRenderingList();
ShowOutline(false);
}
public void Interact()
{
var existingUI = Managers.UI.IsOpened<UIRewardStone>();
if (existingUI != null)
Managers.UI.Hide<UIRewardStone>();
else
Managers.UI.Show<UIRewardStone>();
}
public void ShowOutline(bool show)
{
if (outlinable != null)
outlinable.OutlineParameters.Enabled = show;
}
public Transform GetTransform()
{
return this.transform;
}
}
using UnityEngine;
using EPOOutline;
public class RewardAndPortalStone : MonoBehaviour, IInteractable
{
[SerializeField] protected int NPCCode;
protected Outlinable outlinable;
[Header("윤곽선 설정")]
[SerializeField] protected Color outlineColor = new Color(1f, 0.7f, 0f, 1f);
[SerializeField] protected float outlineWidth = 5f;
private void Awake()
{
outlinable = GetComponent<Outlinable>();
if (outlinable == null)
outlinable = gameObject.AddComponent<Outlinable>();
outlinable.RenderStyle = RenderStyle.Single;
outlinable.OutlineParameters.Color = outlineColor;
outlinable.OutlineParameters.DilateShift = outlineWidth;
outlinable.OutlineParameters.BlurShift = 1f;
outlinable.AddAllChildRenderersToRenderingList();
ShowOutline(false);
}
public void Interact()
{
var existingUI = Managers.UI.IsOpened<UIRewardStone>();
if (existingUI != null)
Managers.UI.Hide<UIRewardStone>();
else
Managers.UI.Show<UIRewardStone>();
}
public void ShowOutline(bool show)
{
if (outlinable != null)
outlinable.OutlineParameters.Enabled = show;
}
public Transform GetTransform()
{
return this.transform;
}
}
using UnityEngine;
using UnityEngine.Timeline;
public class EnterBossStage : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
if (other.gameObject == Managers.Character.Player.gameObject)
{
var existingUI = Managers.UI.IsOpened<UIShelterBossEnter>();
if (existingUI != null)
Managers.UI.Hide<UIShelterBossEnter>();
else
Managers.UI.Show<UIShelterBossEnter>();
}
}
}
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using System;
public class UIShelterBossEnter : UIPopUp
{
[SerializeField] private TextMeshProUGUI floorNumber;
[SerializeField] private Button enterButton;
private int seletedFloor;
protected override void Awake()
{
base.Awake();
enterButton.onClick.AddListener(OnEnterButton);
}
private void OnEnable()
{
floorNumber.text = Managers.Game.TopCurFloor.ToString();
}
public override void Hide()
{
base.Hide();
Managers.UI.Hide<UIShelterBossEnter>();
}
public void OnEnterButton()
{
Managers.Sound.PlaySFX(SFX.NPC_OpenGate);
Hide();
Managers.Stage.CreateStage();
}
}
참조 형식과 값 형식은 데이터 저장 방식과 메모리 사용에 차이가 있습니다.
참조 형식
값 형식
얕은 복사 (Shallow Copy)
깊은 복사 (Deep Copy)
using System;
using Newtonsoft.Json;
class Person {
public string Name { get; set; }
public int[] Scores { get; set; }
}
class Program {
static T DeepCopy<T>(T obj) {
string json = JsonConvert.SerializeObject(obj); // 객체를 JSON으로 직렬화
return JsonConvert.DeserializeObject<T>(json); // JSON을 역직렬화하여 깊은 복사 생성
}
static void Main() {
// 원본 객체 생성
Person original = new Person { Name = "홍길동", Scores = new int[] { 90, 80, 70 } };
// 깊은 복사 수행
Person deepCopy = DeepCopy(original);
// 복사본 수정
deepCopy.Scores[0] = 100;
// 결과 확인
Console.WriteLine($"원본 Scores[0]: {original.Scores[0]}"); // 출력: 90
Console.WriteLine($"복사본 Scores[0]: {deepCopy.Scores[0]}"); // 출력: 100
}
}
int value = 10; // 스택에 저장
object obj = value; // 힙에 박싱된 값 저장
object obj = 10; // 힙에 박싱된 값
int value = (int)obj; // 스택으로 언박싱
class Parent { }
class Child : Parent { }
A
/ \
B C
\ /
D
인터페이스란 클래스가 구현해야 하는 멤버들을 정의하는 것
인터페이스는 클래스의 일종이 아니며, 클래스에 대한 제약 조건을 명시하는 것
클래스가 인터페이스를 구현할 경우, 모든 인터페이스 멤버를 구현해야 함
인터페이스는 다중 상속을 지원
인터페이스에서 선언한 멤버(메서드, 프로퍼티, 이벤트 등)는 기본적으로 public으로 간주 됨. 또한 오직 public으로 선언해야 함
구현 클래스는 상속받은 항목들을 public 아니먄 virtual로 구현해야 함
사용하는 이유
코드의 재사용성
인터페이스를 사용하면 다른 클래스에서 해당 인터페이스를 구현하여 동일한 기능을 공유할 수 있음. 인터페이스를 통해 다양한 클래스가 동일한 동작을 수행할 수 있으므로 코드의 재사용성이 향상 됨
다중 상속 제공
C#에서는 클래스는 단일 상속만을 지원하지만, 인터페이스는 다중 상속을 지원함. 클래스가 여러 인터페이스를 구현함으로써 여러 개의 기능을 조합할 수 있음. 다중 상속을 통해 클래스는 더 다양한 동작을 수행할 수 있음
유연한 설계
인터페이스를 사용하면 클래스와 인터페이스 간에 느슨한 결합을 형성할 수 있음. 클래스는 인터페이스를 구현하기만 하면 되므로, 클래스의 내부 구현에 대한 변경 없이 인터페이스의 동작을 변경하거나 새로운 인터페이스를 추가할 수 있음. 이는 유연하고 확장 가능한 소프트웨어 설계를 가능하게 함
추상클래스
인터페이스
0세대(Gen 0)
새로 생성된 객체가 할당되는 공간. 대부분의 객체는 단기적으로 사용되고, 빠르게 소멸되므로 이 단계에서 수집됩니다.
1세대(Gen 1)
0세대에서 살아남은 객체가 이동되는 공간. 중기 생존 객체를 관리하며, 주로 0세대와 2세대 사이의 완충 역할을 합니다.
2세대(Gen 2)
1세대에서도 살아남아 장기적으로 존재하는 객체가 할당되는 공간. 노년 객체를 관리하며, 이 세대에서는 가장 덜 빈번하게 수집이 이루어집니다.