no image
[객체지향, SOLID] 단일 책임 원칙 SRP
SOLID 아래 5개의 객체 지향 프로그래밍의 원칙을 줄여 SOLID 원칙이라 부른다.Single Reponsibility PrincipleOpen Closed PrincipleLiskov Substituion PrincipleInterface Segregation PrincipleDependency Inversion Principle해당 포스트는 SOLID 중 SRP를 다룬다. SRP(Single-Responsibility Principle, 단일 책임 원칙)모든 클래스는 하나의 책임만을 가진다. SRP는 클래스가 하나의 역할만 해야 하므로 변경해야 할 이유도 하나만 있어야 한다. 좀 더 기술적으로 설명하자면, 소프트웨어 사양에서 데이터베이스 로직, 로깅 로직 등의 변경 사항만 클래스의 사양에 영향을 ..
2024.12.23
[C#] Public 필드와 프로퍼티
Public 필드와 프로퍼티 차이 Properties vs. Public VariablesI occasionally see code with properties like this: private int name; public int Name {     get { return name; }     set { name = value; } } As I see it, there are three things to consider here. 1. When is a property not a property? When it's a glorblog.codinghorror.com위 글을 번역한 내용이다. C#에서는 아래 코드처럼 프로퍼티를 흔하게 볼 수 있다.private int name;public int Name{..
2024.12.20
C#
no image
[Unity Editor Scripting] ScriptableSingleton<T>의 직렬화 유지
문제점ScriptableSingleton을 쓸 때, 자연스럽게 딕셔너리를 사용해버렸는데, 사실 ScriptableSingleton에서 유지되는 ScriptableObject 객체라도 딕셔너리는 직렬화되지 않는다. 그래서 dictTest는 에디터가 리로딩되는 과정에서 역직렬화를 수행하게 되면 null값으로 변하게 된다. 사실 ScriptableSingleton도 ScriptableObject를 상속받아 구현되는 것이기에 당연한 것인데, 생각이 짧았다.public class HCManagers : ScriptableSingleton{ private HCModel _model; public Dictionary dictTest; public static HCModel Model { ..
2024.12.18
no image
[Unity Editor Scripting] "TYPE" must be instantiated using the ScriptableObject.CreateInstance method instead of new "TYPE"
에러 메시지HexaCraft.HCModel must be instantiated using the ScriptableObject.CreateInstance method instead of new HCModel. 원인 분석`ScriptalbeSingleton` 클래스를 상속받은 클래스 내부에서 `HCModel` 클래스 생성자를 호출하였다. HCModel은 Monobehaviour나 ScriptableObject를 상속받은 클래스가 아닌 일반 순수 클래스였다. 생각해보면, 유니티 엔진은 `ScriptableObject`를 상속받은 것들은 모두 자동으로 직렬화하는데, ` ScriptalbeSingleton`도 스크립터블 오브젝트를 상속받았으므로 이를 직렬화하는 과정에서 일반 plain 클래스가 섞여 있으면 직..
2024.12.18
[C#] static 초기화 시점과 C# type Initializer
static 변수 초기화 시점`beforefieldInit` 플래그가 설정되어있는지 아닌지에 따라 초기화 시점이 달라지는데, 해당 플래그의 여부는 정적 생성자가 있는지 여부에 따라 달라진다. 정적 생성자는 타입에 접근하는 순간 호출된다. .NET4 이후로는 동작이 더 "lazy"해진 것 같다고 한다. 정적 필드는 일반적인 코드를 사용하여 액세스하는 한 사용하기 전에 초기화된다. 솔직히 정적 필드를 초기화하는 곳에서 특정 동작을 코딩하진 않을 것이다.  Static constructor (정적 생성자)정적 생성자 설명 MSDN 정적 생성자 - C#C#의 정적 생성자는 정적 데이터를 초기화하거나 한 번만 수행되는 작업을 수행하며 첫 번째 인스턴스가 만들어지거나 정적 멤버가 참조되기 전에 실행됩니다.learn..
2024.12.08
[Unity Editor Scripting] EditorStyles null Reference
EditorStyles null Reference문제점Editor를 상속받은 클래스의 OnEnable에서 GUIStyle을 사용하려면 NullReference가 발생한다. 무조건은 아니지만, 다시 리로드되는 타이밍에는 직렬화 되지 않은 데이터는 초기화되므로 무조건 다시 NullReference가 발생하는 것 같다.private void OnEnable(){ Init(); //SOManagers.instance.hexGridGenerator = new HexGridGenerator(_hCGeneration.HexPrefab);}private void Init(){ _mainHeaderStyle = new GUIStyle(EditorStyles.boldLabel) { fon..
2024.12.06
no image
[C#] Delegate, EventHandler 그리고 구조에 대한 고민
Delegate델리게이트는 특정 매개변수와 반환 타입을 가진 메서드에 대한 "참조"를 나타내는 타입이다. 델리게이트를 인스턴스화하면, 호완가능한 시그니처와 반환 타입을 가진 모든 메소드와 연결할 수 있다. 또한 델리게이트의 인스턴스를 통해 메소드를 호출할 수 있다. 개발을 할 때 "메서드 자체를 파라미터로 전달할 수 있을까?" 라는 의문을 해결하는데는 델리게이트가 적격이다. 메서드에 대한 참조를 델리게이트로 래핑한 뒤, 메서드를 다른 메서드의 파라미터로 전달하는데 사용할 수 있다.  델리게이트 타입의 선언그럼 델리게이트 타입은 어떻게 선언할 수 있을까?public delegate void CustomCallback(string s);`접근한정자` `delegate` `반환 형식` `delegate타입 이..
2024.12.06
C#
no image
[Unity Editor Scripting] 유니티의 직렬화(serialization)와 재귀 문제 회피
스크립트 직렬화직렬화는 자료 구조(data structure) 또는 게임 오브젝트의 상태를 유니티가 저장할 수 있고 추후 Reconstruct 할 수 있는 포맷으로 자동 변환하는 프로세스이다. 유니티 프로젝트에서 데이터를 구성하는 방식은 데이터를 직렬화 하는 방식에 영향을 미치며, 이는 프로젝트 성능에 큰 영향을 미칠 수 있다. 직렬화 규칙Unity의 Serializer는 런타임에 효율적으로 동작하도록 디자인되었다. 이는 유니티의 직렬화가 다른 프로그래밍 환경의 직렬화와 다르게 동작하기 때문이다. Unity의 직렬화는 프로퍼티가 아닌 C# 클래스의 필드에서 직접 동작하기에 유니티는 특정 조건을 충족할 때만 직렬화를 수행한다. 필드 직렬화를 하는 방법public으로 선언 또는 SerializeField a..
2024.11.09
[Unity] Renderer.materials, Renderer.sharedMaterials
Renderer.SharedMaterial인스펙터에서 보는 매터리얼은 Renderer의 SharedMaterial에 저장되어 있다고 함. sharedMaterial을 수정하면 해당 매터리얼을 사용하는 모든 오브젝트의 모양이 변경되고, 프로젝트에 저장된 매터리얼 설정도 변경된다. sharedMaterial이 반환한 material은 수정하지 않는 것이 좋다. renderer의 material을 수정하려면 그냥 Renderer.material 를 사용하는 것을 추천한다. Unity에서는 Render.material에 접근하는 순간 sharedMaterial의 사본을 만들게 된다. 따라서 sharedMaterial과 독자적으로 동작하는 material의 인스턴스가 생성되고 이는 기존 매터리얼이 아닌 별도의 매..
2024.11.08
no image
[Unity Editor Scripting] Editor관련 함수 정리
EditorWindowScriptableObject를 상속받아 구현된 클래스이며 UnityEditor의 네임스페이스에 속한다. 이 클래스를 사용하여 유니티 에디터의 기본 창과 유사하게 독립적으로 띄울 수있거나 탭에 부착 가능한 Editor window를 만들 수 있다.  다음 다이어그램은 에디터 윈도우의 실행 순서이다.OnEnable: 스크립트가 로드되거나 오브젝트가 활성화될 때 호출된다.EditorApplication.isUpdating: true라면, 에디터는 현재 AssetDatabase를 새로고침 중이다.CreateGUI: 에디터가 업데이트 중이 아니라면 GUI를 생성한다.Update: 프레임당 한 번 호되어 스크립트의 로직을 업데이트 한다.OnGUI: GUI 이벤트를 렌더링하고 핸들링하기 위해 ..
2024.10.25
[Unity] TransformDirection()
TransformDirection()Transform.TransformDirection은 local space의 `direction`을 world space의 direction으로 변환한다. 해당 연산은 scale이나 position에 영향을 받지는 않는다. 반환된 벡터의 길이는 `direction`과 같다.  그러나 해당 공식 문서의 설명만으로는 헷갈리는 감이 있어, 아래에 첨부한 참고자료를 살펴보고, 직접 사용해보며 내린 결론을 정리해서 다음과 같이 부연 설명을 덧붙인다. `TransformDirection()`함수를 사용할 때는 인자로 넘겨준 direction을 로컬 좌표계로 취급하는데, 이는 TransformDirection()을 호출한 gameobject의 로컬 좌표계를 기준으로 잡는다.Vect..
2024.10.09
no image
[C#] 제너릭 메소드
제너릭 메소드제너릭 메소드는 이처럼 형식 매개 변수를 사용하여 선언된 메소드이다.static void Swap(T lhs, ref T rhs){ T temp; temp = lhs; lhs = rhs; rhs = temp;}위처럼 선언을 하지않고, 메소드 이름 옆에 를 제거하면 오류가 발생하는 것을 볼 수 있다. 사실 가 없어도 바로 쓸 수 있을 것이라 생각하였는데, 그렇지 않았다. 형식 인수 int를 사용하여 제너릭 메소드를 사용하는 법static void Swap(ref T lhs, ref T rhs){ T temp; temp = lhs; lhs = rhs; rhs = temp;}static void Main(string[] args){ int a = 1..
2024.10.06
C#