<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dev_hang.log</title>
        <link>https://velog.io/</link>
        <description>C# 게임 개발자</description>
        <lastBuildDate>Wed, 21 Jan 2026 11:57:27 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. dev_hang.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dev_hang" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Design Patterns] 디자인 패턴]]></title>
            <link>https://velog.io/@dev_hang/Design-Patterns-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@dev_hang/Design-Patterns-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Wed, 21 Jan 2026 11:57:27 GMT</pubDate>
            <description><![CDATA[<h1 id="싱글턴-패턴singleton-pattern">싱글턴 패턴(Singleton Pattern)</h1>
<p>: 클래스를 하나의 인스턴스로만 존재하도록 만드는 패턴</p>
<ul>
<li><p>하나만 존재(유일성)할 수 있는 클래스 -&gt; 다른 클래스와 혼동할 가능성 적음, 편리하게 접근 가능</p>
</li>
<li><p>원하는 시점에 생성 -&gt; 유연한 초기화</p>
</li>
<li><p>MonoBehaviour를 상속받을 수 있다 -&gt; 다양한 C# 기능활용</p>
</li>
<li><p>객체로써 존재 가능 -&gt; 객체 지향의 디자인 패턴</p>
</li>
<li><p>단 하나의 인스턴스(객체)만 생성되도록 강제하고, 어디서든 그 객체에 쉽게 접근할 수 있게 만든 패턴</p>
</li>
<li><p>게임 전체를 관장하는 시스템에 주로 사용</p>
</li>
<li><p>(주로 관리자(Manager)역할을 하는 스크립트에 사용)
```csharp
단순한 싱글톤
public class SimpleSingleton : MonoBehaviour
{
  public static SimpleSignleton Instance {get; private set;}
  -&gt; static 기반의 Instance<br>  void Awake()
  {</p>
<pre><code>  Instance = this;
  -&gt; 필요할 때 Instance에 this 할당</code></pre><p>  }
}</p>
</li>
<li><blockquote>
<p>유일성이 보장된거는 아닌 단순한 static 기반의 싱글톤 생성</p>
</blockquote>
<pre><code>```csharp
일반적인 싱글톤
public class BasicSingleton : MonoBehaviour
{
   private static BasicSingleton instance;
   public static BasicSingleton Instance
   {
       get =&gt; instance;
   }

   void Awake()
   {
       if(instance == null)
       {
           instance = this; -&gt; 싱글턴 인스턴스 할당
           DontDestoryOnLoad(gameObject); -&gt; 씬 전환되도 파괴되지 않도록 설정
       }
       else
       {
           Destroy(gameObject); -&gt; 중복 방지
       }
   }
}</code></pre><pre><code class="language-csharp">오브젝트가 아예 없을경우의 싱글톤
public class BasicSingleton : MonoBehaviour
{
   private static BasicSingleton instance;
   public static BasicSingleton Instance
   {
       get
       {
           if(instance == null) 
           {
               var obj FindFirstObjectByType&lt;BasicSingleton&gt;();
               -&gt; 씬 상에서 오브젝트 찾기
               if (obj != null) -&gt; 씬 상에서 오브젝트 찾음
                   instance = obj; -&gt; 오브젝트 할당
               else -&gt; 씬 상에서 오브젝트를 찾지 못했으면 직접 만들어서 연결
               {
                   var newObj = new GameObject(&quot;Basic Singleton&quot;);
                   -&gt; 오브젝트 생성
                   newObj.AddComponent&lt;BasicSingleton&gt;();
                   -&gt;컴포넌트 생성
                   instance = newObj.GetComponent&lt;BasicSingleton&gt;();
                   -&gt; 컴포넌트 할당
               }
           }

           return instance
       }
   }

   void Awake()
   {
       if(instance == null)
       {
           instance = this; -&gt; 싱글턴 인스턴스 할당
           DontDestoryOnLoad(gameObject); -&gt; 씬 전환되도 파괴되지 않도록 설정
       }
       else
       {
           Destroy(gameObject); -&gt; 중복 방지
       }
   }
}</code></pre>
<h3 id="제너릭-싱글톤">제너릭 싱글톤</h3>
<p>: 싱글톤 제조기를 하나 만들어 두고, 다른 클래스들이 이 틀을 상속받기만 하면 자동으로 싱글톤이 되도록 만든 기법</p>
<pre><code class="language-csharp">Generic&lt;T&gt;를 활용한 Singleton
어떤 타입이던지 싱글톤을 생성 가능
public class SingletonCore&lt;T&gt; : MonoBehaviour where T : MonoBehaviour
{
   private static T instance;
   public static T Instance
   {
       get
       {
           if(instance == null) 
           {
               instance == FindFirstObjectByType&lt;T&gt;();

               if (instance == null)
               {
                   var newObj = new GameObject(typeof(T).ToString());
                   instance = newObj.AddComponent&lt;T&gt;;
               }

           }

           return instance
       }
   }

   protected virtual void Awake() -&gt; 이 싱글톤이 Awake문을 사용할 수 도 있으니 선택적으로 오버라이드할 수 있게 생성
   {
       if(instance == null)
       {
           instance = this as T; -&gt; 싱글턴 인스턴스 할당
           DontDestoryOnLoad(gameObject); -&gt; 씬 전환되도 파괴되지 않도록 설정
       }
       else
       {
           Destroy(gameObject); -&gt; 중복 방지
       }
   }
}</code></pre>
<pre><code class="language-csharp">해당 클래스를 싱글톤화
public class BasicClass : SingletonCore&lt;BasicClass&gt; -&gt; 싱글톤코어를 상속 &lt;원하는타입&gt;
{
   public int level;

   public void LevelUp()
   {
       level++;
   }
   //만약 Awake를 사용한다면 base.Awake()를 불러준다.
   public void override void Awake()
   {
       base.Awake(); //부모의 싱글톤 설정 기능을 실행
       level = 1;
   }
}</code></pre>
</li>
</ul>
<h1 id="전략-패턴-strategy-pattern">전략 패턴 (Strategy Pattern)</h1>
<p>: 동작을 캡슐화하여 런타임에 알고리즘을 쉽게 교체하는 패턴</p>
<ol>
<li>인터페이스 정의</li>
<li>전략 구현</li>
<li>컨텍스트(사용자) 설정</li>
</ol>
<p>1.인터페이스 정의</p>
<pre><code class="language-csharp">이동 기능에 대한 인터페이스
public interface IMove
{
    void Move(Transform transform);
}</code></pre>
<p>2.전략구현</p>
<pre><code class="language-csharp">달리는 이동 기능
public class MoveRun : IMove
{
    private float speed;

    public MoveRun(float speed)
    {
        this.speed = speed;
    }

    public void Move(Transform transform)
    {

    }
}</code></pre>
<pre><code class="language-csharp">날아서 이동 기능
public class MoveFly : IMove
{
    private float speed;

    public MoveRun(float speed)
    {
        this.speed = speed;
    }

    public void Move(Transform transform)
    {

    }
}</code></pre>
<pre><code class="language-csharp">수영해서 이동 기능
public class MoveSwim : IMove
{
    private float speed;

    public MoveRun(float speed)
    {
        this.speed = speed;
    }

    public void Move(Transform transform)
    {

    }
}</code></pre>
<ol start="3">
<li><p>컨텍스트(사용자)설정</p>
<pre><code class="language-csharp">이동하는 대상
public class Mover : MonoBehaviour
{
 private IMove move;

 void Start()
 {
     move = new MoveRun(3f);
 }

 void Update()
 {
     move.Move(transform); -&gt; start에 transform 주입 시, 생성자 주입 방식이 된다.(너는 평생 이 Transform만 움직여) 

     if(Input.GetKeyDown(KeyCode.Shift)
     {
         move = new MoveRun(3f);
     }
     else if(Input.GetKeyDown(KeyCode.Space)
     {
         move = new MoveFly(7f);
     }
     else if(Input.GetKeyDown(KeyCode.Tap)
     {
         move = new MoveSwim(2f);
     }
 }
}</code></pre>
<h1 id="오브젝트-풀-패턴-object-pool-pattern">오브젝트 풀 패턴 (Object Pool Pattern)</h1>
<p>: 오브젝트를 미리 생성하여 Pool에 저장해두고, 재사용하는 패턴</p>
</li>
</ol>
<ul>
<li>일반적으로 queue, stack 사용</li>
<li>최적화</li>
</ul>
<pre><code class="language-csharp">public class StudyObjectPool : MonoBehaviour
{
    public Queue&lt;GameObject&gt; objQueue = new Queue&lt;GameObject&gt;();

    public GameObject objPrefab;
    -&gt; 풀을 채워 넣을 원본(ex 총알, 몬스터 등)
    public Transform parent;
    -&gt; 생성된 오브젝트들을 깔끔하게 정리하기 위한 폴더 역할의 부모 트랜스폼

    void Start()
    {
        CreateObject(50);
        -&gt; 시작하자마자 50개 미리 생성
    }

    private void CreateObject(int amount)
    {
        for (int i = 0 ; i &lt; amount ; i++)
        {
            GameObject obj = Instantiate(objPrefab, parent);
            -&gt; 부모 밑에 오브젝트 생성
            EnqueueObject(obj);
            -&gt; 생성 후 창고queue에 넣기
        }
    }

    private void EnqueueObject(GameObject newObj) -&gt; 재활용
    {
        Rigidbody rb = newObj.GetComponent&lt;Rigidbody&gt;();

        rb.lineraVelocity = Vector3.zero;
        rb.angularVelocity = Vector3.zero;
        -&gt; 물리적 힘 초기화
        //총알이 발사되기 이전, 상호작용 된것을 초기화

        newObj.SetActive(false);
        -&gt; 비활성화
        obj.Queue.Enqueue(newObj);
        -&gt; 창고에 넣기
    }

    public GameObject DequeueObject() -&gt; 총알을 발사할 때, DequeueObject 호출을 통해 풀에서 꺼내 쓴다.
    {
        if(objQueue.Count &lt; 3) -&gt; 자동확장 로직 //준비해둔 50개를 쓰고 3개밖에 안남았을때 불안하기 때문에 즉시 50개 생성
            CreateObject(50);

        GameObject obj = objQueue.Dequeue();
        -&gt;창고에서 꺼내기
        obj.SetActive(true);
        -&gt; 활성화

        return obj; -&gt; 배달
    }

}</code></pre>
<pre><code class="language-csharp">public class PoolController : MonoBehaviour
{
    public StudyObjectPool pool;
    public Transform shootPoint;

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            GameObject bullet = pool.DequeueObject();
            -&gt; 풀에서 꺼낸다.(기존의 Instantiate 대체)
            bullet.transform.position = shootPoint.position;
            //총알 발사 기능
        }
    }
}</code></pre>
<pre><code class="language-csharp">public class Bullet : MonoBehaviour
{
    public StudyObjectPool pool;

    void OnEnable()
    {
        Invoke(&quot;ReturnPool&quot;,10f);
        -&gt; 10초 후 해당 오브젝트를 queue에 저장
    }
    private void ReturnPool()
    {
        pool.EnqueueObject(gameObject);
        -&gt; 오브젝트를 queue에 저장
    }
}</code></pre>
<h3 id="유니티에-내장된-pool-기능">유니티에 내장된 Pool 기능</h3>
<pre><code class="language-csharp">using UnityEngine.Pool;

public class UnityPoolManager : MonoBehaviour
{
    public ObjectPool&lt;GameObject&gt; pool;
    public GameObject prefab;

    void Awake()
    {
        pool = new ObjectPool&lt;GameObject&gt;(CreateObject, GetObject, ReleaseObject);
    }

    private GameObject CreateObject()
    {
        GameObject obj = Instantiate(prefab);

        return obj;
    }

    private void GetObject(GameObject obj)
    {
        obj.SetActive(true);
    }

    private void ReleaseObject(GameObject obj)
    {
        obj.SetActive(false);
    }
}</code></pre>
<pre><code class="language-csharp">public class PoolController : MonoBehaviour
{
    public UnityPoolManager poolManager;
    public Transform shootPoint;

    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            GameObject bullet = poolManager.pool.Get(); -&gt; pool.Get()을 통해 GetObject()실행, 재고가 없을시 Create하고 Getobject 실행
            bullet.transform.position = shootPoint.position;
        }
    }
}</code></pre>
<pre><code class="language-csharp">-&gt; 유니티 풀 내부 함수 pool.Get() 이해하기 쉽게 하기 위한 함수 예시
public GameObject Get()
{
    GameObject item;

    // 1. 재고 확인
    if (재고가_없으면)
    {
        // 이때만 CreateObject가 호출
        item = CreateObject(); 
    }
    else
    {
        // 재고가 있으면 그냥 꺼냅니다.
        item = 창고.꺼내기();
    }

    // 2. 나가기 전에 활성화 (이건 항상 실행됨)
    GetObject(item);

    return item;
}</code></pre>
<pre><code class="language-csharp">public class Bullet : MonoBehaviour
{
    public UnityPoolManager poolManager;

    void OnEnable()
    {
        Invoke(&quot;ReturnPool&quot;, 10f);
    }

    private void ReturnPool()
    {
        poolManager.pool.Release(gameObject);
    }
}</code></pre>
<h1 id="팩토리-패턴-factory-pattern">팩토리 패턴 (Factory Pattern)</h1>
<p>: 객체 생성을 별도의 클래스(팩토리)에게 위임하고 객체 생성 로직을 캡슐화하여 유연성을 높이는 패턴</p>
<ul>
<li>다양한 오브젝트, 객체를 복잡하게 생성하지 않고 위임하여 유연성을 높임</li>
<li>상속 구조, 상속 구조가 애매할때는 인터페이스를 주로 사용(IFactory)</li>
</ul>
<ol>
<li>몬스터의 기본 설계도 (상속)
```csharp</li>
</ol>
<p>-&gt; 추상 클래스 : 몬스터 뼈대, 몬스터가 가져야 할 기능들
public abstract class MonsterCore
{
    public abstract string Name {get;}
    public abstract void Attack();
}</p>
<pre><code>2. 구체적인 몬스터 종류
```csharp
public class Slime : MonsterCore
{
    public override string Name =&gt; &quot;슬라임&quot;;
    public override void Attack() =&gt; Debug.Log(&quot;슬라임공격&quot;);
}</code></pre><pre><code class="language-csharp">public class Orc : MonsterCore
{
    public override string Name =&gt; &quot;오크&quot;;
    public override void Attack() =&gt; Debug.Log(&quot;오크공격&quot;);
}</code></pre>
<pre><code class="language-csharp">public class Dragon : MonsterCore
{
    public override string Name =&gt; &quot;드래곤&quot;;
    public override void Attack() =&gt; Debug.Log(&quot;드래곤 공격&quot;);
}</code></pre>
<ol start="3">
<li><p>공장의 기본 설계도</p>
<pre><code class="language-csharp">public abstract class MonsterFactory : MonoBehaviour -&gt; 최상위 팩토리
{
 public MonsterCore Spawn(string type)
 {
     MonsterCore monster = CreateMonster(type); -&gt; 추상함수랑 연결되어 있음(구체적인 생성은 자식에게 미룸)
     Debug.Log($&quot;{monster.Name}생성&quot;);

     return monster;
 }

 protected abstract MonsterCore CreateMonster(string type);
 -&gt; 타입에 따라 어떻게 만들지 자식에서 정해라
}</code></pre>
<pre><code class="language-csharp">public class ForestSpawner : MonsterFactory
{
 protected override MonsterCore CreateMonster(string type) -&gt; 오버라이드 재정의
 {
     MonsterCore monster = null;
     switch(type)
     {
         case : &quot;Slime&quot;
             monster = new Slime();
             break;
         case : &quot;Orc&quot;
             monster = new Orc();
             break;
     }

     return monster; -&gt; 만든 몬스터 반환
 }

 IEnumerator Start() -&gt; 1초마다 랜덤하게 몬스터 생성
 {
     while(true)
     {
         int ranIndex = Random.Range(0,2);

         string monsterType = ranIndex == 0 ? &quot;Slime&quot; : &quot;Orc&quot;;
         Spawn(monsterType);

         yield return new WaitForSeconds(1f);
     }
 }
}</code></pre>
</li>
</ol>
<h1 id="명령-패턴-command-pattern">명령 패턴 (Command Pattern)</h1>
<p>: 명령을 객체로 만들어 캡슐화 하는 것</p>
<ul>
<li>인터페이스 or 상속</li>
</ul>
<h1 id="상태-패턴-state-pattern">상태 패턴 (State Pattern)</h1>
<h1 id="이벤트-버스-패턴-event-bus-pattern">이벤트 버스 패턴 (Event Bus Pattern)</h1>
<h1 id="옵저버-패턴-observer-pattern">옵저버 패턴 (Observer Pattern)</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[[UnityC#] 객체 지향 프로그래밍]]></title>
            <link>https://velog.io/@dev_hang/UnityC-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</link>
            <guid>https://velog.io/@dev_hang/UnityC-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</guid>
            <pubDate>Sun, 11 Jan 2026 11:57:01 GMT</pubDate>
            <description><![CDATA[<h1 id="객체지향-프로그래밍">객체지향 프로그래밍</h1>
<p>: 현실 세계를 모형으로 모든 것을 객체로 표현하는 프로그래밍 방식
<br></p>
<p>객체</p>
<ul>
<li>속성과 기능을 가진 실체를 가진 대상</li>
<li>유니티에서 GameObject + Component로 객체를 구성<h2 id="객체-지향-프로그래밍의-특성">객체 지향 프로그래밍의 특성</h2>
</li>
<li>추상화 : 핵심 정보만 공개 (설계의 단순화)</li>
<li>상속 : 코드 재사용, 부모 기능 물려받기 (코드간결,유지보수 용이)</li>
<li>다형성 : 같은 함수, 다양한 동작 실행 (유연한 설계)</li>
<li>캡슐화 : 내부 정보 은닉, 접근 통제 (보안성과 안정성)</li>
</ul>
<h2 id="오버로딩overloading">오버로딩(Overloading)</h2>
<p>: 동일한 함수명의 매개변수를 다르게 설정해서 다른 기능을 구현하는 방법(다형성, 유연성)</p>
<pre><code class="language-csharp">    매개변수 타입만 다른 함수 3종

    public void Method(int a){}
    public void Method(float a){}
    public void Method(string a){}

    하나로 모든 타입을 받을 수 있는 제너릭을 활용한 함수

    public void Method&lt;T&gt;(T a){}

    함수명은 같지만 매개변수가 달라 다른 함수가 된다.

    private void TargetMovement(Transform target)
    {
        //target이 앞으로 이동하는 기능
    }
    private void TargetMovement(Transform target, Transform destination)
    {
        //target이 목적지를 향해 이동하는 기능
    }
    private void TargetMovement(Transform target, Transform destination, float speed)
    {
        //target이 목적지를 향해 speed의 속도를 가지고 이동하는 기능
    }</code></pre>
<h2 id="캡슐화encapsulation">캡슐화(Encapsulation)</h2>
<p>: 외부에서 직접 접근하는 것을 제한하여 데이터 무결성을 보장하는 방법
-&gt; 속성과 함수를 하나의 클래스로 묶고, 접근을 제한하여 은닉성 부여</p>
<h3 id="접근-제한자">접근 제한자</h3>
<ul>
<li>public : 모든 외부 접근 허용 (외부 접근 허용 필드, 메서드)</li>
<li>private : 클래스 내부에서만 접근 가능 (내부 필드, 내부 로직 전용)</li>
<li>protected : 상속받은 클래스까지 접근 가능 (자식 클래스에게만 접근 허용)</li>
</ul>
<pre><code class="language-csharp">public int number; -&gt; 외부 클래스 접근 O, 유니티 접근 O
private int number; -&gt; 외부 클래스 접근 X, 유니티 접근 X -&gt; 내부에서만 접근 가능
protected int number; -&gt; 외부 클래스 접근 X, 유니티 접근 X -&gt; 내부와 자식 클래스에서만 접근 가능

//[] 애티르뷰트 Attribute -&gt; 코드에 대한 부가 정보를 기록하고 읽을 수 있는 기능(컴퓨터가 읽는 주석)
[HideInInspector] public int number; -&gt; 외부 클래스 접근 O, 유니티 접근 X -&gt; 인스펙터에서 수정을 방지
[SerializeField] private int number; -&gt; 외부 클래스 접근 X, 유니티 접근 O
[SerializeField] protected int number; -&gt; 외부 클래스 접근 X, 유니티 접근 O -&gt; 내부와 자식 클래스 접근 O
[field:SerializeField] public int number{get; set;} -&gt; 프로퍼티를 인스펙터에서 보여주는 기능</code></pre>
<pre><code class="language-csharp">[System.Serializable]
public class Example
{
    public int num1;
    public int num2;
    private int num3;
}

public class Test : MonoBehaviour
{
    public Example example = new Example();
}</code></pre>
<pre><code>-&gt; [System.Serializable]을 사용함으로써 Test스크립트를 사용하는 오브젝트는 num1,num2가 인스펙터에서 보여진다</code></pre><h4 id="프로퍼티property--캡슐화한-데이터접근자-설정자-메소드를-축약">프로퍼티(Property) : 캡슐화한 데이터(접근자, 설정자 메소드를 축약)</h4>
<pre><code class="language-csharp">public class Example
{
    int num = 10;
    public int Num
    {
        get { return num; }
        set { num = value; } == public void SetNum(int value){num = value;} 컴파일러가 자동으로 매개변수 인식
    }
}

public class Example 
{
    public int Num {get;set;} -&gt; 자동 구현 프로퍼티 : 프로퍼티를 더 축약
}

public class Example -&gt; 프로퍼티를 인스펙터 창에서 보여주도록 설정
{
    [field:SerializeField]
    public int Num {get;set;}
}</code></pre>
<h3 id="직렬화-serialization">직렬화 (Serialization)</h3>
<p>: 데이터를 byte 배열로 변환하는 작업(데이터를 직선으로 바꾸는 기능)
-&gt; 게임저장 / 네트워크 연결 시 이용
-&gt; public : 내부적으로 직렬화 과정을 거쳐서 유니티 에디터에서 보이도록 설정한 접근 제한자
-&gt; 인스펙터 창 : 게임 오브젝트의 컴포넌트 필드 값을 확인하거난 변경하면 Unity 에디터가 해당 데이터를 직렬화한 후 인스펙터창에 표시</p>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/979e476e-9e3e-48fb-89de-1c3a6ad57d6a/image.png" alt=""></p>
<h3 id="역직렬화-deserialize">역직렬화 (Deserialize)</h3>
<p>: byte 배열을 데이터로 변환하는 작업(직선 데이터를 원래대로 바꾸는 기능)</p>
<h2 id="상속-inheritance">상속 (Inheritance)</h2>
<p>: 부모 클래스를 자식 클래스가 물려 받아, 부모 클래스의 속성과 기능을 쓸 수 있는 방법
-&gt; 기존 코드 재사용 용이, 확장도 가능</p>
<ul>
<li>상속받은 변수는 그대로 사용 가능</li>
</ul>
<pre><code class="language-csharp">class Monster
{
    //이동 기능
    //공격 기능
    //사망 기능
}

class Orc : Monster
{
    //오크 스킬 기능
    //오크 고유 기능
}

class Zombie : Monster
{
    //좀비 고유 기능
}

class OrcArcher : Orc
{
    //오크궁수 고유 스킬 (활쏘기)
    //오크궁수 고유 기능
}
Monster &lt;- Orc &lt;- OrcArcher</code></pre>
<h3 id="다형성-polymorphism">다형성 (Polymorphism)</h3>
<p>: 다른 형태여도 같은 타입이라면 제어가능 -&gt; 유연한 설계 가능</p>
<pre><code class="language-csharp">public class Character
{
    public float hp;
    public float damage;

    public virtual void Move(){}
    public virtual void Attack(){}   
}

public class Player : Character
{
    public override void Move()
    {
        Debug.Log(&quot;플레이어 이동&quot;);
    }
    public override void Attack()
    {
        Debug.Log(&quot;플레이어 공격&quot;);
    }
}</code></pre>
<h3 id="virtual-abstract-override">Virtual, Abstract, Override</h3>
<p>: 상속받은 함수를 변경하는 기능</p>
<h4 id="virtual---override">Virtual - Override</h4>
<ul>
<li>부모 클래스에서 virtual 사용 시, 자식 클래스에서 선택적 재정의(override) 가능</li>
<li>base 키워드를 활용하여 기존 기능 + 추가 기능 구현 -&gt; 기능 유연성</li>
<li>기능 확장</li>
</ul>
<pre><code class="language-csharp">public class Monster : MonoBehaviour
{
    public virtual void Attack(){}
    public virtual void Shout(){}
}

public class Goblin : Monster
{
    public override void Attack()
    {
        base.Attack();
        // + 독 데미지 추가 기능
    }
    public override void Shout()
    {
        //shout 기능
    }
}

public class OrcMonster
{
    public override void Attack()
    {
        base.Attack();
        // + 범위 공격 추가 기능
    }
    public override void Shout()
    {
        //shout 기능
    }
}</code></pre>
<h4 id="abstract---override-추상-메소드">Abstract - Override (추상 메소드)</h4>
<ul>
<li>부모 클래스에서 abstract 사용 시, 자식 클래스에서 필수적 재정의(override)</li>
<li>부모 클래스에서 기능 구현 불가 -&gt; base 키워드 사용 불가</li>
<li>구조 설계, 기능 확장</li>
</ul>
<pre><code class="language-csharp">public class Monster : MonoBehaviour
{
    public abstract void Attack(); -&gt; 구현 불가
    public abstract void Shout();
}

public class Goblin : Monster
{
    public override void Attack()
    {
        //독 데미지 공격 기능
    }
    public override void Shout()
    {
        //shout 기능
    }
}

public class OrcMonster
{
    public override void Attack()
    {
        base.Attack();
        //범위 공격 기능
    }
    public override void Shout()
    {
        //shout 기능
    }
}</code></pre>
<h3 id="다중-상속">다중 상속</h3>
<p>: 부모 클래스를 여러개 상속받는 것</p>
<pre><code class="language-csharp">public class Monster
{
    public virtual void Attack(){}
}

public class Orc : Monster
{
    public override void Attack(){}
}
public class Ogre : Monster
{
    public override void Attack(){}
}

public class CheifOrc : Orc, Ogre --&gt; 오류 발생
{
    public override void Attack(){}
}
</code></pre>
<ul>
<li>죽음의 다이아몬드 구조
: 하나의 부모 클래스를 두개의 자식 클래스가 상속받고 다시 하나의 자식 클래스가 상속받는 것
<img src="https://velog.velcdn.com/images/dev_hang/post/f0c93ffb-7c8d-4a95-90dc-ccb8fa2a2aaa/image.png" alt=""></li>
</ul>
<h2 id="인터페이스-interface">인터페이스 (Interface)</h2>
<p>: 프로그래밍상 계약 혹은 약속으로 정의(구현해야 하는 기능, 추가 기능, 다형성)</p>
<ul>
<li>추상 클래스로 대체 가능</li>
<li>I붙이고 이름 ex) IAttack, IRun, IMove</li>
<li>인터페이스는 클래스가 아니라 다중 상속 기능이 가능</li>
<li>인스턴스 생성 불가</li>
</ul>
<pre><code class="language-csharp">public interface IAttack
{
    public void Attack();
}
public interface IMove
{
    public void Move();
}

public class Orc : IAttack, IMove -&gt; 다중 상속 가능
{
    public void Attack()
    {
        Debug.Log(&quot;Orc Attack&quot;);
    }

    public void Move()
    {
        //움직이는 기능
    }
}

public interface IDamageable
{
    int Hp {get; set;}

    void TakeDamage(int dmg);
    void Death();
}

public class Tree
{
    //파괴 불가능한 오브젝트
}

//파괴 가능한 오브젝트들
public class Wall : IDamageable
{
    public void TakeDamage(int amount){}
    public void Death(){}
}
public class Car : IDamageable
{
    public void TakeDamage(int amount){}
    public void Death(){}
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity C#] 프로그래밍 기초]]></title>
            <link>https://velog.io/@dev_hang/Unity-C-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@dev_hang/Unity-C-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Wed, 31 Dec 2025 06:10:19 GMT</pubDate>
            <description><![CDATA[<h1 id="유니티-함수">유니티 함수</h1>
<h2 id="unity-script-생명주기">Unity Script 생명주기</h2>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/21fc22b9-4bea-4f9f-bb18-6175019bd40c/image.png" alt="">
<img src="https://velog.velcdn.com/images/dev_hang/post/22f5f185-86c7-4420-99ef-a97844a3b503/image.png" alt=""></p>
<h2 id="시작함수">시작함수</h2>
<h4 id="void-awake">void Awake()</h4>
<p>: 가장 먼저 1번 실행되는 함수</p>
<h4 id="void-onenable">void OnEnable()</h4>
<p>: 오브젝트가 on될 때마다 1번 실행되는 함수</p>
<h4 id="void-start">void Start()</h4>
<p>: 1번 실행되는 함수</p>
<h4 id="void-ondisable">void OnDisable()</h4>
<p>: 오브젝트가 off될 때마다 1번 실행되는 함수</p>
<h4 id="void-ondestroy">void OnDestroy()</h4>
<p>: 오브젝트가 파괴될때 1번 실행되는 함수</p>
<h4 id="void-fixedupdate">void FixedUpdate()</h4>
<p>: 고정된 프레임마다 계속 실행</p>
<h4 id="void-update">void Update()</h4>
<p>: 컴퓨터 성능에 따라 계속 실행</p>
<h4 id="void-lateupdate">void LateUpdate()</h4>
<p>: Update 다음에 실행</p>
<br>


<h2 id="physics-함수">physics 함수</h2>
<br>


<h3 id="oncollision-이벤트">OnCollision 이벤트</h3>
<h4 id="void-oncollisionentercollision-collision">void OnCollisionEnter(Collision collision)</h4>
<p>: 두 오브젝트가 충돌했을 때 1번 호출</p>
<h4 id="void-oncollisionstaycollision-collision">void OnCollisionStay(Collision collision)</h4>
<p>: 두 오브젝트가 충돌 상태를 유지하는 동안 호출</p>
<h4 id="void-oncollisionexitcollision-collision">void OnCollisionExit(Collision collision)</h4>
<p>: 두 오브젝트가 충돌 상태에서 벗어났을 때 호출
<br></p>
<h3 id="ontrigger-이벤트">OnTrigger 이벤트</h3>
<h4 id="void-ontriggerentercollider-other">void OnTriggerEnter(Collider other)</h4>
<p>: Collider 영역에 들어갔을 때 1번 호출</p>
<h4 id="void-ontriggerstaycollider-other">void OnTriggerStay(Collider other)</h4>
<p>: Collider 영역에 들어간 상태를 유지하는 동안 호출</p>
<h4 id="void-ontriggerexitcollider-other">void OnTriggerExit(Collider other)</h4>
<p>: Collider 영역을 벗어났을 때 1번 호출</p>
<br>
<br>

<h3 id="oncollision과-ontrigger의-차이점">OnCollision과 OnTrigger의 차이점</h3>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/3db2d939-aeea-4b9f-8733-85c8a55f2276/image.png" alt=""></p>
<h2 id="input-event-함수">Input Event 함수</h2>
<h3 id="마우스-이벤트-함수">마우스 이벤트 함수</h3>
<h4 id="void-onmousedown">void OnMouseDown()</h4>
<p>: 마우스로 누를 때 1번 실행</p>
<h4 id="void-onmouseup">void OnMouseUp()</h4>
<p>: 마우스로 뗄 때 1번 실행</p>
<h4 id="void-onmouseenter">void OnMouseEnter()</h4>
<p>: 마우스 포인터가 진힙했을 때 1번</p>
<h4 id="void-onmouseexit">void OnMouseExit()</h4>
<p>: 마우스로 포인터가 빠져나갔을 때 1번</p>
<h4 id="void-onmouseover">void OnMouseOver()</h4>
<p>: 마우스 오브젝트 위에 있을 때 계속 실행</p>
<h4 id="void-onmousedrag">void OnMouseDrag()</h4>
<p>: 마우스를 누른 상태로 있을 때 계속 실행</p>
<h4 id="void-onmouseupasbutton">void OnMouseUpAsButton()</h4>
<p>: 오브젝트 범위 내에서 마우스를 뗀 경우 1번 실행</p>
<h3 id="키보드-이벤트-함수inputevent-함수-x프레임-상태에서-조회하는-polling방식">키보드 이벤트 함수(InputEvent 함수 X,프레임 상태에서 조회하는 Polling방식)</h3>
<h4 id="inputgetkeykeycode-key">Input.Getkey(KeyCode key)</h4>
<p>: 키를 누르고 있는 동안 계속 실행</p>
<h4 id="inputgetkeydownkeycode-key">Input.GetKeyDown(KeyCode key)</h4>
<p>: 키를 누른 순간 1번 실행</p>
<h4 id="inputgetkeyupkeycode-key">Input.GetKeyUp(KeyCode key)</h4>
<p>: 키를 뗀 순간 1번 실행</p>
<h4 id="inputgetaxishorizontal-or-vertical">Input.GetAxis(&quot;Horizontal&quot; or &quot;Vertical&quot;)</h4>
<p>: 입력값을 -1~1값으로 변환</p>
<h4 id="inputgetaxisrawhorizontal-or-vertical">Input.GetAxisRaw(&quot;Horizontal&quot; or &quot;Vertical&quot;)</h4>
<p>: 보정 없는 즉기 값 변환 (-1.0.1)</p>
<h4 id="inputanykey-ifinputanykey">Input.anyKey (if(Input.anyKey))</h4>
<p>: 아무 키나 눌렀을 때 true</p>
<h4 id="inputanykeydown-ifinputanykeydown">Input.anyKeyDown (if(Input.anyKeyDown))</h4>
<p>: 아무 키나 처음 눌렀을 때 1번
<br>
<br></p>
<h2 id="조건문">조건문</h2>
<p>: 조건의 결과를 보고 실행되는 문법</p>
<h4 id="if-else-조건문">if-else 조건문</h4>
<pre><code class="language-csharp">if (조건 A){
    조건 A가 true
}
else if(조건 B){
    조건 B가 true
}
else{
    그 외의 경우
}</code></pre>
<h4 id="switch-조건문">Switch 조건문</h4>
<pre><code class="language-csharp">switch (변수)
{
    case a:
        break;
        //변수가 a일경우 실행
    case b:
        break;
        //변수가 b일경우 실행
    case c:
        break;
        //변수가 c일경우 실행
    default:
        break;
        //변수의 값이 위의 값 이외의 경우 실행
}</code></pre>
<h2 id="invoke-함수">Invoke 함수</h2>
<p>: 호출 함수</p>
<h4 id="invoke함수명-지연시간">Invoke(&quot;함수명&quot;, 지연시간)</h4>
<p>: 지연시간 후 함수 실행</p>
<h4 id="invokerepeating함수명-지연시간-반복주기">InvokeRepeating(&quot;함수명&quot;, 지연시간, 반복주기)</h4>
<p>: 지연시간 후 함수 실행 한 후 반복주기 마다 실행
ex) InvokeRepeating(&quot;함수명&quot;,3f, 2f) -&gt; 함수를 3초 후에 실행한 후 2초마다 반복 실행</p>
<h4 id="cancelinvoke함수명">CancelInvoke(&quot;함수명&quot;)</h4>
<p>: 호출한 Invoke함수 취소 (Invoke,InvokeRepeating으로 예약된 호출만 취소가능)</p>
<pre><code class="language-csharp">Invoke(&quot;함수명&quot;, 지연시간);
InvokeRepeating(&quot;함수명&quot;, 처음 지연시간, 반복주기);
CancelInvoke(&quot;함수명&quot;);</code></pre>
<h2 id="반복문-함수">반복문 함수</h2>
<p>: 조건에 만족하면 반복해서 실행되는 문법</p>
<h4 id="while-반복문">While 반복문</h4>
<p>: 조건이 성립되는 동안 반복</p>
<pre><code class="language-csharp">while (조건 A){
    조건 A가 true인 경우 실행
}</code></pre>
<h4 id="dowhile-반복문">do~while 반복문</h4>
<p>: do -&gt; while 조건 확인 -&gt; do -&gt; while 조건 확인 -&gt; do ...
: 조건에 맞지 않아도 do문은 한번 실행</p>
<pre><code class="language-csharp">do
{

}
while(조건 A)</code></pre>
<h4 id="for-반복문">for 반복문</h4>
<p>: 순차적으로 반복</p>
<pre><code class="language-csharp">for(변수 정의; 반복범위; 증감단위){

}

for( i = 1; i &lt; 3 ; i++){
    Debug.Log(i);
}</code></pre>
<h4 id="foreach-반복문">foreach 반복문</h4>
<p>: 배열이나 리스트를 하나씩 반복</p>
<pre><code class="language-csharp">foreach(데이터타입 변수 in Collection){

}

private string[] personNames = [&quot;철수&quot;,&quot;영희&quot;,&quot;영지&quot;];


foreach(var personName in personNames){
    Debug.Log(personName);
}</code></pre>
<pre><code class="language-log">철수
영희
영지</code></pre>
<h3 id="break-return-continue">break, return, continue</h3>
<p>break : 반복문을 빠져나오는 기능
return : 함수를 종료
continue : continue보다 아래 기능을 실행하지 않고 다시 반복문을 실행</p>
<h2 id="random">Random</h2>
<p>: Random.Range(int or float a, int or float b)
: a~b까지의 랜덤 숫자 뽑기</p>
<h2 id="코루틴coroutine">코루틴(Coroutine)</h2>
<p>(시작 시간과 끝나는 시간이 정해져있을때 사용, 느린판단을 할때)</p>
<pre><code class="language-csharp">yield return null; -&gt; 1프레임 대기 Update 호출까지 대기 후 실행
yield return new WaitForFixedUpdated(); -&gt; FixedUpdate 호출까지 대기 후 실행
yield return new WaitForSeconds(time); -&gt; tiem 만큼 대기 후 실행
yield return new WaitForSecondsRealtime(time); -&gt; Timescale에 영향 X, time 대기 후 실행
yield return new WaitForEndOffFrame(); -&gt; 모든 렌더링 작업이 완료될 때까지 대기 후 실행
yield return new WaitUntill(()=&gt;time &gt; 10); -&gt; 해당 조건이 true가 될때까지 대기 후 실행
yield break; -&gt; 코루틴 종료

//함수 호출 방법
void Start(){
    StartCoroutine(&quot;Routine&quot;);
    StartCoroutine(nameof(Routine));
    StartCoroutine(Routine());
    //매개변수 한개(함수 이름으로 실행할 경우)
    StartCoroutine(&quot;Routine1&quot;,4);
    //매개변수 여러개(함수 자체로 실행)
    StartCoroutine(Rotuine2(1,2,3));
}

//코루틴 생성 방법
IEnumerator Routine(){
    Debug.Log(&quot;Hello&quot;);
    yield return new WaitForSeconds(3f);
}

IEnumerator Routine1(int a){
    Debug.Log(&quot;a&quot;);
    yield return null;
}

IEnumerator Routine2(int a, int b, int c){
    Debug.Log(&quot;a&quot;);
    Debug.Log(&quot;b&quot;);
    Debug.Log(&quot;c&quot;);
    yield return null;
}</code></pre>
<pre><code class="language-csharp">//함수 종료 방법
private Coroutine runningCoroutine; -&gt; 반환값 Coroutine을 담을 맴버 변수 선언

void Start()
{
    runningCoroutine = StartCoroutine(Running());
    Invoke(&quot;StopRoutine&quot;, 1.5f);
}

IEnumerator Running()
{
    Debug.Log(&quot;실행 1&quot;);
    yield return new WaitForSeconds(1.0f);

    Debug.Log(&quot;실행 2&quot;);
    yield return new WaitForSeconds(1.0f);

    Debug.Log(&quot;실행 3&quot;);
    yield return new WaitForSeconds(1.0f);
}

private void StopRoutine()
{
    StopCoroutine(runningCoroutine); -&gt; StopCoroutine(Running())은 작동하지 않는다.
    Debug.Log(&quot;강제 종료&quot;);

    StopAllCoroutines(); // 클래스 내에서 실행되는 모든 Coroutine 정지
}</code></pre>
<h2 id="제너릭generic">제너릭(Generic)</h2>
<p>: 데이터 타입을 파라미터로 활용하는 변수</p>
<ul>
<li>코드 재사용성 용이</li>
<li>호출시 타입 결정되기 때문에 성능 저하 X</li>
</ul>
<pre><code class="language-csharp">public void Copy(int[] source, int[] target)
{
    for (int i = 0 ; i &lt; source.Length ; i++)
    {
        target[i] = source[i];
    }
}

public void Copy(float[] source, float[] target)
{
    for (int i = 0 ; i &lt; source.Length ; i++)
    {
        target[i] = source[i];
    }
}

public void Copy&lt;T&gt;(T[] source, T[] target) -&gt; 일반화(모든 자료형 사용 가능-&gt;호출 시 자료형 재정의)
{
    for (int i = 0 ; i &lt; source.Length ; i++)
    {
        target[i] = source[i];
    }
}

//오브젝트 풀 예시 문

public class ObjectPool&lt;T&gt; where T : Component -&gt; 제약 조건(T타입에 대한 조건 지정)
{
    private Queue&lt;T&gt; pool = new Queue&lt;T&gt;();
    private T prefab;

    public ObjectPool(T prefab, int initialCount)
    {
        this.prefab = prefab;
        for(int i = 0; i &lt;initialCount ; i++)
        {
            T obj = GameObject.Instantiate(prefab);
            obj.gameObject.SetActive(false);
            pool.Enqueu(obj);
        }
    }

    public T Get()
    {
        if(pool.Count &gt; 0)
        {
            var obj = pool.Dequeue();
            obj.gameObject.SetActive(true);
            return obj;
        }

        return GameObject.Instantiate(prefab);
    }

    public void Return(T obj)
    {
        obj.gameObject.SetActive(false);
        pool.Enqueue(obj);
    }
}</code></pre>
<h2 id="매개변수-활용--ref--out--params">매개변수 활용 : ref / out / params</h2>
<h3 id="일반-매개변수-call-by-value">일반 매개변수 (Call by Value)</h3>
<ul>
<li>기본값이며, 값 형식인 경우 복사본 전달</li>
<li>함수 내부에서 변경해도 원본은 변경되지 않는다.</li>
</ul>
<h3 id="ref-call-by-reference">ref (Call by Reference)</h3>
<ul>
<li>초기화된 변수만 전달 가능</li>
<li>함수 내부에서 변경 시 원본도 같이 변경</li>
</ul>
<pre><code class="language-csharp">public int num = 10;

void Start()
{
        NormalParameter(num);
        RefParameter(ref num);
}

public void NormalParameter(int n)
{
        Debug.Log(&quot;호출 전 : &quot; + n);
        n = 1;
        Debug.Log(&quot;호출 후 : &quot; + num);
}
public void RefParameter(ref int n)
{
        Debug.Log(&quot;호출 전 : &quot; + n);
        n = 1; 
        Debug.Log(&quot;호출 후 : &quot; + num);
}</code></pre>
<pre><code>호출 전 : 10
호출 후 : 10 -&gt; 원본이 변경 X

호출 전 : 10
호출 후 : 1 -&gt; ref는 원본이 변경되었다.</code></pre><h3 id="out-출력-전용-참조">Out (출력 전용 참조)</h3>
<ul>
<li>함수 내부에서 반드시 초기화해야한다.</li>
<li>초기화되지 않은 변수도 전달 가능</li>
<li>입력값은 무시, 출력용 목적으로 사용 </li>
</ul>
<pre><code class="language-csharp">public class OutParameter : MonoBehaviour
{
    void Start()
    {
        int a = Random.Range(1,100);
        int b = Random.Range(1,100);

        //Old 버전
        int result1 = 0;
        int result2 = 0;
           Divide(a,b,out result1,out result2);

        //Out 파라미터를 메소드를 호출할 때 선언 가능
        //현재 메소드가 호출되는 블록 내부에서 선언 이후 사용 가능
        Divide(a,b,out int result1, out int result2);

        // var 키워드 사용 가능
        // 메소드 정의에는 var를 사용할 수 없기 때문에 메소드 정의를 참고해서 자동 설정
        Divide(a, b, out var r1, out var r2);

        //메소드 정의는 2개의 out 파라미터를 사용하도록 되어 있지만 필요 없는 경우도 존재 가능 &#39;_&#39; 사용
        Divide(a,b,out var rr1, out _);

        Debug.Log($&quot;{a} / {b} = {result1}&quot;);
        Debug.Log($&quot;{a} / {b} = {result2}&quot;);

        Debug.Log($&quot;{a} / {b} = {r1}&quot;);
        Debug.Log($&quot;{a} / {b} = {r2}&quot;);

        Debug.Log($&quot;{a} / {b} = {rr1}&quot;);
    }

    void Divide(int num1, int num2,out int r1,out int r2)
    {
        r1 = num1 / num2; -&gt;몫
        r2 = num1 % num2; -&gt; 나머지
    }
}</code></pre>
<pre><code>5 / 2 = 2
5 % 2 = 1

5 / 2 = 2
5 % 2 = 1

5 / 2 = 2</code></pre><h3 id="params-가변-인자">Params (가변 인자)</h3>
<ul>
<li>매개변수의 개수를 가변적으로 받을 때 사용</li>
<li>배열로 전달(개수가 정해지지 않은 자료형의 데이터를 넘기게 된다.)</li>
<li>메서드 정의 시 마지막 인자에만 사용 가능</li>
</ul>
<pre><code class="language-csharp">void Like(int x, params string[] message)
{
    foreach (string s in message)
    {
        Debug.Log(s);
    }
}

void Start()
{
    int x = 3;
    Like(x, &quot;맑음&quot;,&quot;나쁨&quot;,&quot;바람&quot;);
}</code></pre>
<pre><code>3
맑음
나쁨
바람</code></pre><pre><code class="language-csharp">public int[] nums = {1,2,3,4,5};

void Start()
{
    ParamsParameter(1,2,3,4,5);
    ParamsParameter(10,20,30);
}

void ParmasParameter(params int[] numbers)
{
    string str = &quot;&quot;;
    foreach (var number in numbers)
    {
        str += num + &quot; &quot;;
    }
    Debug.Log(str);
}</code></pre>
<pre><code>1 2 3 4 5
10 20 30</code></pre><h2 id="클래스와-함수-커스텀--partial--sealed">클래스와 함수 커스텀 : Partial / Sealed</h2>
<h3 id="partial">Partial</h3>
<ul>
<li>분리 용도</li>
<li>하나의 클래스, 구조체, 인터페이스를 여러파일에 나누어 구현 가능</li>
<li>주로 Unity의 자동 생성 코드와 사용자 코드 분리, 대형 클래스 분할에 사용</li>
<li>실행시 하나로 합쳐져서 컴파일 진행 -&gt; 컴파일 단계</li>
<li>네임스페이스가 동일해야 함</li>
<li>모든 부분 정의에서 같은 접근 제한자 사용 ex) 하나의 partial 정의가 public이면 다른 정의도 public</li>
<li><blockquote>
<p>장점 : 가독성,협업,조직화</p>
</blockquote>
</li>
</ul>
<pre><code class="language-csharp">public partial class StudyPartial : MonoBehaviour
{
    void Start()
    {
        Debug.Log(&quot;Start method&quot;);
    }
}

public partial class StudyParital
{
    void Update()
    {
        Debug.Log(&quot;Update mehtod&quot;);
    }
}</code></pre>
<pre><code>Start method
Update method
Update method
Update method
Update method
...
-&gt; 2개의 파일이 컴파일 시 내용이 합쳐져서 하나의 클래스가된다.</code></pre><p>Sealed</p>
<ul>
<li>봉인 용도</li>
<li>클래스를 상속하지 못하도록 방지</li>
<li>함수를 override 못하도록 막을 수 있다</li>
<li>클래스 앞 -&gt; 더 이상 상속 불가</li>
<li>override된 메서드 앞 -&gt; 자식에서 override 불가</li>
</ul>
<pre><code class="language-csharp">public class BaseClass : MonoBehaviour
{
    public virtual void Method()
    {
        Debug.Log(&quot;일반 함수&quot;);
    }
}

public class MiddleClass : BaseClass
{
    public sealed override void Method()
    {
        Debug.Log(&quot;봉인된 오버라이드 함수&quot;);
    }
}

public class LastClass : MiddleClass
{
    public override void Method() --&gt; 함수가 봉인되었기 때문에 오류 발생(override 불가)
    {
        Debug.Log(&quot;오버라이드 함수&quot;);
    }
}</code></pre>
<h2 id="함수를-대신-실행하는-대리자--delegate">함수를 대신 실행하는 대리자 : Delegate</h2>
<h3 id="delegate">Delegate</h3>
<p>: 함수를 참조</p>
<ul>
<li>델리게이트 체인 (+= 등록, -= 제거)</li>
</ul>
<pre><code class="language-csharp">접근제한자 delegate 반환타입 이름(매개변수)
public delegate void MyDelegate();</code></pre>
<pre><code class="language-csharp">public class StudyDelegate : MonoBehaviour
{
    public delegate void MyDelegate();
    public MyDelegate onDelegate;

    void Start()
    {
        //onDelegate에 함수 할당
        onDelegate = MethodA;
        //MethodB 추가
        onDelegate += MethodB;
        //MethodC 추가
        onDelegate += MethodC;
        //MethodB 삭제
        onDelegate -= MethodB;

        //직접 실행
        onDelegate();
        //직접 실행과 동일한 방식
        //delegate.invoke -&gt; 함수 즉시 호출, monobehaviour.invoke -&gt; 지연 호출
        onDelegate.Invoke();
        //null 체크 방식
        OnDelegate?.Invoke();
    }
}

public class ParameterDelegate : MonoBehaviour
{
    public delegate void MyDelegate(int a = 10); -&gt; 매개변수가 있는 함수 연결(default값을 10으로 설정)
    public Mydelegate onDelegate;

    void Start()
    {
        onDelegate += MethodA; -&gt; 오류 발생
        onDelegate += MethodB;
    }

    private void MethodA(){} -&gt; 매개변수가 없는 함수
    private void MethodB(int b){} -&gt; 매개변수가 있는 함수
}</code></pre>
<h2 id="eventunityeventeventhandler-delegate-기반">event/UnityEvent/EventHandler (Delegate 기반)</h2>
<h3 id="event">event</h3>
<ul>
<li><p>구독/발행 이벤트 패턴 용도</p>
</li>
<li><p>외부 호출 방지 -&gt; 오직 선언된 클래스 내부에서만 Invoke 가능</p>
</li>
<li><p>+= -=로 구독 -&gt; &#39;=&#39;를 사용해서 외부에서 새롭게 할당 방지</p>
</li>
<li><p>(delegate를 외부에서 함부로 호출하거나 초기화하지 못하게 막는 캡슐화된 기능)</p>
</li>
<li><p>함수 캡슐화</p>
<pre><code class="language-csharp">public class ExampleEvent : MonoBehaviour
{
  //델리게이트정의
  public delegate void InputKeyHandler();
 // public delegate void InputKeyHandler(string msg);
  //event 선언
  public event InputKeyHandler onInputKey;
  //위에 두줄 == public event Action onInputKey;

  public KeyCode keycode = KeyCode.Space;

  void start
  {
      // 구독
      onInputKey += OnInputKey;
  }
  void Update()
  {
      if (Input.GetKeyDown(keycode)
      {
          //구독자가 한명이라도 있으면 실행(즉, 0명인지 확인)
          onInputKey?.Invoke();
          //onInputKey?.Invoke($&quot;{keyCode}를 눌렀습니다&quot;);
      }
  }
  public void OnInputKey()
  {
      Debug.Log(&quot;key Down&quot;);
  }
  /*public void OnInputKey(string msg)
  {
      Debug.Log(msg);
  }
  */
}</code></pre>
</li>
</ul>
<h3 id="unityevent">UnityEvent</h3>
<ul>
<li>인스펙터상에 표시하여 이벤트를 등록 가능</li>
<li>외부에서 호출 가능, [SerializeField]를 활용하여 외부 접근 제한 가능</li>
<li>AddListener, RemoveListener로 구독</li>
<li>(인스펙터 창에서 이벤트를 연결할 수 있도록 만든 클래스)</li>
</ul>
<pre><code class="language-csharp">using UnityEngine.Events; -&gt; UnityEvent를 사용할려면 작성해야함

public class StudyUnityEvent : MonoBehaviour
{
    [SerializedField] private void UnityEvent onHappened -&gt; 인스펙터 노출(외부 접근 제한)
    public UnityEvent uEvent;

    void Start()
    {
        //구독
        uEvent.AddListener(MethoA);
        uEvent.AddListener(MethoB);
        //매개변수가 있는 함수의 경우
        uEvent.AddListener(() =&gt; MethodC(10));

        //삭제
        uEvent.RemoveListener(MethoA);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space)
        {
            //실행
            uEvent?.Invoke();
        }
    }

    private void MethodA(){}
    private void MethodB(){}
    private void MethodC(int num){}
}</code></pre>
<h3 id="unityhandler">UnityHandler</h3>
<ul>
<li>Argument(인자)를 활용하는 Delegate</li>
</ul>
<pre><code class="language-csharp">public delegate void EventHandler(object sender, EventArgs e);
//object sender -&gt; 이벤트를 실행시키는 객체
//EventArgs e -&gt; 이벤트 실행시 전달할 수 있는 매개변수</code></pre>
<pre><code class="language-csharp">public class StudyEventHandler : MonoBehaviour
{
   private event EventHandler handler;
   //add, remove 이벤트 접근자
   public event EventHandler Handler //프로퍼티
   {
           add
        {
            Debug.Log($&quot;{value.Method} 추가됨&quot;); -&gt; MethodA 추가됨
            handler += value;
        }
        remove
        {
            Debug.Log($&quot;{value.Method} 삭제됨&quot;); -&gt; MethodA 삭제됨
            handler -= value;
        }
   }

  //EventHandler -&gt; void 타입의 매개변수가 2개인 델리게이트

  //delegate의 작업에서 주로 쓰이는 형태 OnEnable &lt;-&gt; OnDisable
  //켜져있으면 자동등록
  void OnEnable()
  {
      Handler += MethodA;
  }
  //파괴되거나 없어지면 구독해제
  void OnDisable()
  {
      Hanbdler -= MethodA;
  }

  void Update()
  {
       if(Input.GetKeyDown(keyCode.Space)
          handler?.Invoke(this, EventArgs.Empty);
          -&gt; 매개변수를 아무것도 넣은게 없다면 (이렇게할거면 다른거를 사용하는게 좋음)
  }

    public void MethodA(object o, EventArgs e)
    {

    }
}</code></pre>
<pre><code class="language-csharp">public class ExternalClass : MonoBehaviour
{
    public StudyEventHandler study;
    void Start()
    {
        study?.Invoke(this, EventArgs.Empty); -&gt; 실행불가능
    }
}</code></pre>
<pre><code class="language-csharp">public class DataClass : EventArgs
-&gt; Invoke를 통해 핸들러를 실행했을 때 데이터클래스의 정보를 활용하고 싶으면 DataClass에 EventArgs를 상속시키면 된다.
{
    public string dataName;
    public int dataNumer;
    public bool isData;

    public DataClass(string dataName, int dataNumber, bool isData)
    {
        this.dataName = dataName;
        this.dataNumber = dataNumber;
        this.isData = isData;
    }
}
public class StudyEventHandler : MonoBehaviour
{
    public event EventHandler handler;
    -&gt; EventHandler는 여러 데이터를 활용하는 용도로 사용
    void Start()
    {
        handler += StartEvent;

        DataClass data1 = new DataClass(&quot;DataClass1&quot;,1,false);
        DataClass data1 = new DataClass(&quot;DataClass1&quot;,1,false);

        handler?.Invoke(this , data1); -&gt; (data1을 Eventargs타입인 e로 자동변환 -&gt; 업캐스팅)
        handler?.Invoke(this , data2);
    }

    private void StartEvent(object o, EventArgs e)
    {
        var data = (DataClass)e; -&gt; 형변환(e를 DataClass형태로 전환 -&gt; 다운캐스팅)
        Debug.Log($&quot;Data Name : {data.dataName}&quot;);
    }
}</code></pre>
<p>업캐스팅, 다운캐스팅 없이 전달하기 위해서 EventHandler&lt;&#39;T&#39;&gt;를 사용</p>
<pre><code class="language-csharp">public class StudyEventHandler : MonoBehaviour
{
    public event EventHandler&lt;DataClass&gt; handler;
      -&gt;  제너릭&lt;T&gt;를 활용
      -&gt; delegate void EventHandler&lt;T&gt;(object sender, T e)
    void Start()
    {
        handler += StartEvent;

        DataClass data1 = new DataClass(&quot;DataClass1&quot;,1,false);
        DataClass data1 = new DataClass(&quot;DataClass1&quot;,1,false);

        handler?.Invoke(this , data1);
        handler?.Invoke(this , data2);
    }

    private void StartEvent(object o, DataClass e) -&gt; 제너릭&lt;T&gt; 타입을 DataClass로 설정을 했기때문에 EventArgs를 넣을 필요가 없어짐
    {
        Debug.Log($&quot;Data Name : {e.dataName}&quot;);
          Debug.Log($&quot;Data Name : {e.dataNumber}&quot;);
          Debug.Log($&quot;Data Name : {e.isData}&quot;);
    }
}</code></pre>
<h2 id="익명함수와-람다">익명함수와 람다</h2>
<h3 id="익명함수anonymous-method">익명함수(Anonymous Method)</h3>
<ul>
<li>이름 없는 함수</li>
<li>한 번만 쓸건데 이름짓고 따로 만들기 귀찮은 상황 -&gt; 간략하게 작성하자</li>
</ul>
<pre><code class="language-csharp">public class StudyLamda : MonoBehaviour
{
     public delegate void MyDelegate();
      public MyDelegate myDelegate;

      void Start()
      {
          //myDelegate = OnLog;
          myDelegate = delegate -&gt; 한번 쓰는 함수를 void OnLog(){} 쓰기 귀찮음 -&gt; 일회용 함수 사용(함수 이름 X)
          {
              Debug.Log(&quot;Hello Unity&quot;);
          }
          myDelegate?.Invoke();

          //매개변수가 있는 익명함수
          //myDelegate += delegate ~ 도 사용 가능
          myDelegate = delegate (string s)
          {
              Debug.Log(s);
          }
          myDelegate?.Invoke(&quot;Hello Unity&quot;);
      }
      /*
      public void OnLog()
      {
          Debug.Log(&quot;Hello Unity&quot;);
      }
      */
}</code></pre>
<h3 id="람다">람다</h3>
<ul>
<li>익명함수를 활용</li>
<li>함수를 생성하지 않아도 된다.</li>
</ul>
<pre><code class="language-csharp">public class StudyLamda : MonoBehaviour
{
    public delegate void MyDelegate1();
      public delegate void MyDelegate2(string s);
      public delegate void MyDelegate3(string s);

      public MyDelegate1 myDelegate1;
      public MyDelegate2 myDelegate2;
      public MyDelegate2 myDelegate3

      void Start()
      {
          myDelegate1 = () =&gt; Debug.Log(&quot;Hello Unity&quot;);
          myDelegate1?.Invoke();

          myDelegate2 = (s) =&gt; Debug.Log(s);
          myDelegate2?.Invoke(&quot;Hello Unity&quot;);

          myDelegate3 = (s) =&gt;
          {
              Debug.Log(s);
              Debug.Log(&quot;Hello Unity&quot;);
          }
          myDelegate3?.Invoke(&quot;Hello C#&quot;);
      }
}</code></pre>
<pre><code class="language-text">Hello Unity
Hello Unity
Hello C#
Hello Unity</code></pre>
<pre><code class="language-csharp">public class StudyLamda : MonoBehaviour
{
    public Button buttonUI;

      void Start()
      {
          buttonUI.onClick.AddListener( () =&gt; OnLog(&quot;Hello&quot;) );
      }
      private void OnLog(string msg)
      {
          Debug.Log(&quot;Hello Unity&quot;);
      }
}</code></pre>
<h4 id="closure-이슈">Closure 이슈</h4>
<p>: 외부 함수의 변수를 내부 함수가 참조할 때 발생
-&gt; 내부 함수는 외부 함수의 실행이 끝난 후에도 외부 함수의 변수에 접근 가능</p>
<pre><code class="language-csharp">public class ExampleClosure : MonoBehaviour
{
     public Button[] buttonUIs;

      void Start()
      {
          for (int i = 0 ; i &lt; 5 ; i++) -&gt; 외부함수의 영역
        {
            int temp = i; -&gt; Closure 이슈 방지, temp는 매 for문 바퀴마다 새로 생성               
            buttonUIs[i].onClick.AddListener(() =&gt; SetButton(temp)); -&gt;(()=&gt;Setbutton(temp))가 내부함수      
        }
      }
}</code></pre>
<h2 id="func--predicate--action--unityaction">Func / Predicate / Action / UnityAction</h2>
<h3 id="func">Func</h3>
<p>: 여러 개의 매개변수를 넣을 수 있고 반환타입이 있는 Delegate
-&gt; 마지막에 적은 타입이 반환타입</p>
<ul>
<li><p>델리게이트 체인이 있을경우 가장 마지막에 실행된 메서드의 반환값만 남게 된다.</p>
<pre><code class="language-csharp">접근제한자 Func&lt;매개변수1, 매개변수2, 반환타입&gt; 변수명;
public Func&lt;int, int, int -&gt; 반환타입&gt; myFunc;</code></pre>
<pre><code class="language-csharp">public class StudyFunc : MonoBehaviour
{
  public Func&lt;int,int,int&gt; myFunc; -&gt; int 반환타입
  public Func&lt;string, string, bool&gt; myFunc2; -&gt; bool 반환타입

  void Start()
  {
      myFunc = AddMethod;
      int result = myFunc?.Invoke(10,7);
      Debug.Log($&quot;최종 결과 : {result}&quot;);

      myFunc2 = CompareText
      bool result =2 myFunc2?.Invoke(&quot;hello&quot;, &quot;unity&quot;);
      Debug.Log(result2);
  }

  private int AddMethod(int num1, int num2)
  {
      return num1 + num2;
  }

  public bool CompareText(string msg1, string msg2)
  {
      if (a==b)
          return true;

      return false;
  }
}</code></pre>
<p>여러 개의 Func를 추가한 List</p>
<pre><code class="language-csharp">using System;
using System.Collections.Generic;
using UnityEngine;
</code></pre>
</li>
</ul>
<p>public class StudyFunc : MonoBehaviour
{
    private List&lt;Func&lt;int, int&gt;&gt; funcList = new List&lt;Func&lt;int, int&gt;&gt;();</p>
<pre><code>void Start()
{
    funcList.Add(AddMethod);
    funcList.Add(MinusMethod);
    funcList.Add(MultiplyMethod);

    -&gt; 람다식으로 줄일 수 있음 (addmethod,minusmethod,multiplymethod가 필요없어짐)
    funcList.Add(n =&gt; n + 1);
    funcList.Add(n =&gt; n - 3);
    funcList.Add(n =&gt; n * 2);

    int result = 0;
    foreach (var func in funcList) -&gt; 함수 순서대로 동작 
        result += func(5);

    Debug.Log($&quot;최종 결과: {result}&quot;);
}

private int AddMethod(int n)
{
    return n + 1;
}

private int MinusMethod(int n)
{
    return n - 3;
}

private int MultiplyMethod(int n)
{
    return n * 2;
}</code></pre><p>}</p>
<pre><code>```text
18 (addmethod return : 6 + minusmethod return : 2 + multiplymethod return : 10)</code></pre><h3 id="predicate">Predicate</h3>
<p>: 반환값이 boolean인 Delegate</p>
<pre><code class="language-csharp">접근제한자 Predicate&lt;매개변수&gt; 변수명;
public Preicate&lt;int&gt; myPredicate;</code></pre>
<pre><code class="language-csharp">public class StudyPreicate : MonoBehaviour
{
    public Predicate&lt;int&gt; myPredicate;
    public int myLevel = 10;

    void Start()
    {
        myPredicate = n =&gt; n &lt;= 10; (n &lt;= 10) -&gt; true 값이 n으로 반환
        string msg = myPredicate(myLevel) ? &quot;초보자 사냥터 이용 가능&quot; : &quot;:초보자 사냥터 이용 불가능&quot;; -&gt; 반환값에 따라 ? 이용 가능(true) : 이용 불가능(false)
        Debug.Log(msg);
    }
}</code></pre>
<h3 id="action">Action</h3>
<p>: 반환 타입이 없는 Delegate</p>
<pre><code class="language-csharp">접근제한자 Action 변수명;
접근제한자 Action&lt;매개변수(여러개도 가능)&gt; 변수명;</code></pre>
<pre><code class="language-csharp">public class StudyAction : MonoBehaviour
{
    //매개변수 없는
    public Action myAction;
    //매개변수가 있는
    public Action&lt;string&gt; myAction2;

    void Start()
    {
        myAction = () =&gt; Debug.Log(&quot;Hello Unity&quot;);
        myAction?.Invoke();

        myAction2 = (s) =&gt; Debug.Log(s);
        myAction2?.Invoke(&quot;Hello Unity&quot;);        
    }
}</code></pre>
<p>Action은 함수만 static</p>
<pre><code class="language-csharp">public class ExampleAction : MonoBehaviour
{
    public static Action myAction; -&gt; myActiong만 static
    //public static event Action myAction; -&gt; 캡슐화 작업을 통해 외부 작업 방지
    // Property는 변수 캡슐화 작업
    void Start()
    {
        myAction += AddMethod;
    }

    private void AddMethod()
    {
        Debug.Log(&quot;더하는 기능&quot;);
    }
}

public class ExampleClass : MonoBehaviour
{
    void Start()
    {
        ExampleAction.myAction += OtherMethod; -&gt; 외부에서 실행할때, 굳이 싱글턴 또는 변수만들어서 할 필요없이 static된 myAction만 접근가능

        ExampleAction.myAction?.Invoke();
    }

    public void OtherMethod()
    {
        Debug.Log(&quot;기능&quot;);
    }
}</code></pre>
<h3 id="unityaction">UnityAction</h3>
<p>: Unity에서 제공하는 Action Delegate</p>
<ul>
<li>delegate -&gt; +=, -=, ?.Invoke</li>
<li>UnityEvent -&gt; AddListener, RemoveListener, ?.Invoke</li>
</ul>
<pre><code class="language-csharp">public class StudyUnityAction : MonoBehaviour
{
    public Button buttonUI;
    public UnityAction uAction;

    void Start()
    {
        uAction += MethodA;
        uAction += MethodB;
        uAction += MethodC;

        buttonUI.onClick.AddListener(uAction);
    }

    private void MethodA(){};
    private void MethodB(){};
    private void MethodC(){};


}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity C#] 게임 수학]]></title>
            <link>https://velog.io/@dev_hang/Unity-C-%EA%B2%8C%EC%9E%84-%EC%88%98%ED%95%99</link>
            <guid>https://velog.io/@dev_hang/Unity-C-%EA%B2%8C%EC%9E%84-%EC%88%98%ED%95%99</guid>
            <pubDate>Wed, 31 Dec 2025 02:48:38 GMT</pubDate>
            <description><![CDATA[<h2 id="제곱근">제곱근</h2>
<p>: 어떤 수 x에 대해 제곱의 대상 (result=num1^num2)</p>
<ul>
<li>Mathf.Pow(float a,float b)</li>
</ul>
<pre><code class="language-csharp">public float num1 = 2, num2 = 3;

void start(){
    float result = Mathf.Pow(num1, num2);
    Debug.Log(result);
}
</code></pre>
<pre><code class="language-log">64</code></pre>
<h2 id="루트">루트</h2>
<p>: 어떤 수의 거듭제곱을 푸는 연산 (√16 = 4)</p>
<ul>
<li>Mathf.Sqrt(float a);</li>
</ul>
<pre><code class="language-csharp">void start(){
    float result = Mathf.Sqrt(16f);
    Debug.Log(result);
}</code></pre>
<pre><code class="language-log">4</code></pre>
<h2 id="로그">로그</h2>
<p>: 거듭제곱을 푸는 연산, Log의 밑 기준 몇 제곱인지 구하는 함수 (log₂(4))</p>
<ul>
<li>Mathf.Log(float a)</li>
</ul>
<pre><code class="language-csharp">void start(){
    float value1 = Mathf.Log10(1000f);
    float value2 = Mathf.Log(4f, 2f); log₂(4)
    Debug.Log(&quot;value 1 : &quot; + value1 +&quot;, value 2 : &quot; + value2);
}</code></pre>
<pre><code class="language-log">value 1 : 3, value 2 : 2</code></pre>
<h2 id="반올림-올림-내림">반올림, 올림, 내림</h2>
<ul>
<li>Mathf.Round(float a) 반올림</li>
<li>Mathf.Ceil(float a) 올림</li>
<li>Mathf.Floor(float a) 내림</li>
</ul>
<h2 id="파이">파이</h2>
<p>: 원의 둘레</p>
<ul>
<li>Mathf.PI (= 180f)</li>
</ul>
<h2 id="라디안">라디안</h2>
<p>:호도법으로 각도를 측정한 단위</p>
<ul>
<li>도 -&gt; 라디안 Mathf.Deg2Rad</li>
<li>라디안 -&gt; 도 Mathf.Rad2Deg</li>
</ul>
<pre><code class="language-csharp">float rad = degree * Mathf.Deg2Rad; //도 -&gt; 라디안 구하는 방식
float deg = radian * Mathf.Rad2Deg; // 라디안 -&gt; 도 구하는 방식</code></pre>
<h2 id="벡터">벡터</h2>
<p>: 크기와 방향을 가지고 있는 값</p>
<ul>
<li>Vector3(x,y,z)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/c5dcacb3-77bd-4a0e-bc3c-16d3742e0cd1/image.png" alt=""></p>
<p>두 벡터 사이 거리 구하기</p>
<ul>
<li>Distance : 특정 두 점의 거리 계산 √(x^2 + y^2 + z^2)</li>
<li>magnitude : 특정 벡터의 크기 계산 √(x^2 + y^2 + z^2)</li>
<li>sqrMagnitude : 특정 벡터의 크기의 제곱 (x^2 + y^2 + z^2)</li>
<li>normalized : 정규화된 벡터 (길이가 1인 방향 벡터)</li>
</ul>
<h2 id="내적-dot-product">내적 (Dot Product)</h2>
<p>: 두 벡터 간의 크기와 방향 관계를 나타내는 연산 (두 벡터의 방향을 확인)</p>
<ul>
<li>Vector3.Dot(Vector3 A, Vector3 B)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/93897235-9e8d-4200-84b5-9574072caaf9/image.png" alt=""></p>
<h2 id="외적-cross-product">외적 (Cross Product)</h2>
<p>: 두 벡터로부터 수직인 새로운 벡터를 생성하는 연산 (두 벡터가 이루는 평면의 수직 벡터 변환)
: 크기는 두 벡터로 이루어진 평면의 넓이와 관련</p>
<ul>
<li>Vector3.Cross(Vector3 A, Vector3 B)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/288c0ed3-82ff-47a9-9c23-89953440c05c/image.png" alt=""></p>
<h2 id="반사-reflection-">반사 (Reflection) (?)</h2>
<p>: 입사 벡터와 법선을 기준으로 반대쪽 방향 계산</p>
<ul>
<li>Vector3.Reflect(Vector3 inDirection, Vector3 inNormal) #inDirection : 입사 벡터, inNormal : 반사할 표면의 법선 벡터</li>
</ul>
<pre><code class="language-csharp">Vector3 inDirection = new Vector3(1,-1,0).normalized;
Vector3 inNormal = Vector3.up;

Vector3 reflected = Vector3.Reflect(inDirection , inNormal);

Debug.Log($&quot;입사각 : {inDirection}&quot;);
Debug.Log($&quot;반사각 : {reflected}&quot;);</code></pre>
<pre><code class="language-log">입사각 : (0.71, -0.71, 0.00)
반사각 : (0.71, 0.71, 0.00)</code></pre>
<h2 id="선형-보간-lerp">선형 보간 (Lerp)</h2>
<p>: 두 점 사이의 부드러운 직선 경로</p>
<ul>
<li>Mathf.Lerp(Vector3 a,Vector3 b,float c) #a : 시작 값, b : 도착 값, c : 0~1사이 비율</li>
</ul>
<h2 id="구면-선형-보간-slerp">구면 선형 보간 (Slerp)</h2>
<p>: 두 점 사이의 부드러운 둥근 경로</p>
<ul>
<li>Quaternion.Slerp(Vector3 a, Vector3 b, float c)</li>
</ul>
<h2 id="행렬-matrix">행렬 (Matrix)</h2>
<p>: 공간 변환(이동, 회전, 스케일)을 계산하는 수학 도구</p>
<h2 id="역행렬-inverse-matrix">역행렬 (Inverse Matrix)</h2>
<p>: 변환을 되돌리는 행렬</p>
<h2 id="회전-행렬-rotation-matrix">회전 행렬 (Rotation Matrix)</h2>
<p>: 회전을 행렬로 표현하여 벡터를 회전</p>
<h2 id="오일러-각-euler-angles">오일러 각 (Euler Angles)</h2>
<p>: X,Y,Z축을 기준으로 회전을 정의하는 방식</p>
<h2 id="쿼터니언-quaternion">쿼터니언 (Quaternion)</h2>
<p>: 4개의 값(x,y,z,w)로 구성된 회전 표현 방식</p>
<ul>
<li>Quaternion.Euler(float x,float y, float z)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity C#] Unity C# 기초]]></title>
            <link>https://velog.io/@dev_hang/Programming-C-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@dev_hang/Programming-C-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Thu, 18 Dec 2025 09:04:56 GMT</pubDate>
            <description><![CDATA[<h2 id="표기법">표기법</h2>
<pre><code class="language-csharp">public class Notation : MonoBehaviour
{
    string myName; // 카멜 표기법
    string my_name; // 스네이크 표기법

    string strMyName; // 헝가리안 표기법
    string s_myName; // 헝가리안 표기법
}</code></pre>
<h2 id="namespace">namespace</h2>
<p>: 코드의 지역성 설정</p>
<pre><code class="language-csharp">#namespace 설정
namespace NamespaceExample{
}

#특정 namespace(NamespaceExample) 내부의 코드를 사용할 수 있도록 설정
using NamespaceExample
</code></pre>
<h2 id="class">Class</h2>
<p>: 속성(데이터)와 기능의 집합, 자유롭게 조합할 수 있는 하나의 데이터 구조체
-&gt; 객체 지향 프로그래밍의 기초
클래스 안에 함수와 변수를 정의</p>
<pre><code class="language-csharp">class 클래스명 : MonoBehaviour{

}</code></pre>
<pre><code class="language-csharp">class NPC : MonoBehaviour
{
    public string npcName;
    public int npcAge;

}
public class NPCManager : Monobehaviour
{
    void Start()
    {
        NPC npc1 = new NPC();
        npc1.npcNmae = &quot;상인&quot;;
        npc1.npcAge = 50;
        Debug.Log(npc1.npcName);
        Debug.Log(npc1.npcAge);
    }
}</code></pre>
<pre><code class="language-text">상인
50</code></pre>
<h3 id="new-연산자">new 연산자</h3>
<p>: 메모리 상에 공간을 확보하고 생성한 객체를 저장</p>
<h2 id="struct">Struct</h2>
<p>: 속성(데이터)ㅣ와 기능의 집합, 자유롭게 조합할 수 있는 하나의 데이터 구조체
-&gt; Class와 매우 비슷하지만 메모리 상에 저장하는 방식이 다름
-&gt; 상속을 받지 못한다</p>
<pre><code class="language-csharp">public struct Car{
    float price;
    int years;
    string name;
}</code></pre>
<h2 id="method함수">Method(함수)</h2>
<p>: 기능 처리를 위한 작업의 단위</p>
<pre><code class="language-csharp">void 함수명()
{

}</code></pre>
<h3 id="매개-변수parmeter-인자argument">매개 변수(Parmeter), 인자(Argument)</h3>
<p>: 함수 실행에 필요한 추가 데이터 -&gt; 함수 실행의 재료</p>
<pre><code class="language-csharp"> void Start()
 {
     num1 = 10;
    num2 = 5;
     AddNumber1();
    AddNumber2(20,10); //Argument(인자)
 }

 //매개변수가 없는 함수
  public void AddNumber1()
 {
     int result = num1 + num2;

 }
 //매개변수가 있는 함수
 public void AddNumber2(int num3, int num4) // Parmeter 매개변수값이 존재하는 함수
 {
     int result = num3 + num4;
 }
</code></pre>
<h2 id="variable변수">Variable(변수)</h2>
<p>: 데이터를 저장할 수 있는 공간</p>
<pre><code class="language-csharp">public class ExampleVariable : MonoBehaviour
{
    // 맴버 변수
    int iNum;
    float fNum;
    double bNum;
    bool isYesNo;
    char c;
    string str;

    void Start()
    {    // 지역 변수
        int startNum;
        bool isStart;
    }
}</code></pre>
<h4 id="맴버-변수">맴버 변수</h4>
<ul>
<li>필드 (Field) : 클래스나 구조체 내부에 선언된 변수를 가리킴</li>
<li>속성(Attribute) 또는 프로퍼티(Property) : 객체의 특성</li>
<li>인스턴스 변수 (Instance Variable) : 객체가 생성될 때마다 메모리에 할당되는 변수</li>
</ul>
<h4 id="지역-변수">지역 변수</h4>
<ul>
<li>로컬 변수 : 함수 내부에서 선언된 변수를 가리킴</li>
</ul>
<h4 id="스코프">스코프</h4>
<ul>
<li>변수의 유효 범위</li>
</ul>
<h3 id="자료형">자료형</h3>
<p>: 메모리에 저장되는 데이터 형식
<img src="https://velog.velcdn.com/images/dev_hang/post/544d51b1-e723-45d6-9f37-ff27fa010f35/image.png" alt=""></p>
<h3 id="상수">상수</h3>
<p>: 변하지 않는 수(불변 값) -&gt; 변수를 상수로 설정하는 키워드</p>
<pre><code class="language-csharp">const float PI1 = 3.1415f;
readonly float PI2 = 3.1415f;</code></pre>
<h4 id="const">const</h4>
<ul>
<li>컴파일 단계에서 값이 적용</li>
<li>int, float, string, enum 등에 적용 가능</li>
<li>선언할 때 초기화가 필요</li>
</ul>
<h4 id="readonly">readonly</h4>
<ul>
<li>런타임 단계에서 값이 적용</li>
<li>모든 Type에 적용 가능</li>
<li>반드시 초기화 필요 X</li>
<li>const보다 유연하다</li>
</ul>
<h2 id="접근-제한자">접근 제한자</h2>
<p>: 변수나 함수의 접근 권한을 설정 -&gt; Access할 수 있는 보안 수준</p>
<pre><code class="language-csharp">private : 자신의 클래스만 접근 가능
protected : 자신의 클래스, 자신의 클래스를 상속받은 클래스만 접근 가능
public : 모든 클래스에서 접근 가능</code></pre>
<h3 id="클래스-접근">클래스 접근</h3>
<p>:  &#39; . &#39;을 찍어서 내부로 접근 가능</p>
<pre><code class="language-csharp">public class ScriptA
{

    public int num1 = 1; // public 맴버변수
      int num2 = 2; // private 맴버변수
    private int num3 = 3; // private 맴버변수
    [SerializeField] private int num4 = 4; // private 맴버변수
    protected int num5 = 5; //protected 맴버변수

    void Start(){
        int num6 = 6; // 지역변수
    }
}</code></pre>
<pre><code class="language-csharp">public class ScriptB
{
    public ScriptA scriptA;

    void Start(){
        scriptA.num1 = 10;
        scriptA.num2 = 10;
        scriptA.num3 = 10;
        scriptA.num4 = 10;
        scriptA.num5 = 10;
        scriptA.num6 = 10;

    }
}</code></pre>
<pre><code class="language-text">num1 = 10만 적용</code></pre>
<h3 id="필드">필드</h3>
<p>: 일반적인 변수</p>
<pre><code class="language-csharp">private int num1; //private 필드 : 자신의 클래스만 접근 가능
public int num2; //public 필드 : 다른 클래스에서 접근 가능</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Component (추가 예정)]]></title>
            <link>https://velog.io/@dev_hang/Unity-Component-%EC%B6%94%EA%B0%80-%EC%98%88%EC%A0%95</link>
            <guid>https://velog.io/@dev_hang/Unity-Component-%EC%B6%94%EA%B0%80-%EC%98%88%EC%A0%95</guid>
            <pubDate>Thu, 18 Dec 2025 07:37:55 GMT</pubDate>
            <description><![CDATA[<h2 id="component">Component</h2>
<p>: 게임 오브젝트의 기능</p>
<br/>



<p><img src="https://velog.velcdn.com/images/dev_hang/post/5ae67509-128a-4c20-8abc-4394e3f3a3d1/image.png" alt=""></p>
<h4 id="transform">Transform</h4>
<p>: 게임 오브젝트의 위치, 회전, 크기 정보
<img src="https://velog.velcdn.com/images/dev_hang/post/324505ff-cf8c-42db-8a3c-f778e0bbd3d0/image.png" alt=""></p>
<h4 id="mesh-filter">Mesh Filter</h4>
<p>:메쉬 필터에는 게임 오브젝트의 모양(Mesh)를 담을 수 있다.
<img src="https://velog.velcdn.com/images/dev_hang/post/4f4e52fb-5eed-4f1c-a3e6-ea5db4dc87c9/image.png" alt=""></p>
<h4 id="mesh-renderer">Mesh Renderer</h4>
<p>: 게임 오브젝트의 모양을 그리는 컴포넌트
<img src="https://velog.velcdn.com/images/dev_hang/post/bfe0b5e7-9210-44f9-8be6-fe0c57bb1242/image.png" alt=""></p>
<h4 id="capsule-collider">Capsule Collider</h4>
<h4 id="box-collider">Box Collider</h4>
<h4 id="rigidbody">RigidBody</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] GameObject]]></title>
            <link>https://velog.io/@dev_hang/Unity-GameObject</link>
            <guid>https://velog.io/@dev_hang/Unity-GameObject</guid>
            <pubDate>Thu, 18 Dec 2025 07:22:29 GMT</pubDate>
            <description><![CDATA[<h2 id="gameobject--오브젝트의-기본단위">GameObject : 오브젝트의 기본단위</h2>
<br/>
<h4 style ="text-align : center">
유니티 3D에서 제공하는 기본 도형
 </h4>

<p><img src="https://velog.velcdn.com/images/dev_hang/post/e38893ac-533f-4e5c-a431-3ed19ec9f3af/image.png" alt=""></p>
<br/>

<h4 style ="text-align : center">
Vertext(점), Edge(선), Polygon(삼각형)
</h4>

<p><img src="https://velog.velcdn.com/images/dev_hang/post/3115cfeb-1181-45dc-ba9f-72c59d8f86dd/image.png" alt=""></p>
<h3 id="low-폴리와-high-폴리">Low 폴리와 High 폴리</h3>
<p>: Polygon 수에 비례하는 퀄리티 -&gt; Polygon수는 퀄리티와 최적화의 영향을 끼침</p>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/89e3ecae-ff33-4f51-a36a-223b46885551/image.png" alt=""></p>
<h3 id="empty-gameobject">Empty GameObject</h3>
<p>: 게임 오브젝트들의 그룹화 또는 스크립트를 실행하는 용도</p>
<div style="display:flex; justify-content:center; gap:16px;">
  <img src="https://velog.velcdn.com/images/dev_hang/post/c1e2b635-32c5-4b1d-b1c4-f64251c86261/image.png" width="400">
  <img src="https://velog.velcdn.com/images/dev_hang/post/81f799fb-e62b-4576-a915-82c424393d59/image.png" width="400">
</div>

<p><img src="https://velog.velcdn.com/images/dev_hang/post/34161c92-e6f2-48b4-8d3d-b7fec234a66b/image.png" alt="">
<dr/></p>
<h3 id="prefab">Prefab</h3>
<p>: Scene에 있는 Object를 Asset으로 포장하는 것</p>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/a8e3f37b-944e-4eb8-9ab9-f654f2eebbcc/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/6285cb45-531e-4a18-b23b-0af6d15d5a0b/image.png" alt=""></p>
<h4 id="prefab의-종류">Prefab의 종류</h4>
<div style="display:flex; justify-content:center; gap:16px;">
  <img src="https://velog.velcdn.com/images/dev_hang/post/b8aa6efa-9645-42d5-ba83-d3990f910c80/image.png" width= "300">
  <img src="https://velog.velcdn.com/images/dev_hang/post/99e88e28-6e1d-4d10-bec8-97227d4d2050/image.png" width="300">
</div>


<ul>
<li>Origin Prefab
: 원본 프리팹 </li>
<li>Varient Prefab
: 원본 프리팹을 상속받는 프리팹</li>
<li>Nested Prefab
: 프리팹 안에 프리팹이 있는 구조</li>
</ul>
<br/>
<br/>

<div style="text-align:center">
해당 프리팹 더블 클릭을 통해 프리팹을 수정할 수 있다.
</div>

<p><img src="https://velog.velcdn.com/images/dev_hang/post/ec609b7d-951a-4762-a680-53ac6b569757/image.png" alt=""></p>
<div style="text-align:center">
만약에 프리팹 자체를 수정하지 않고 씬의 프리팹을 수정할 경우 Override를 통해 프리팹을 수정할 수 있다.
</div>

<p><img src="https://velog.velcdn.com/images/dev_hang/post/a5071f0a-e92f-4f6c-ac01-48b3832bc9f3/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Pivot, Center, Local, Global 좌표]]></title>
            <link>https://velog.io/@dev_hang/Unity-Pivot-Center-Local-Global-%EC%A2%8C%ED%91%9C</link>
            <guid>https://velog.io/@dev_hang/Unity-Pivot-Center-Local-Global-%EC%A2%8C%ED%91%9C</guid>
            <pubDate>Fri, 05 Dec 2025 10:39:33 GMT</pubDate>
            <description><![CDATA[<h2 id="pivot-좌표계-center-좌표계">Pivot 좌표계, Center 좌표계</h2>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/35a7df63-e9be-4bbe-8bba-7d7713148764/image.png" alt=""></p>
<h3 id="pivot--선택한-오브젝트의-기준-축">Pivot : 선택한 오브젝트의 기준 축</h3>
<h3 id="center--선택한-오브젝트의-자식오브젝트까지-포함한-중심-축">Center : 선택한 오브젝트의 자식오브젝트까지 포함한 중심 축</h3>
<div style="display: flex; justify-content : center; gap: 1px;">

  <figure style ="text-align: center;">
    <img src="https://velog.velcdn.com/images/dev_hang/post/b2c340cb-88de-4fdd-82e3-468198759e87/image.png" />
    <figcaption> Pivot 좌표계 </figcaption>
  </figure>

  <figure style ="text-align: center;">
    <img src="https://velog.velcdn.com/images/dev_hang/post/31bd2b18-a4b2-4b86-8614-db3f1b97753b/image.png" />
    <figcaption> Center 좌표계 </figcaption>
      </figure>
</div>



<h2 id="local-좌표계-global-좌표계">Local 좌표계, Global 좌표계</h2>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/f1388706-690c-4ab3-981e-394137a054a7/image.png" alt="">
<img src="https://velog.velcdn.com/images/dev_hang/post/93c53b7a-331a-45d8-b87d-1ad65fd80694/image.png" alt=""></p>
<h3 id="local--오브젝트-기준에서의-좌표">Local : 오브젝트 기준에서의 좌표</h3>
<h3 id="global--world에서-오브젝트의-좌표">Global : World에서 오브젝트의 좌표</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Console View]]></title>
            <link>https://velog.io/@dev_hang/Unity-Console-View</link>
            <guid>https://velog.io/@dev_hang/Unity-Console-View</guid>
            <pubDate>Fri, 05 Dec 2025 10:19:33 GMT</pubDate>
            <description><![CDATA[<h2 id="console-view">Console View</h2>
<p>: Log를 확인할 수 있는 창 (단축키 : Ctrl + Shift + c)
<img src="https://velog.velcdn.com/images/dev_hang/post/354da560-81e6-4a09-be55-990935471f4c/image.png" alt=""></p>
<p>Unity Editor Play 버튼 클릭 시
콘솔 창에서 Log, LogWarning, LogError를 확인할 수 있음</p>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/f69dfafd-1e98-4a2b-8cd6-a34bbaf0cb97/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Inspector View]]></title>
            <link>https://velog.io/@dev_hang/Unity-Inspector-View</link>
            <guid>https://velog.io/@dev_hang/Unity-Inspector-View</guid>
            <pubDate>Fri, 05 Dec 2025 10:12:19 GMT</pubDate>
            <description><![CDATA[<h2 id="inspector-view">InSpector View</h2>
<p>: 상세정보 창 (선택한 오브젝트 또는 Asset의 상세정보)
<img src="https://velog.velcdn.com/images/dev_hang/post/3d60ec60-9dad-41eb-ab8f-c09b10d49b57/image.png" alt=""></p>
<h3 id="오브젝트-활성화--비활성화">오브젝트 활성화 / 비활성화</h3>
<p>: 오브젝트의 존재 상태를 키고 끄는 것 (단축키 : Alt + Shift + A)
<img src="https://velog.velcdn.com/images/dev_hang/post/72024c9a-cbee-4cf5-81d8-2037b2cfff73/image.png" alt=""></p>
<h3 id="오브젝트의-이름">오브젝트의 이름</h3>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/2ecec2c3-582a-46c6-8dd5-3d184638ad29/image.png" alt=""></p>
<h3 id="static-설정정적-게임-오브젝트-설정">Static 설정(정적 게임 오브젝트 설정)</h3>
<p>: 무엇인가를 계산하기 위해 &quot;움직이지 않는 게임 오브젝트&quot; 설정
<img src="https://velog.velcdn.com/images/dev_hang/post/a18daacf-d440-4eb6-842f-0bc5b2d8e1ab/image.png" alt=""></p>
<ul>
<li>Nothing : 어떠한 Static옵션도 적용 X</li>
<li>Everything : 모든 Static 옵션을 활성화</li>
<li>Contribute GI : 오브젝트가 라이트맵을 생성하고 사용하는데 필요한 정보 제공</li>
<li>Occluder Static : 카메라에서 보이지 않는 오브젝트의 렌더링 방지</li>
<li>Occludee Static : 해당 오브젝트가 다른 오브젝트에 의해 가려질 수 있음을 의미(즉, 다른 오브젝트에 의해 가려져 있을 때 렌더링에서 제외되어 성능 향상)</li>
<li>Navigation Static : AI캐릭터가 이동할 수 있는 경로 계산</li>
<li>Off Mesh Link Generation : Navigation system에서 Mesh간의 연결 링크를 자동으로 생성하도록 설정</li>
<li>Reflection Probe Static : Reflection Probe에 의해 반사되는 환경을 계산(실시간으로 빛의 반사를 계산하여 환경의 실감나는 표현 도움)</li>
</ul>
<br>

<h3 id="tag">Tag</h3>
<p>: 오브젝트의 별명, 오브젝트를 식별할 수 있음
<img src="https://velog.velcdn.com/images/dev_hang/post/f29b7048-bd80-4254-ae84-4c3c48d1d322/image.png" alt=""></p>
<h3 id="layer">Layer</h3>
<p>: 오브젝트 그룹, 오브젝트 소속</p>
<div style="display : flex; gap: 10px;">
  <img src ="https://velog.velcdn.com/images/dev_hang/post/8d645074-b426-4537-b5b7-92684e882731/image.png" />
  <img src="https://velog.velcdn.com/images/dev_hang/post/3000b1b2-af9c-4031-a268-00e70e1e0cd5/image.png" />
 />
</div>



]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Project View]]></title>
            <link>https://velog.io/@dev_hang/Unity-Project-View</link>
            <guid>https://velog.io/@dev_hang/Unity-Project-View</guid>
            <pubDate>Fri, 05 Dec 2025 09:32:06 GMT</pubDate>
            <description><![CDATA[<h2 id="project-view">Project View</h2>
<p>: 리소스 관리창 (프로젝트의 파일 목록)</p>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/7e06a9b6-8b85-45d4-a768-e7e97ef16556/image.png" alt=""></p>
<h5 id="asset--유니티에서-사용하는-프로젝트-파일의-기본-단위">Asset : 유니티에서 사용하는 프로젝트 파일의 기본 단위</h5>
<br>


<h3 id="project-view-layout-변경">Project View Layout 변경</h3>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/698f86de-1347-4866-9cac-429094e334ac/image.png" alt=""></p>
<p>슬라이더 : Two Column Layout일 경우, 아이콘 크기 조절
<img src="https://velog.velcdn.com/images/dev_hang/post/6fdaf387-9b59-4ea9-bdda-eedcb339ed58/image.png" alt=""></p>
<h3 id="프로젝트-폴더-생성-및-정리">프로젝트 폴더 생성 및 정리</h3>
<p>: 자기가 편한데로 수정 가능 (협업일 경우, 통일)</p>
<img src ="https://velog.velcdn.com/images/dev_hang/post/ca39d01d-6add-4c4f-8c51-0e8cbc495e39/image.png" width = "300px" />
<br>
<br>

<h3 id="asset의-타입으로-검색">Asset의 타입으로 검색</h3>
<p align = "center">
  <img src="https://velog.velcdn.com/images/dev_hang/post/26a29dcc-9968-4d61-8cf3-d782d3bbbe71/image.png" /> </p>





]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Hierarchy View]]></title>
            <link>https://velog.io/@dev_hang/Unity-Hierarchy-View</link>
            <guid>https://velog.io/@dev_hang/Unity-Hierarchy-View</guid>
            <pubDate>Fri, 05 Dec 2025 09:15:42 GMT</pubDate>
            <description><![CDATA[<h3 id="hierarchy-view">Hierarchy View</h3>
<p>: 배치된 오브젝트들의 목록 (계층 구조(계단식 구조, 순서가 있다))
<img src="https://velog.velcdn.com/images/dev_hang/post/4d03a3fa-6582-4026-9d62-7a979b7eab2f/image.png" alt=""></p>
<p> &#39;+&#39; 버튼 클릭 또는 마우스 우클릭 후 오브젝트 생성
 <img src="https://velog.velcdn.com/images/dev_hang/post/5e1a3e7e-c46b-4a68-8946-9ee5ad9a42f5/image.png" alt=""></p>
<ul>
<li>검색 기능
<img src="https://velog.velcdn.com/images/dev_hang/post/6d579065-e69b-4baf-af84-ca5370a559d2/image.png" alt=""></li>
</ul>
<h3 id="계층-구조">계층 구조</h3>
<p> : 순서, 부모 - 자식 관계가 있는 구조
 <img src="https://velog.velcdn.com/images/dev_hang/post/19363583-9ece-4942-8aae-1d61194e5fdf/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Game View]]></title>
            <link>https://velog.io/@dev_hang/Unity-Game-View</link>
            <guid>https://velog.io/@dev_hang/Unity-Game-View</guid>
            <pubDate>Fri, 05 Dec 2025 09:02:21 GMT</pubDate>
            <description><![CDATA[<h2 id="game-view">Game View</h2>
<p>: 실행 시 화면에 보이는 결과물 화면
<img src="https://velog.velcdn.com/images/dev_hang/post/3395cdf2-31ed-465d-88dc-33088cdb2e05/image.png" alt=""></p>
<br>

<h3 id="game-view-해상도-설정">Game View 해상도 설정</h3>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/7790e8ae-2994-4cbb-934a-a0a699ee0427/image.png" alt=""></p>
<ul>
<li><p>HD(720p) : High Definition = 1280 * 720</p>
</li>
<li><p>FHD(1080p) : Full High Definition = 1920 * 1080</p>
</li>
<li><p>QHD(1440p) : Quad High Definition = 2560 * 1440</p>
</li>
<li><p>UWQHD(1440p) : Ultra Wide Quad High Definition = 3440 * 1440</p>
</li>
<li><p>UHD(2160p) : Ultra High Definition = 3840 * 2160</p>
<ul>
<li>2K = 2048 * 1080</li>
<li>4k = 4096 * 2160</li>
<li>8K = 8192 * 4320</li>
</ul>
</li>
</ul>
<h3 id="game-view-state">Game View State</h3>
<p>: 실행되고 있는 현재 성능 상태 표시</p>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/bec722f9-5222-4ec1-9a49-0ce0143ed1db/image.png" alt=""></p>
<h3 id="게임-내-game-view-종류">게임 내 Game View 종류</h3>
<p>: 카메라 위치에 따른다.</p>
<ul>
<li>1인칭 뷰</li>
<li>3인칭 뷰</li>
<li>탑다운 뷰</li>
<li>쿼터 뷰</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Snap]]></title>
            <link>https://velog.io/@dev_hang/%EC%9C%A0%EB%8B%88%ED%8B%B0-%ED%88%B4-Snap</link>
            <guid>https://velog.io/@dev_hang/%EC%9C%A0%EB%8B%88%ED%8B%B0-%ED%88%B4-Snap</guid>
            <pubDate>Fri, 05 Dec 2025 08:48:53 GMT</pubDate>
            <description><![CDATA[<h3 id="frame-selected">Frame Selected</h3>
<p>: 포커스 기능</p>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/f57a3cf0-0e55-4fb5-ac6f-5980c18deb95/image.png" alt=""></p>
<h2 id="snap">Snap</h2>
<p>: 오브젝트의 트랜스 값을 떨어지게 변경 (Ctrl + 이동)</p>
<h3 id="vertex-snap">Vertex Snap</h3>
<p>: 오브젝트를 모서리에 붙이는 기능 (V + 이동)</p>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/8d2ce0f1-47a7-416f-a289-b99869dcaee8/image.png" alt=""></p>
<h3 id="surface-snap">Surface Snap</h3>
<p>: 평평한 면에 붙이는 기능 ( Ctrl + Shift + 이동)
<img src="https://velog.velcdn.com/images/dev_hang/post/a025a7d6-8845-4314-b938-2e2ca75dfbdc/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Scene View]]></title>
            <link>https://velog.io/@dev_hang/Unity-Scene-View</link>
            <guid>https://velog.io/@dev_hang/Unity-Scene-View</guid>
            <pubDate>Thu, 04 Dec 2025 13:23:02 GMT</pubDate>
            <description><![CDATA[<h3 id="개발자-작업-공간">개발자 작업 공간</h3>
<h4 id="scene--개발자가-구성하는-하나의-월드">Scene : 개발자가 구성하는 하나의 월드</h4>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/774a929e-8db2-4b27-95dd-b6728a6c10ad/image.png" alt=""></p>
<h4 id="fly-through--scene-공간을-날아다니는-기능">Fly Through : Scene 공간을 날아다니는 기능</h4>
<ul>
<li><p>이동 : W, A , S , D + 마우스 오른쪽 클릭</p>
</li>
<li><p>가속 : 이동 중 + Shift</p>
</li>
<li><p>확대 : 마우스 휠</p>
<br>
<p align="center">
<img src="https://velog.velcdn.com/images/dev_hang/post/c8c5c5a4-9f67-46f7-9d47-0be4c332237a/image.png" width="600px" />

</li>
</ul>
<h4 id="tool-bar--자주-사용하는-도구-상자-왼쪽부터-4개를-주로-사용">Tool Bar : 자주 사용하는 도구 상자 (왼쪽부터 4개를 주로 사용)</h4>
<ul>
<li><p>Hand Tool(단축키 - Q) : 화면을 잡고 움직이는 기능</p>
</li>
<li><p>Move Tool(단축키 - W) : 오브젝트의 위치를 조작</p>
</li>
<li><p>Rotate Tool(단축키 - E) : 오브젝트의 회전을 조작</p>
</li>
<li><p>Scale Tool(단축키 - R) : 오브젝트의 크기를 조작</p>
</li>
</ul>
<p><br><br></p>
<img src="https://velog.velcdn.com/images/dev_hang/post/b03d2baa-7490-4b40-8bc6-a0b8840042ec/image.png" width = "150px" />
 </p>

<h4 id="gizmo--scene의-나침반">Gizmo : Scene의 나침반</h4>
<ul>
<li>Z축 : 앞쪽</li>
<li>Y축 : 위쪽</li>
<li>X축 : 오른쪽</li>
</ul>
<h1 id="scene-렌더링-방식">Scene 렌더링 방식</h1>
<h4 id="perspective--원근법이-적용된-시점">Perspective : 원근법이 적용된 시점</h4>
<img src="https://velog.velcdn.com/images/dev_hang/post/c58bf2c2-ebf4-4c77-afea-c245ab7d5b0d/image.png" />


<h4 id="isometric--원근법이-적용되지-않은-시점orthographic">Isometric : 원근법이 적용되지 않은 시점(Orthographic)</h4>
<img src="https://velog.velcdn.com/images/dev_hang/post/c2347f37-ec81-4b2c-a88e-1b0f0cf17ac5/image.png" width = "500px" />






]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Editor Layout]]></title>
            <link>https://velog.io/@dev_hang/Unity</link>
            <guid>https://velog.io/@dev_hang/Unity</guid>
            <pubDate>Thu, 04 Dec 2025 12:55:50 GMT</pubDate>
            <description><![CDATA[<h1 id="유니티-에디터-레이아웃">유니티 에디터 레이아웃</h1>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/5833163d-c587-42e4-a5f7-d475944a5ac5/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/56fd2f7f-2444-465e-9002-4ae2048879a0/image.png" alt="">
<img src="https://velog.velcdn.com/images/dev_hang/post/53424d58-364d-4fa9-aece-f66e0c84ce9a/image.png" alt="">
특정 window가 없어졌을 경우, window -&gt; General -&gt; 해당 레이아웃</p>
<p><img src="https://velog.velcdn.com/images/dev_hang/post/3995fe3c-3e1e-437f-a781-29321d28731d/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>