<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko-KR, en-US"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://jinlee0206.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://jinlee0206.github.io/" rel="alternate" type="text/html" hreflang="ko-KR, en-US" /><updated>2024-09-03T18:12:58+09:00</updated><id>https://jinlee0206.github.io/feed.xml</id><title type="html">Lavi</title><subtitle>개발자로서 나의 성장을 기록하다
</subtitle><author><name>Jinsoo Lee</name><email>ljs4784@gmail.com</email></author><entry><title type="html">[회사분석] 키엔스</title><link href="https://jinlee0206.github.io/diary/Keyence.html" rel="alternate" type="text/html" title="[회사분석] 키엔스" /><published>2024-09-03T00:00:00+09:00</published><updated>2024-09-03T00:00:00+09:00</updated><id>https://jinlee0206.github.io/diary/Keyence</id><content type="html" xml:base="https://jinlee0206.github.io/diary/Keyence.html"><![CDATA[<!--more-->

<ul id="markdown-toc">
  <li><a href="#키엔스" id="markdown-toc-키엔스">키엔스</a>    <ul>
      <li><a href="#회사-소개" id="markdown-toc-회사-소개">회사 소개</a></li>
      <li><a href="#모집-부분-및-자격" id="markdown-toc-모집-부분-및-자격">모집 부분 및 자격</a></li>
      <li><a href="#인재상" id="markdown-toc-인재상">인재상</a></li>
      <li><a href="#복지" id="markdown-toc-복지">복지</a></li>
      <li><a href="#인터뷰" id="markdown-toc-인터뷰">인터뷰</a>        <ul>
          <li><a href="#머신-비전-그룹" id="markdown-toc-머신-비전-그룹">머신 비전 그룹</a></li>
          <li><a href="#정밀-측정-그룹" id="markdown-toc-정밀-측정-그룹">정밀 측정 그룹</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<h1 id="키엔스">키엔스</h1>

<h2 id="회사-소개">회사 소개</h2>

<ul>
  <li>KEYENCE는 산업용 센서에서부터 검사라인을 위한 측정기기 및 연구개발용 계측기에 이르는 광범위한 제품을 제공하며 또한 설계 및 연구 단계를 비롯한 생산설비 전 분야에 필요한 솔루션 및 서비스를 제공하고 있는 회사</li>
  <li>KEYENCE의 제품들은 현재뿐만 아니라 미래 고객들의 요구까지 감안하여 제조와 연구 분야에서 적용할 수 있는 혁신적인 제품들을 선보여 오고 있음</li>
  <li>현장의 업무를 빈틈 없이 뒷바침하기 위해서 다양한 영업 지원팀들의 역할 또한 존재</li>
</ul>

<h2 id="모집-부분-및-자격">모집 부분 및 자격</h2>
<blockquote>
  <p>기술 엔지니어</p>
</blockquote>

<ul>
  <li>담당 업무
    <ul>
      <li>초기 장비 셋업 및 교육</li>
      <li>기술 문의 대응</li>
    </ul>
  </li>
  <li>우대 사항
    <ul>
      <li>머신비전 현장대응 유경험자
        <ul>
          <li><em>머신 비전</em> : 기계에 인간의 시각과 판단 능력을 부여하여 사람이 인지하고 판단하는 기능을 하드웨어와 소프트웨어 시스템이 대신 처리하는 기술</li>
        </ul>
      </li>
      <li>C++, C# 프로그램 가능자</li>
      <li>일본어, 영어 가능자</li>
    </ul>
  </li>
</ul>

<h2 id="인재상">인재상</h2>
<ul>
  <li>인재 역량
    <ul>
      <li>목표 의식 : 열정을 가지고 목표를 향해 최선을 다하는 자세</li>
      <li>도전 의식 : 간절함을 가지고 포기하지 않고 진취적으로 나아가려는 자세</li>
      <li>능동적 사고 : 열린 관점에서 자신의 생각과 논리로 겸손하게 일할 수 있는 자세</li>
    </ul>
  </li>
  <li>인재 성향
    <ul>
      <li>성실함 : 남을 의식하지 않고 꾸준하게 목표를 향해 주어진 직무를 수행할 수 있는 사람</li>
      <li>솔직함 : 본 그대로를 전달하고 자신의 생각을 솔직하게 말할 수 있는 사람</li>
      <li>신뢰감 : 내가 중심이 아닌 상대방에게 좋은 느낌이 들도록 신뢰감을 줄 수 있는 사람</li>
    </ul>
  </li>
</ul>

<h2 id="복지">복지</h2>
<ul>
  <li>최적의 근무환경 제공
    <ul>
      <li>업무에 집중할 수 있도록 회사 차원에서 지원해주는 최적의 근무 환경 존재</li>
      <li>지속적인 교육 및 다양한 교육 프로그램을 통해 각 직무의 스페셜리스트가 될 수 있는 징검다리 역할을 회사에서 제공</li>
    </ul>
  </li>
  <li>다양한 복지
    <ul>
      <li>가정을 꾸렸을 때에 지원해 주는 여러 다양한 복지 제도가 존재</li>
    </ul>
  </li>
  <li>확실한 성과보상
    <ul>
      <li>개인 성과에 따른 차등적 성과급 지급제도와 다양한 인센티브제 운영</li>
      <li>자연스럽게 높은 애사심으로 이어지는 징검다리</li>
    </ul>
  </li>
  <li>안정적인 생활
    <ul>
      <li>DB형 퇴직연금이나 주거 안정화 보조금 지원은 회사에 오래 근속할 좋은 동기부여가 됨</li>
    </ul>
  </li>
</ul>

<h2 id="인터뷰">인터뷰</h2>

<h3 id="머신-비전-그룹">머신 비전 그룹</h3>
<blockquote>
  <p>머신 비전 : <em>기계에 인간의 시각과 판단 능력을 부여하여 사람이 인지하고 판단하는 기능을 하드웨어와 소프트웨어 시스템이 대신 처리하는 기술</em></p>
</blockquote>

<ul>
  <li>정밀 검사 수행
    <ul>
      <li>산업 분야가 <strong>자동화</strong>로 전환되면서 생산공정에 단순한 측정뿐만 아니라 공정과정에서 획득한 영상의 기술적 처리, 판단 프로세서까지 사용자의 목적에 맞게 광범위하게 사용됨</li>
      <li>머신 비전 시스템을 이용한다면, 제조 업체에서는 고속/고배율/24시간 작업 및 측정의 반복성 등이 필요한 검사 공정을 머신 비전을 통해 정밀하고 고속으로 검사 가능</li>
      <li>고객에 니즈에 맞는 <strong>토탈 솔루션</strong> 제공</li>
      <li><code class="language-plaintext highlighter-rouge">머신비전 = 하드웨어(고성능 카메라, 조명, 렌즈) + 소프트웨어 (이미지 프로세서)</code></li>
      <li>수행하고자 하는 작업의 목적에 맞게 적절한 이미지를 획득한 후, 이미지 프로세서를 통해 영상처리 및 분석과정을 거쳐 원하는 작업을 수행</li>
      <li>KEYENCE 비전은 고해상도 카메라와 혁신적인 특수조명 Line-up을 통해 기존에 일반적인 비전시스템에서는 검사가 어려웠던 부분들을 안정적으로 검출 가능</li>
      <li>공장자동화 분야에서 세계적인 기업이며, 앞으로의 시장 확대 및 적용 분야가 무궁 무진함</li>
    </ul>
  </li>
  <li>직무 및 업무
    <ul>
      <li>판매뿐아니라 제품 및 기술에 대한 지식을 통해 고객에게 제안 및 문제 해결에 대응하는 업무</li>
      <li>공장자동화 관련 산업분야에서의 키엔스는 점유율이 세계적으로 높으므로 성취감과 긍지를 가지고 업무에 임할 수 있다</li>
    </ul>
  </li>
  <li>필요 역량
    <ul>
      <li>강한 멘탈
        <ul>
          <li>오랜 시간 고객과 커뮤니케이션 및 검토를 진행해야하는 경우도 있고, 중간에 문제가 발생해도 포기하지않고 상황을 이끌어가야하는 경우가 있다</li>
          <li>긍정적인 마인드와 끈기가 필요</li>
          <li>고객과의 원활한 의사소통 능력과 문제해결 능력도 필요</li>
        </ul>
      </li>
      <li>배우고자 하는 의지
        <ul>
          <li>기술 및 소프트웨어에 대한 습득력이 떨어지더라도 개인의 목표와 배우고자 하는 의지가 뚜렷하다면 얼마든지 극복할 수 있다</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<h3 id="정밀-측정-그룹">정밀 측정 그룹</h3>
<ul>
  <li>다양한 영업 그룹들의 현장 지원
    <ul>
      <li>필드 엔지니어는 다양한 영업 그룹들의 현장 지원을 하고있으며, 업무는 크게 내/외근 으로 나뉨</li>
      <li>외근 시 : 영업사원이 고객에 제안하고 판매한 제품에 대해 고객의 요구 사항에 따라 셋업을 지원</li>
      <li>내근 시 : 고객들에게 발생한 설정상 문제점 분석과 고객 문의에 대한 기술 대응 그리고 스킬업을 위한 팀별 셋업 교육을 진행</li>
    </ul>
  </li>
  <li>업무를 하면서 가장 보람된 순간
    <ul>
      <li>필드 엔지니어는 직접 고객과 가장 많은 시간을 마주하며 자동화 공정 개선 방안에 대해 함께 고민하는 포지션</li>
      <li>고객의 요청 사항에 맞는 정확한 셋업과 신속한 기술대응으로 고객이 만족하여 다시 한번 키엔스 제품을 찾을 때 가장 만족과 보람을 느낌</li>
    </ul>
  </li>
  <li>필요 역량
    <ul>
      <li>정확한 이해력과 지속적인 노력 그리고 책임감</li>
      <li>필드 엔지니어는 <em>판매된 제품이 제 기능을 할 수 있도록 셋업하는 것이 주 업무</em></li>
      <li><em>제품에 대한 정확한 이해</em>와 <em>주어진 시간 내에서의 업무 수행능력</em>이 가장 중요</li>
      <li>제품의 모든 것을 알아야 하므로 교육 기간 이후로도 지속적인 노력이 필요하며 셋업 이후에도 <em>고객과의 커뮤니케이션</em>이 필요하기 떄문에 책임감 또한 필요</li>
    </ul>
  </li>
  <li>팀과 고객 중심의 사고
    <ul>
      <li>일을 하는 과정에서 <em>성취감과 만족감 느끼며 일을 할 수 있는 마인드</em></li>
      <li>회사와 함께 성장하고 싶다는 동반자 의식</li>
    </ul>
  </li>
</ul>]]></content><author><name>Jinsoo Lee</name><email>ljs4784@gmail.com</email></author><category term="diary" /><category term="diary" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">[Unity] 직렬화</title><link href="https://jinlee0206.github.io/develop/Unity_Serialization.html" rel="alternate" type="text/html" title="[Unity] 직렬화" /><published>2024-08-25T00:00:00+09:00</published><updated>2024-08-25T00:00:00+09:00</updated><id>https://jinlee0206.github.io/develop/Unity_Serialization</id><content type="html" xml:base="https://jinlee0206.github.io/develop/Unity_Serialization.html"><![CDATA[<!--more-->

<ul id="markdown-toc">
  <li><a href="#직렬화-serialization" id="markdown-toc-직렬화-serialization">직렬화 (Serialization)</a>    <ul>
      <li><a href="#장점" id="markdown-toc-장점">장점</a></li>
      <li><a href="#직렬화-규칙" id="markdown-toc-직렬화-규칙">직렬화 규칙</a></li>
      <li><a href="#unity-json-직렬화" id="markdown-toc-unity-json-직렬화">Unity Json 직렬화</a></li>
    </ul>
  </li>
  <li><a href="#출처" id="markdown-toc-출처">출처</a></li>
</ul>

<h1 id="직렬화-serialization">직렬화 (Serialization)</h1>
<blockquote>
  <p>오브젝트나 연결된 오브젝트의 묶음(오브젝트 그래프)을 바이트 스트림으로 변환하는 과정</p>
</blockquote>

<p>복잡한 데이터를 일렬로 세우기 때문에 직렬화 라고 한다. 반대는 역직렬화(Deserialization)</p>

<h2 id="장점">장점</h2>
<ul>
  <li>현재 프로그래밍의 상태를 저장하고 필요할 때에 복원 가능. (게임의 저장)</li>
  <li>현재 객체의 정보를 클립보드에 복사해서 다른 프로그램에 전송 가능.</li>
  <li>네트워크를 통해 현재 프로그램의 상태를 다른 컴퓨터에 복원 가능. (멀티플레이어 게임)</li>
  <li>데이터 압축, 암호화를 통해 데이터를 효율적이고 안전하게 보관 가능.</li>
</ul>

<h2 id="직렬화-규칙">직렬화 규칙</h2>
<ul>
  <li>public이거나 <code class="language-plaintext highlighter-rouge">SerializeField</code> 속성이 있어야 함</li>
  <li>정적이 아님</li>
  <li>상수가 아님</li>
  <li>읽기 전용이 아님</li>
  <li>직렬화 가능할 필드 타입이 있어야 함
    <ul>
      <li>기본 데이터 형식</li>
      <li>열거형 타입(32 바이트 이하)</li>
      <li>고정 크기 버퍼</li>
      <li>Unity 빌트인 타입</li>
      <li><code class="language-plaintext highlighter-rouge">Serializable</code> 속성이 있는 커스텀 구조체</li>
      <li>UnityEngine.Ojbect에서 파생된 오브젝트에 대한 레퍼런스</li>
      <li><code class="language-plaintext highlighter-rouge">Serializable</code> 속성이 있는 커스텀 클래스</li>
      <li>위에서 언급한 필드 타입의 배열</li>
      <li>위에서 언급한 필드 타입의 List <T></T></li>
    </ul>
  </li>
</ul>

<h2 id="unity-json-직렬화">Unity Json 직렬화</h2>
<blockquote>
  <p>Json을 유니티에서 직렬화 할 때는 JsonUtility 클래스를 사용할 수 있다. JsonUtility는 Unity에서 지원하는 Json 데이터 처리 클래스.</p>
</blockquote>

<ul>
  <li>사용 조건
    <ul>
      <li>직렬화하려는 데이터가 <em>구조화</em>된 데이터여야 한다. 즉 저장하려는 변수를 클래스나 구조체로 표현해야 함</li>
      <li>Monobehavior 혹은 ScriptableObject를 상속받은 클래스 이거나, [Serialzable] 속성을 가진 클래스여야 함</li>
      <li>단순 변수나 배열은 직렬화하지 못하며, 클래스 혹은 구조체를 사용하여 나타야 함</li>
    </ul>
  </li>
</ul>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Json 데이터에 저장하려는 변수를 설명하는 클래스 혹은 구조를 만들기</span>
<span class="p">[</span><span class="n">Serializable</span><span class="p">]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">MyClass</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="n">level</span><span class="p">;</span>
    <span class="k">public</span> <span class="kt">float</span> <span class="n">timeElapsed</span><span class="p">;</span>
    <span class="k">public</span> <span class="kt">string</span> <span class="n">playerName</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1">// 클래스의 인스턴스를 생성하고 초기화</span>
<span class="n">MyClass</span> <span class="n">myObject</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">MyClass</span><span class="p">();</span>
<span class="n">myObject</span><span class="p">.</span><span class="n">level</span> <span class="p">=</span> <span class="m">1</span><span class="p">;</span>
<span class="n">myObject</span><span class="p">.</span><span class="n">timeElapsed</span> <span class="p">=</span> <span class="m">47.5f</span><span class="p">;</span>
<span class="n">myObject</span><span class="p">.</span><span class="n">playerName</span> <span class="p">=</span> <span class="s">"Dr Charles Francis"</span><span class="p">;</span>

<span class="c1">// JsonUtility.ToJson() 메소드를 사용해 JSON 포멧으로 직렬화</span>
<span class="kt">string</span> <span class="n">json</span> <span class="p">=</span> <span class="n">JsonUtility</span><span class="p">.</span><span class="nf">ToJson</span><span class="p">(</span><span class="n">myObject</span><span class="p">);</span>
<span class="c1">// json now contains: '{"level":1,"timeElapsed":47.5,"playerName":"Dr Charles Francis"}'</span>

<span class="c1">// 다시 오브젝트로 전환</span>
<span class="n">myObject</span> <span class="p">=</span> <span class="n">JsonUtility</span><span class="p">.</span><span class="n">FromJson</span><span class="p">&lt;</span><span class="n">MyClass</span><span class="p">&gt;(</span><span class="n">json</span><span class="p">);</span>

</code></pre></div></div>

<h1 id="출처">출처</h1>
<ul>
  <li>사이트 : <a href="https://docs.unity3d.com/kr/2021.3/Manual/JSONSerialization.html">Unity Documentation_JSON 직렬화</a></li>
</ul>]]></content><author><name>Jinsoo Lee</name><email>ljs4784@gmail.com</email></author><category term="develop" /><category term="devlog" /><category term="csharp" /><category term="unity" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">[Unreal] 25.언리얼 멀티플레이</title><link href="https://jinlee0206.github.io/develop/Unreal_25.html" rel="alternate" type="text/html" title="[Unreal] 25.언리얼 멀티플레이" /><published>2024-08-25T00:00:00+09:00</published><updated>2024-08-25T00:00:00+09:00</updated><id>https://jinlee0206.github.io/develop/Unreal_25</id><content type="html" xml:base="https://jinlee0206.github.io/develop/Unreal_25.html"><![CDATA[<blockquote>
  <p><span style="font-size: 80%">
본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다 <br />
</span>
<!--more--></p>
</blockquote>

<ul id="markdown-toc">
  <li><a href="#ue-멀티-플레이어-시스템" id="markdown-toc-ue-멀티-플레이어-시스템">UE 멀티 플레이어 시스템</a></li>
  <li><a href="#넷-모드" id="markdown-toc-넷-모드">넷 모드</a>    <ul>
      <li><a href="#standalone" id="markdown-toc-standalone">Standalone</a></li>
      <li><a href="#dedicated-server" id="markdown-toc-dedicated-server">Dedicated Server</a></li>
      <li><a href="#listen-server" id="markdown-toc-listen-server">Listen Server</a></li>
      <li><a href="#client" id="markdown-toc-client">Client</a></li>
    </ul>
  </li>
  <li><a href="#언리얼-엔진의-네트워킹-시나리오" id="markdown-toc-언리얼-엔진의-네트워킹-시나리오">언리얼 엔진의 네트워킹 시나리오</a></li>
  <li><a href="#리플리케이션" id="markdown-toc-리플리케이션">리플리케이션</a></li>
  <li><a href="#언리얼-주요-클래스-생성" id="markdown-toc-언리얼-주요-클래스-생성">언리얼 주요 클래스 생성</a></li>
  <li><a href="#출처" id="markdown-toc-출처">출처</a></li>
</ul>

<!-- <p align = "center">
  <img src ="https://github.com/user-attachments/assets/3b3d3969-f050-4a56-afde-3a731370edfb" width = 520>
</p> -->

<h1 id="ue-멀티-플레이어-시스템">UE 멀티 플레이어 시스템</h1>
<blockquote>
  <p>멀티 플레이어 게임은 동일한 게임의 여러 인스턴스가 동시에 실행되는 것을 목표로 한다</p>
</blockquote>

<ol>
  <li>동일한 시스템의 다른 프로세스</li>
  <li>동일한 로컬 네트워크의 다른 컴퓨터</li>
  <li>인터넷을 통해 서로 다른 위치에 존재하는 플레이어</li>
</ol>

<ul>
  <li>언리얼 엔진의 네트워크 모델에서 플레이어는 서버 연결 상태를 유지하고, 서버는 월드를 신뢰할수 있는 상태로 유지</li>
  <li>서버에서 변경 사항이 발생하면 해당 변경 사항은 <strong>리플리케이션(Replication)</strong> 이라는 프로세스의 일부로 필요에 따라 클라이언트에 전파된다
    <ul>
      <li>리플리케이션 시스템은 게임 코드와 통합되어 멀티 플레이어 게임을 쉽게 개발하도록 해줌</li>
      <li>통신을 통해 토켓을 따로 열거나 패킷을 보내지 않아도 되며, 데이터 직렬화(Serealization) / 인코딩(Encoding) / 바이트 순서 / 타임스탬프 / 재정렬 및 라우팅(Routing) 등을 처리하지 않고, 단순히 해당 프로퍼티를 복제하기를 요구하면 복제되는 시스템</li>
    </ul>
  </li>
</ul>

<hr />

<h1 id="넷-모드">넷 모드</h1>
<blockquote>
  <p>월드의 속성으로 네 가지의 모드(StandAlone / Dedicated Server / Listen Server / Client)가 존재하며, 세 가지 질문 통해 모드를 나눌 수 있다</p>
</blockquote>

<p>월드의 NetMode는 게임 인스턴스가 시작된 방식에 따라 달라진다</p>

<ul>
  <li>Playable
    <ul>
      <li>게임을 플레이할 수 있는가?</li>
      <li>게임 인스턴스에 LocalPlayer가 존재하고, 해당 플레이어의 입력을 처리하고, 월드를 뷰포트로 렌더링하고 있는가?</li>
    </ul>
  </li>
  <li>Autority?
    <ul>
      <li>우리는 서버인가?</li>
      <li>게임 인스턴스에 GameMode 액터가 포함된 World의 정식 사본이 있는가?</li>
    </ul>
  </li>
  <li>Open To Clients?
    <ul>
      <li>(우리가 서버라면) 원격 연결 시도를 위해 열려있는가?</li>
      <li>다른 플레이어가 클라이언트로 참여해 게임을 플레이 할 수 있는가?</li>
    </ul>
    <p align="center">
  <img width="415" alt="240825_NetMode01" src="https://github.com/user-attachments/assets/a0c1c36e-652f-4d73-a26e-34ce82b26cfe" />
</p>
  </li>
</ul>

<h2 id="standalone">Standalone</h2>
<blockquote>
  <p>게임 인스턴스가 로컬로 맵을 로드한 경우, 게임 월드의 넷 모드는 Standalone이 된다.</p>
</blockquote>

<p align="center">
  <img width="420" alt="240825_NetMode_SA" src="https://github.com/user-attachments/assets/c8796d33-1d0d-44ea-a79e-2101564691d2" />
</p>

<ul>
  <li>단일 게임 인스턴스는 서버이자 클라이언트이지만, 단일 플레이어 구성에서 실행되기 때문에 다른 클라이언트가 연결할 수 없다</li>
  <li>URL은 맵 이름 혹은 경로</li>
</ul>

<h2 id="dedicated-server">Dedicated Server</h2>
<blockquote>
  <p>로컬 플레이어와 뷰포트가 없는 게임 인스턴스. 플레이어가 클라이언트로 연결할 수 있는 서버 전용 콘솔 응용 프로그램으로서 작동</p>
</blockquote>

<p align="center">
  <img width="420" alt="240825_NetMode_DS" src="https://github.com/user-attachments/assets/188c363c-8074-405b-91f5-9291de3640da" />
</p>

<ul>
  <li>사운드, 그래픽, 사용자 입력 등 플레이어 관련 기능을 제거하여 효율적인 실행이 가능한 서버</li>
</ul>

<p>깃허브에서 데디케이트 서버를 다운 받아서 사용 할 수 있다</p>

<p><a href="http://www.unrealengine.com/ko/ue-on-github">깃허브 내 언리얼 엔진 계정연결 링크</a></p>

<ul>
  <li>사용 방법
    <ul>
      <li>설치
        <ul>
          <li>깃허브 UE 계정 연동 및 코드 다운로드</li>
          <li><code class="language-plaintext highlighter-rouge">Setup.bat</code> 으로 셋업</li>
          <li><code class="language-plaintext highlighter-rouge">GenerateProjectFiles.bat</code> 으로 솔루션 생성</li>
          <li>엔진 풀코드 전체 빌드 <code class="language-plaintext highlighter-rouge">ctrl + shift + B</code></li>
          <li><code class="language-plaintext highlighter-rouge">UnrealEditor.exe</code>로 실행 (서버 기능도 포함한 언리얼 에디터)</li>
        </ul>
      </li>
      <li>데디케이트 버전으로의 변환
        <ul>
          <li>switch Unreal Engine version</li>
          <li><code class="language-plaintext highlighter-rouge">[프로젝트].Target.cs</code> 버전을 동기화 해준후</li>
          <li><code class="language-plaintext highlighter-rouge">[프로젝트].ServerTarget.cs</code> 서버 타겟에 대한 세팅 후 빌드</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<h2 id="listen-server">Listen Server</h2>
<blockquote>
  <p>유저 중에 한명이 서버가 되는 구조</p>
</blockquote>

<p align="center">
  <img width="420" alt="240825_NetMode_LS" src="https://github.com/user-attachments/assets/9904b1a1-1815-4f70-9f18-97082f9ccec3" />
</p>

<ul>
  <li>맵을 로컬로 로드하지만 경로에 ?Listen 옵션을 추가하여 로드한 경우 Standalone과 동일하지만 다른 클라이언트가 참여할 수도 있다</li>
  <li>URL 은 맵 경로?Listen</li>
</ul>

<h2 id="client">Client</h2>
<blockquote>
  <p>게임 인스턴스가 원격 서버로 연결된 경우</p>
</blockquote>

<p align="center">
  <img width="420" alt="240825_NetMode_C" src="https://github.com/user-attachments/assets/de304085-12ee-4e4b-a651-8abd64117713" />
</p>

<ul>
  <li>게임은 로컬 플레이어가 플레이 할 수 있지만, 서버 요청에 따라 월드가 업데이트 된다</li>
  <li>서버가 아닌 유일한 모드로 서버측의 로직이 실행되지 않음</li>
  <li>URL은 IP 주소</li>
</ul>

<hr />
<h1 id="언리얼-엔진의-네트워킹-시나리오">언리얼 엔진의 네트워킹 시나리오</h1>

<p align="center">
  <img width="420" alt="240825_NW01" src="https://github.com/user-attachments/assets/e8451197-cefd-4e04-918a-04475544921c" />
</p>

<ul>
  <li>싱글 플레이어
    <ul>
      <li>하나의 게임 인스턴스가 있고, 해당 월드는 Standalone 모드에서 실행 됨</li>
    </ul>
  </li>
  <li>멀티 플레이어
    <ul>
      <li>각각 고유한 게임 인스턴스들이 있고, 고유한 World 복사본이 있는 여러 프로세스가 있다</li>
      <li>이러한 프로세스 중 하나는 Listen Server 또는 Dedicated Server</li>
    </ul>
  </li>
</ul>

<h1 id="리플리케이션">리플리케이션</h1>
<blockquote>
  <p>서버와 클라이언트 사이에서 데이터와 명령을 주고 받는 프로세스</p>
</blockquote>

<p>액터 업데이트 방식은 크게 두 가지</p>
<ol>
  <li>프로퍼티 업데이트</li>
  <li>RPC(Remote Procedure Call)</li>
</ol>

<hr />

<h1 id="언리얼-주요-클래스-생성">언리얼 주요 클래스 생성</h1>

<ul>
  <li><em>GameMode</em> : 서버에만 생성</li>
  <li>PlayerController : 서버, 클라이언트 생성</li>
  <li>PlayerPawn : 서버, 클라이언트 생성 //</li>
  <li>PlayerState : 서버, 클라이언트 생성 //</li>
  <li>PlayerAnimInstance : 서버, 클라이언트 생성</li>
  <li>GameState : 서버, 클라이언트 생성</li>
</ul>

<hr />

<h1 id="출처">출처</h1>
<ul>
  <li>블로그 : <a href="https://velog.io/@doorbals_512/%EC%96%B8%EB%A6%AC%EC%96%BC-%EC%97%94%EC%A7%84-%EB%A9%80%ED%8B%B0-%ED%94%8C%EB%A0%88%EC%9D%B4%EC%96%B4-%EC%8B%9C%EC%8A%A4%ED%85%9C-Part1">doorbals_512.log</a></li>
  <li>블로그 : <a href="https://velog.io/@seok9403/%EC%96%B8%EB%A6%AC%EC%96%BC-%EB%A9%80%ED%8B%B0%ED%94%8C%EB%A0%88%EC%9D%B4-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0">MoOrY.log</a></li>
  <li>유튜브 : <a href="https://youtu.be/JOJP0CvpB8w?si=p7HzWbcR-gGWCvJL">Multiplayer in Unreal Engine: How to Understand Network Replication</a></li>
</ul>]]></content><author><name>Jinsoo Lee</name><email>ljs4784@gmail.com</email></author><category term="develop" /><category term="cpp" /><category term="unreal" /><summary type="html"><![CDATA[본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다]]></summary></entry><entry><title type="html">[Unreal] 24.서버</title><link href="https://jinlee0206.github.io/develop/Unreal_24.html" rel="alternate" type="text/html" title="[Unreal] 24.서버" /><published>2024-08-24T00:00:00+09:00</published><updated>2024-08-24T00:00:00+09:00</updated><id>https://jinlee0206.github.io/develop/Unreal_24</id><content type="html" xml:base="https://jinlee0206.github.io/develop/Unreal_24.html"><![CDATA[<blockquote>
  <p><span style="font-size: 80%">
본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다 </span></p>
</blockquote>

<!--more-->

<ul id="markdown-toc">
  <li><a href="#스레드" id="markdown-toc-스레드">스레드</a>    <ul>
      <li><a href="#과제" id="markdown-toc-과제">과제</a></li>
    </ul>
  </li>
</ul>

<!-- <p align = "center">
  <img src ="https://github.com/user-attachments/assets/3b3d3969-f050-4a56-afde-3a731370edfb" width = 520>
</p> -->

<h1 id="스레드">스레드</h1>
<blockquote>
  <p><em>프로세스를 여러 개의 조각으로 나눈 것</em>, 프로세스는 하나 이상의 스레드로 이루어져 있다</p>
</blockquote>

<ul>
  <li>언리얼은 기본적으로 멀티 스레드를 지원하고 두 개의 메인 스레드로 돌고 있다. 하나는 <strong>게임 스레드</strong> 이고 다른 하나는 <strong>렌더 스레드</strong> 이다</li>
  <li>커스텀 <em>Recieve Thread</em>를 만들어서 동작시킬 예정
    <ul>
      <li>패킷 큐를 이용해서 언리얼 스레드와 커스텀 리시브 스레드를 연결할 것</li>
      <li>큐에 패킷을 넣고 뺄 때, 동기화가 되게 끔 구현</li>
    </ul>
  </li>
</ul>

<h2 id="과제">과제</h2>
<ul>
  <li>리스트, 스택, 큐 구현해보기</li>
</ul>]]></content><author><name>Jinsoo Lee</name><email>ljs4784@gmail.com</email></author><category term="develop" /><category term="cpp" /><category term="unreal" /><summary type="html"><![CDATA[본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다]]></summary></entry><entry><title type="html">[Unreal] 23.서버</title><link href="https://jinlee0206.github.io/develop/Unreal_23.html" rel="alternate" type="text/html" title="[Unreal] 23.서버" /><published>2024-08-18T00:00:00+09:00</published><updated>2024-08-24T00:00:00+09:00</updated><id>https://jinlee0206.github.io/develop/Unreal_23</id><content type="html" xml:base="https://jinlee0206.github.io/develop/Unreal_23.html"><![CDATA[<blockquote>
  <p><span style="font-size: 80%">
본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다 </span></p>
</blockquote>

<!--more-->

<ul id="markdown-toc">
  <li><a href="#서버" id="markdown-toc-서버">서버</a></li>
  <li><a href="#스레드" id="markdown-toc-스레드">스레드</a>    <ul>
      <li><a href="#네트워크-매니저" id="markdown-toc-네트워크-매니저">네트워크 매니저</a>        <ul>
          <li><a href="#networkmanagercpp" id="markdown-toc-networkmanagercpp">NetworkManager.cpp</a></li>
          <li><a href="#networkinfoh" id="markdown-toc-networkinfoh">NetworkInfo.h</a></li>
          <li><a href="#networksessionh" id="markdown-toc-networksessionh">NetworkSession.h</a></li>
          <li><a href="#networksessioncpp" id="markdown-toc-networksessioncpp">NetworkSession.cpp</a></li>
          <li><a href="#gameinstancecpp" id="markdown-toc-gameinstancecpp">GameInstance.cpp</a></li>
          <li><a href="#selectgamemodecpp" id="markdown-toc-selectgamemodecpp">SelectGameMode.cpp</a></li>
        </ul>
      </li>
      <li><a href="#과제" id="markdown-toc-과제">과제</a></li>
    </ul>
  </li>
</ul>

<!-- <p align = "center">
  <img src ="https://github.com/user-attachments/assets/3b3d3969-f050-4a56-afde-3a731370edfb" width = 520>
</p> -->

<h1 id="서버">서버</h1>
<blockquote>
  <p>서비스를 제공하는 소프트웨어가 실행되는 컴퓨터</p>
</blockquote>

<h1 id="스레드">스레드</h1>
<blockquote>
  <p><em>프로세스를 여러 개의 조각으로 나눈 것</em>, 프로세스는 하나 이상의 스레드로 이루어져 있다</p>
</blockquote>

<ul>
  <li>언리얼은 기본적으로 멀티 스레드를 지원하고 두 개의 메인 스레드로 돌고 있다. 하나는 <strong>게임 스레드</strong> 이고 다른 하나는 <strong>렌더 스레드</strong> 이다</li>
  <li>커스텀 <em>Recieve Thread</em>를 만들어서 동작시킬 예정
    <ul>
      <li>PQ를 이용해서 언리얼 스레드와 커스텀 리시브 스레드를 연결할 것</li>
      <li>Queue에 패킷을 넣고 뺄 때, 동기화가 되게 끔 구현</li>
    </ul>
  </li>
</ul>

<h2 id="네트워크-매니저">네트워크 매니저</h2>
<blockquote>
  <p>여러 개의 소켓을 관리하기 위함</p>
</blockquote>

<p>소켓은 각 운영체제마다 사용하는 것이 달라질 수 있다</p>

<ul>
  <li>모듈 추가 : <strong>Networking</strong>, <strong>Sockets</strong>, <strong>HTTP</strong>, <strong>Json</strong></li>
  <li><code class="language-plaintext highlighter-rouge">GameInfo.h</code>에 해더 추가
    <ul>
      <li>HTTP 통신을 할 수 있도록 Http 헤더도 추가 (모바일 기반 게임 통신이 주로 사용)</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">DefaultEngine.ini</code>
    <ul>
      <li>HTTP 관련된 내용을 커스텀으로 추가할 수 있다</li>
    </ul>
  </li>
</ul>

<h3 id="networkmanagercpp">NetworkManager.cpp</h3>
<blockquote>
  <p>여러 개의 소켓 관리를 위한 네트워크 매니저 클래스</p>
</blockquote>

<ul>
  <li><code class="language-plaintext highlighter-rouge">NetworkManager</code> 클래스 생성 -&gt; <em>싱글톤을 이용해 제작할 예정</em>
    <ul>
      <li>어떠한 클래스도 상속받지 않는 클래스이므로 메모리 관리를 직접 해주어야 한다</li>
    </ul>
  </li>
  <li>생성자 <code class="language-plaintext highlighter-rouge">CNetworkManager</code>
    <ul>
      <li>싱글톤 클래스 생성 및 초기화</li>
    </ul>
  </li>
  <li>소멸자 <code class="language-plaintext highlighter-rouge">~CNetworkManager</code></li>
  <li>맵으로 네크워크 세션들을 매핑한 후 저장한다
    <ul>
      <li>세션을 체크하는 함수</li>
      <li>연결하는 함수</li>
      <li>패킷 전송/받는 함수</li>
      <li>세션을 찾는 함수</li>
    </ul>
  </li>
</ul>

<h3 id="networkinfoh">NetworkInfo.h</h3>
<blockquote>
  <p>네트워크 정보를 담고 있는 헤더 파일</p>
</blockquote>

<h3 id="networksessionh">NetworkSession.h</h3>
<blockquote>
  <p>언리얼 기능 중 네트워크 기능을 편하게 사용하기 위해 만든 커스텀 모듈</p>
</blockquote>

<ul>
  <li>NetworkManager와 friend 처리</li>
  <li>멤버 변수
    <ul>
      <li>소켓 이름</li>
      <li>생성된 소켓의 주소</li>
      <li>연결 상태 boolean 값</li>
      <li>uint8 타입의 전송패킷, 수신패킷 배열</li>
    </ul>
  </li>
  <li>멤버 함수
    <ul>
      <li><code class="language-plaintext highlighter-rouge">Connect(const FString&amp; IpAddr, int32 Port)</code></li>
      <li><code class="language-plaintext highlighter-rouge">Close()</code> 연결 해제</li>
      <li>bool 타입 함수 <code class="language-plaintext highlighter-rouge">Recieve(int32&amp; PacketHeader, int32&amp; Size, uint8* Packet)</code>
        <ul>
          <li>패킷헤더(이름표)에 데이터 사이즈를 알려주는 Size 변수를 전달하고, 실제 데이터는 Packet에 저장</li>
        </ul>
      </li>
      <li>bool 타입 함수 <code class="language-plaintext highlighter-rouge">Send(int32 PacketHeader, int32 Size, uint8* Packet)</code></li>
    </ul>
  </li>
</ul>

<h3 id="networksessioncpp">NetworkSession.cpp</h3>

<ul>
  <li>PLATFORM_SOCKETSUBSYSTEM 다양한 플랫폼의 소켓 서브시스템을 받아와서 해당 되는(사용할) 소켓을 따로 만들 수 있다</li>
  <li>연결 해제 시 소켓을 직접 삭제 해줘야 한다</li>
  <li>Receive
    <ul>
      <li>하나의 큰 데이터 패킷으로 온 것을 FMemory의 Memcpy 함수를 통해 내가 원하는 정보로 변환할 수 있다</li>
    </ul>
  </li>
</ul>

<p align="center">
  <img src="https://github.com/user-attachments/assets/e9bedbee-0f07-42b4-b024-b990d6819fbc" width="320" />
</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">CNetworkSession</span><span class="o">::</span><span class="n">Connect</span><span class="p">(</span><span class="k">const</span> <span class="n">FString</span><span class="o">&amp;</span> <span class="n">IpAddr</span><span class="p">,</span> <span class="n">int32</span> <span class="n">Port</span><span class="p">)</span>
<span class="p">{</span>
  <span class="n">mSocket</span> <span class="o">=</span> <span class="n">ISocketSubSystem</span><span class="o">::</span><span class="n">GET</span><span class="p">(</span><span class="n">PLATFORM_SOCKETSUBSYSTEM</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">CreateSocket</span><span class="p">(</span><span class="n">NAME_Stream</span><span class="p">,</span> <span class="n">TEXT</span><span class="p">(</span><span class="s">"Default"</span><span class="p">),</span> <span class="nb">false</span><span class="p">);</span>

  <span class="c1">// 문자열로 들어 온 주소를 실제 주소로 만들어준다</span>
  <span class="n">FIPv4Address</span> <span class="n">ip</span><span class="p">;</span>
  <span class="n">FIPv4Address</span><span class="o">::</span><span class="n">Parse</span><span class="p">(</span><span class="n">IPAddr</span><span class="p">,</span> <span class="n">ip</span><span class="p">);</span>

  <span class="c1">// IP와 Port를 합친 최종 주소를 만들어 준다</span>
  <span class="n">TSharedRef</span><span class="o">&lt;</span><span class="n">FInternetAddr</span><span class="o">&gt;</span> <span class="n">Add</span> <span class="o">=</span> <span class="n">ISocketSubSystem</span><span class="o">::</span><span class="n">Get</span><span class="p">(</span><span class="n">PLATFORM_SOCKETSUBSYSTEM</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">CreateInternetAddr</span><span class="p">();</span>

  <span class="n">Addr</span><span class="o">-&gt;</span><span class="n">SetIP</span><span class="p">(</span><span class="n">ip</span><span class="p">.</span><span class="n">Value</span><span class="p">);</span>
  <span class="n">Addr</span><span class="o">-&gt;</span><span class="n">SetPort</span><span class="p">(</span><span class="n">Port</span><span class="p">);</span>

  <span class="n">mConnect</span> <span class="o">=</span> <span class="n">mSocket</span><span class="o">-&gt;</span><span class="n">Connect</span><span class="p">(</span><span class="o">*</span><span class="n">Addr</span><span class="p">);</span>

  <span class="k">return</span> <span class="n">mConnect</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="gameinstancecpp">GameInstance.cpp</h3>
<blockquote>
  <p>게임인스턴스를 활용해 네트워크 매니저 사용</p>
</blockquote>

<p>언제 네트워크 매니저로 관리되는 채팅 소켓을 활성화 할 지가 중요 <br />
게임 선택 모드가 종료될 때, 채팅 서버를 연결할 예정</p>

<h3 id="selectgamemodecpp">SelectGameMode.cpp</h3>
<ul>
  <li>[캐릭터 선택] - [<strong>SelectGameMode</strong> 제거] - [채팅 서버 연결]
    <ul>
      <li><code class="language-plaintext highlighter-rouge">SelectGameMode</code>의 <code class="language-plaintext highlighter-rouge">EndPlay()</code>함수를 재정의
        <ul>
          <li>NetworkManager 인스턴스 만들고 <code class="language-plaintext highlighter-rouge">Connect()</code></li>
          <li>채팅 서버와 통신할 스레드를 생성한 후 연결한다</li>
          <li>ReceiveThread에서 사용할 Session을 넣어준다</li>
          <li>스레드를 동작시킨다</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<h2 id="과제">과제</h2>
<ul>
  <li>리스트, 스택, 큐 구현해보기</li>
</ul>]]></content><author><name>Jinsoo Lee</name><email>ljs4784@gmail.com</email></author><category term="develop" /><category term="cpp" /><category term="unreal" /><summary type="html"><![CDATA[본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다]]></summary></entry><entry><title type="html">[Unreal] 22.시네마틱</title><link href="https://jinlee0206.github.io/develop/Unreal_22.html" rel="alternate" type="text/html" title="[Unreal] 22.시네마틱" /><published>2024-08-17T00:00:00+09:00</published><updated>2024-08-22T00:00:00+09:00</updated><id>https://jinlee0206.github.io/develop/Unreal_22</id><content type="html" xml:base="https://jinlee0206.github.io/develop/Unreal_22.html"><![CDATA[<blockquote>
  <p><span style="font-size: 80%">
본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다 </span></p>
</blockquote>

<!--more-->

<ul id="markdown-toc">
  <li><a href="#시네마틱" id="markdown-toc-시네마틱">시네마틱</a>    <ul>
      <li><a href="#무비-렌더-큐" id="markdown-toc-무비-렌더-큐">무비 렌더 큐</a></li>
      <li><a href="#레벨-시퀀스" id="markdown-toc-레벨-시퀀스">레벨 시퀀스</a>        <ul>
          <li><a href="#페이드-트랙" id="markdown-toc-페이드-트랙">페이드 트랙</a></li>
          <li><a href="#카메라-액터" id="markdown-toc-카메라-액터">카메라 액터</a></li>
          <li><a href="#시네-카메라-액터" id="markdown-toc-시네-카메라-액터">시네 카메라 액터</a></li>
          <li><a href="#릭-레일" id="markdown-toc-릭-레일">릭 레일</a></li>
          <li><a href="#일반-액터" id="markdown-toc-일반-액터">일반 액터</a></li>
          <li><a href="#카메라-셰이크" id="markdown-toc-카메라-셰이크">카메라 셰이크</a></li>
        </ul>
      </li>
      <li><a href="#트리거" id="markdown-toc-트리거">트리거</a></li>
    </ul>
  </li>
</ul>

<!-- <p align = "center">
  <img src ="https://github.com/user-attachments/assets/3b3d3969-f050-4a56-afde-3a731370edfb" width = 520>
</p> -->

<h1 id="시네마틱">시네마틱</h1>

<h2 id="무비-렌더-큐">무비 렌더 큐</h2>
<blockquote>
  <p>언리얼 영상 렌더 시스템. 플러그인에서 추가해서 사용 가능</p>
</blockquote>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Apple ProRes Media</code> 플러그인 추가</li>
  <li>코덱 지정</li>
  <li>렌더</li>
</ul>

<h2 id="레벨-시퀀스">레벨 시퀀스</h2>
<blockquote>
  <p>시네마틱 영상, 컷신 등의 제작을 위한 편집기. 간단한 렌더링 효과도 시퀀스로 만들어 두고 사용할 수 있다</p>
</blockquote>

<p align="center">
  <img src="https://github.com/user-attachments/assets/646dae57-40cf-4071-b517-57f6a2219011" width="180" />
</p>

<ul>
  <li>월드 상의 물체의 애니메이션 효과를 부여해주는 형식으로도 활용 가능</li>
</ul>

<h3 id="페이드-트랙">페이드 트랙</h3>
<blockquote>
  <p>간단한 페이드 인/아웃 효과를 만들어서 이 시퀀스를 간단한 렌더링 효과처럼 사용할 수도 있다</p>
</blockquote>

<h3 id="카메라-액터">카메라 액터</h3>
<ul>
  <li>트랜스폼
    <ul>
      <li>트랜스폼 컴포넌트를 부착하고 트랜스폼을 조정하여서 카메라 액터의 트랜스폼 조정 해줄 수 있음</li>
    </ul>
  </li>
</ul>

<h3 id="시네-카메라-액터">시네 카메라 액터</h3>
<blockquote>
  <p>영화와 같은 연출을 사용할 수 있게끔 만들어 주는 고급 카메라 기능 지원하는 액터</p>
</blockquote>

<h3 id="릭-레일">릭 레일</h3>
<ul>
  <li>스플라인 컴포넌트를 활용해 부드럽게 곡선 형태의 움직임을 만들어 원하는 경로를 만들어 낼 수 있음</li>
  <li>카메라를 릭 레일의 자식으로 만들어 레일 상 위치를 따라가게 끔 지정</li>
  <li>포인트가 되는 흰색 지점의 기울기를 조정하여 작업 가능</li>
</ul>

<h3 id="일반-액터">일반 액터</h3>
<ul>
  <li>스켈레탈 메쉬 컴포넌트 추가 가능
    <ul>
      <li>애니메이션 추가 가능</li>
    </ul>
  </li>
</ul>

<h3 id="카메라-셰이크">카메라 셰이크</h3>

<h2 id="트리거">트리거</h2>
<blockquote>
  <p>특정 상황에 도달하였을 때, 실행되는 이벤트를 만들 수 있다</p>
</blockquote>

<ul>
  <li>트리거의 모양은 상황에 따라 달라질 수 있다
    <ul>
      <li>각 충돌체(박스, 캡슐, 스피어 등)의 공통 부모는 <code class="language-plaintext highlighter-rouge">UShapeComponent</code>이므로 UShapeComponent를 기본 변수로 선언하여 자식 클래스로 만든 후 다운 캐스팅해서 사용할 수 있다</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">TriggerOverlap()</code>과 <code class="language-plaintext highlighter-rouge">TriggerOverlapEnd()</code> 함수를 각 클래스에서 재정의</li>
  <li>오버랩 시 <code class="language-plaintext highlighter-rouge">AddDynamic()</code> 함수를 이용해 재정의한 오버랩 함수를 등록</li>
  <li><em>Trigger</em> 프로파일 생성
    <ul>
      <li>플레이어와 에너미와 각각 오버랩</li>
    </ul>
  </li>
  <li><em>TriggerPlayer</em> 프로파일 생성
    <ul>
      <li>플레이어 전용 트리거, 트리거를 부착할 오브젝트에 설정하는 프로파일</li>
      <li>쿼리 온리(충돌 필요없음)</li>
      <li>플레이어 채널과도 오버랩 설정</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">GameInfo.h</code>에 enum class 타입으로 <code class="language-plaintext highlighter-rouge">TriggerOption</code>을 생성</li>
</ul>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Trigger.h</span>
<span class="n">TObjectPtr</span><span class="o">&lt;</span><span class="n">UShapeComponent</span><span class="o">&gt;</span> <span class="n">mCollider</span><span class="p">;</span>

<span class="c1">// TriggerBaseBox.cpp</span>
<span class="n">mCollider</span> <span class="o">=</span> <span class="n">CreateDefaultSubobject</span><span class="o">&lt;</span><span class="n">UBoxComponent</span><span class="o">&gt;</span><span class="p">(</span><span class="n">TEXT</span><span class="p">(</span><span class="s">"Body"</span><span class="p">));</span>
<span class="n">SetRootComponent</span><span class="p">(</span><span class="n">mCollier</span><span class="p">);</span>
</code></pre></div></div>]]></content><author><name>Jinsoo Lee</name><email>ljs4784@gmail.com</email></author><category term="develop" /><category term="cpp" /><category term="unreal" /><summary type="html"><![CDATA[본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다]]></summary></entry><entry><title type="html">[C++] 프로그래머스 : 단어변환</title><link href="https://jinlee0206.github.io/develop/Programmers-%EB%8B%A8%EC%96%B4%EB%B3%80%ED%99%98.html" rel="alternate" type="text/html" title="[C++] 프로그래머스 : 단어변환" /><published>2024-08-15T00:00:00+09:00</published><updated>2024-08-15T00:00:00+09:00</updated><id>https://jinlee0206.github.io/develop/Programmers-%EB%8B%A8%EC%96%B4%EB%B3%80%ED%99%98</id><content type="html" xml:base="https://jinlee0206.github.io/develop/Programmers-%EB%8B%A8%EC%96%B4%EB%B3%80%ED%99%98.html"><![CDATA[<blockquote>
  <p><span style="font-size: 80%">
인프런에 있는 큰돌님의 강의 10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트를 듣고 정리한 필기입니다.</span></p>
</blockquote>

<!--more-->

<ul id="markdown-toc">
  <li><a href="#문제" id="markdown-toc-문제">문제</a></li>
  <li><a href="#제한사항" id="markdown-toc-제한사항">제한사항</a></li>
  <li><a href="#입출력-예" id="markdown-toc-입출력-예">입출력 예</a></li>
  <li><a href="#알고리즘" id="markdown-toc-알고리즘">알고리즘</a></li>
  <li><a href="#풀이" id="markdown-toc-풀이">풀이</a>    <ul>
      <li><a href="#백트래킹-수도-코드" id="markdown-toc-백트래킹-수도-코드">백트래킹 수도 코드</a></li>
      <li><a href="#dfs의-종료조건과-매개변수" id="markdown-toc-dfs의-종료조건과-매개변수">DFS의 종료조건과 매개변수</a></li>
      <li><a href="#효율적인-코드" id="markdown-toc-효율적인-코드">효율적인 코드</a></li>
    </ul>
  </li>
  <li><a href="#코드" id="markdown-toc-코드">코드</a></li>
  <li><a href="#평가" id="markdown-toc-평가">평가</a></li>
</ul>

<h2 id="문제">문제</h2>

<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/43163">프로그래머스 : 단어변환(링크)</a></p>

<p>두 개의 단어 begin, target과 단어의 집합 words가 있습니다. 아래와 같은 규칙을 이용하여 begin에서 target으로 변환하는 가장 짧은 변환 과정을 찾으려고 합니다.</p>

<ol>
  <li>한 번에 한 개의 알파벳만 바꿀 수 있습니다.</li>
  <li>words에 있는 단어로만 변환할 수 있습니다.</li>
</ol>

<p>예를 들어 begin이 “hit”, target가 “cog”, words가 [“hot”,”dot”,”dog”,”lot”,”log”,”cog”]라면 “hit” -&gt; “hot” -&gt; “dot” -&gt; “dog” -&gt; “cog”와 같이 4단계를 거쳐 변환할 수 있습니다.</p>

<p>두 개의 단어 begin, target과 단어의 집합 words가 매개변수로 주어질 때, 최소 몇 단계의 과정을 거쳐 begin을 target으로 변환할 수 있는지 return 하도록 solution 함수를 작성해주세요.</p>

<h2 id="제한사항">제한사항</h2>
<ul>
  <li>각 단어는 알파벳 소문자로만 이루어져 있습니다.</li>
  <li>각 단어의 길이는 3 이상 10 이하이며 모든 단어의 길이는 같습니다.</li>
  <li>words에는 3개 이상 50개 이하의 단어가 있으며 중복되는 단어는 없습니다.</li>
  <li>begin과 target은 같지 않습니다.</li>
  <li>변환할 수 없는 경우에는 0를 return 합니다.</li>
</ul>

<h2 id="입출력-예">입출력 예</h2>

<table>
  <thead>
    <tr>
      <th><strong>begin</strong></th>
      <th><strong>target</strong></th>
      <th><strong>words</strong></th>
      <th><strong>return</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>“hit”</td>
      <td>“cog”</td>
      <td>[“hot”, “dot”, “dog”, “lot”, “log”, “cog”]</td>
      <td>4</td>
    </tr>
    <tr>
      <td>“hit”</td>
      <td>“cog”</td>
      <td>[“hot”, “dot”, “dog”, “lot”, “log”]</td>
      <td>0</td>
    </tr>
  </tbody>
</table>

<h2 id="알고리즘">알고리즘</h2>
<ol>
  <li>DFS</li>
  <li>백트래킹</li>
</ol>

<h2 id="풀이">풀이</h2>
<ul>
  <li>하나의 줄기를 탐색해가며 변환 단계의 최소 값을 구해 나가면 된다
    <ul>
      <li><strong>하나의 줄기 탐색</strong> =&gt; <strong>DFS</strong></li>
      <li>한번 사용한 단어 다시 사용하지 않는다 (최소값 구하기)</li>
      <li>탐색함수를 재귀적으로 호출
        <ul>
          <li>종료 조건 세우기</li>
        </ul>
      </li>
      <li><code class="language-plaintext highlighter-rouge">target</code> 문자열과 동일하게 변환이 완료 되어 재귀 호출이 종료된 경우 다른 최소 경로의 변환 과정이 있을 수 있기 때문에 <em>해당 탐색 과정에서 다시 가장 가까운 갈림길로 돌아와서(Back-Tracking) 다른 방향으로 다시 탐색 진행 한다</em></li>
    </ul>
  </li>
  <li>한 글자만 다른 단어인지 판별하는 함수 작성</li>
</ul>

<h3 id="백트래킹-수도-코드">백트래킹 수도 코드</h3>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span> <span class="n">words</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// 1. 방문 처리</span>
    <span class="n">visited</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
    <span class="c1">// 2. 재귀 호출, 단계 증가 </span>
    <span class="n">dfs</span><span class="p">(...</span> <span class="p">,</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
    <span class="c1">// 3. 백트래킹(방문 처리 해제) 후 다음 분기점부터 다시 탐색</span>
    <span class="n">visited</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="dfs의-종료조건과-매개변수">DFS의 종료조건과 매개변수</h3>
<ul>
  <li>종료조건(기저사례)
    <ul>
      <li>탐색 중인 단어와 <code class="language-plaintext highlighter-rouge">target</code>단어가 같아졌을 때</li>
    </ul>
  </li>
</ul>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="n">current</span> <span class="o">==</span> <span class="n">target</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li>재귀함수의 매개변수
    <ul>
      <li>현재 탐색 중인 단어가 매개변수로 주어져야지 종료조건으로써 참조할 수 있다</li>
      <li>단어 변환이 몇 번 일어 났는지 체크할 변수 (최소값 비교를 위해)</li>
    </ul>
  </li>
</ul>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">dfs</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">current</span><span class="p">,</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;&amp;</span> <span class="n">words</span><span class="p">,</span> <span class="kt">int</span> <span class="n">step</span><span class="p">);</span>
</code></pre></div></div>

<h3 id="효율적인-코드">효율적인 코드</h3>
<p>현재 갱신하는 중인 최소 값 step이 만약 answer(항상 최소 값으로 갱신) 보다 크다면 해당 노드는 탐색할 필요가 없다</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">answer</span> <span class="o">=</span> <span class="n">min</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span> <span class="n">step</span><span class="p">);</span>
</code></pre></div></div>

<h2 id="코드">코드</h2>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// 프로그래머스 단어변환 Lv.3</span>
<span class="c1">// DFS, 백트래킹</span>
<span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="kt">int</span> <span class="n">answer</span> <span class="o">=</span> <span class="mi">50</span><span class="p">;</span>
<span class="kt">bool</span> <span class="n">visited</span><span class="p">[</span><span class="mi">50</span><span class="p">];</span>

<span class="kt">bool</span> <span class="nf">check_diff</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">cnt</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">a</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">if</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">b</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
        <span class="p">{</span>
            <span class="n">cnt</span><span class="o">++</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="k">if</span><span class="p">(</span><span class="n">cnt</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
    <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">dfs</span><span class="p">(</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">current</span><span class="p">,</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;&amp;</span> <span class="n">words</span><span class="p">,</span> <span class="kt">int</span> <span class="n">step</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span><span class="p">(</span><span class="n">answer</span> <span class="o">&lt;=</span> <span class="n">step</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
    
    <span class="k">if</span><span class="p">(</span><span class="n">current</span> <span class="o">==</span> <span class="n">target</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">answer</span> <span class="o">=</span> <span class="n">min</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span> <span class="n">step</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span> <span class="n">words</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">if</span><span class="p">(</span><span class="n">check_diff</span><span class="p">(</span><span class="n">current</span><span class="p">,</span> <span class="n">words</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">visited</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
        <span class="p">{</span>
            <span class="n">visited</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
            <span class="n">dfs</span><span class="p">(</span><span class="n">words</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">target</span><span class="p">,</span> <span class="n">words</span><span class="p">,</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
            <span class="n">visited</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>    
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="n">solution</span><span class="p">(</span><span class="n">string</span> <span class="n">begin</span><span class="p">,</span> <span class="n">string</span> <span class="n">target</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">words</span><span class="p">)</span> <span class="p">{</span>   
    <span class="n">dfs</span><span class="p">(</span><span class="n">begin</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">words</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    
    <span class="k">if</span><span class="p">(</span><span class="n">answer</span> <span class="o">==</span> <span class="mi">50</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
    
    <span class="k">return</span> <span class="n">answer</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="평가">평가</h2>
<ul>
  <li>DFS 문제는 종료조건(기저사례)와 DFS의 매개변수 설정이 중요</li>
  <li>DFS, BFS 문제 중 백트래킹이 필요한 문제 중 기본적인 템플릿</li>
  <li>효율적인 코드를 위해 이미 최소 값이 안되는 탐색 노드는 계산하지 않는 코드를 사용한 것도 잘 지켜보기</li>
</ul>]]></content><author><name>Jinsoo Lee</name><email>ljs4784@gmail.com</email></author><category term="develop" /><category term="cpp" /><category term="algorithm" /><summary type="html"><![CDATA[인프런에 있는 큰돌님의 강의 10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트를 듣고 정리한 필기입니다.]]></summary></entry><entry><title type="html">[Unreal] 21.인트로</title><link href="https://jinlee0206.github.io/develop/Unreal_21.html" rel="alternate" type="text/html" title="[Unreal] 21.인트로" /><published>2024-08-11T00:00:00+09:00</published><updated>2024-08-21T00:00:00+09:00</updated><id>https://jinlee0206.github.io/develop/Unreal_21</id><content type="html" xml:base="https://jinlee0206.github.io/develop/Unreal_21.html"><![CDATA[<blockquote>
  <p><span style="font-size: 80%">
본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다 </span></p>
</blockquote>

<!--more-->

<ul id="markdown-toc">
  <li><a href="#인트로" id="markdown-toc-인트로">인트로</a>    <ul>
      <li><a href="#인트로_레벨" id="markdown-toc-인트로_레벨">인트로_레벨</a></li>
      <li><a href="#인트로_ui" id="markdown-toc-인트로_ui">인트로_UI</a></li>
      <li><a href="#인트로_게임모드" id="markdown-toc-인트로_게임모드">인트로_게임모드</a></li>
      <li><a href="#인트로_플레이어-컨트롤러" id="markdown-toc-인트로_플레이어-컨트롤러">인트로_플레이어 컨트롤러</a></li>
      <li><a href="#동영상-재생" id="markdown-toc-동영상-재생">동영상 재생</a>        <ul>
          <li><a href="#intro-동영상" id="markdown-toc-intro-동영상">Intro 동영상</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<!-- <p align = "center">
  <img src ="https://github.com/user-attachments/assets/3b3d3969-f050-4a56-afde-3a731370edfb" width = 520>
</p> -->

<h1 id="인트로">인트로</h1>

<h2 id="인트로_레벨">인트로_레벨</h2>
<blockquote>
  <p>인트로 화면이 될 새 레벨 만들기. 유니티에서의 새 씬</p>
</blockquote>

<h2 id="인트로_ui">인트로_UI</h2>
<blockquote>
  <p>인트로 화면에서 사용될 UI 제작</p>
</blockquote>

<ul>
  <li>UI StartWidget 위젯 블루프린트
    <ul>
      <li>StartButton, EndButton 생성 후 이미지 삽입</li>
      <li>UI 애니메이션 처리
        <ul>
          <li>UI 블루프린트 위젯에서 애니메이션 탭을 오픈한 후 애니메이션 처리할 패널 추가한 후 각 컴포넌트(트랜스폼 (위치, 회전, 크기) 등) 변경 및 애니메이션 효과 처리 가능</li>
          <li>시네마틱 영상 처리 또한 비슷한 방식으로 처리하기 때문에 연습 필요</li>
          <li>애니메이션을 생성해 두고, 사용될 순간에 애니메이션이 동작할 수 있게 연결해주어야 한다</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>StartWidget C++ 클래스
    <ul>
      <li><code class="language-plaintext highlighter-rouge">NativeOnInitialized()</code>
        <ul>
          <li>버튼 캐스팅해서 각 버튼 초기화</li>
        </ul>
      </li>
      <li>클릭 시, 마우스 오버 시, 마우스 오버 해제 시에 해당하는 함수 <code class="language-plaintext highlighter-rouge">UFUNCTION()</code>으로 만들고, 델리게이트 등록</li>
      <li><code class="language-plaintext highlighter-rouge">UWidgetBlueprintGeneratedClass</code> 를 통해 현재 위젯 트리를 가지는 클래스를 찾아옴</li>
      <li>해당 위젯 클래스의 애니메이션을 찾아서 마우스 위치와 같은 위젯인지 찾고, 같다면 해당 애니메이션 재생</li>
    </ul>
  </li>
</ul>

<h2 id="인트로_게임모드">인트로_게임모드</h2>
<blockquote>
  <p>인트로용 게임모드 제작. 별도의 서버는 필요없고 클라이언트 단에 작성하면 된다</p>
</blockquote>

<h2 id="인트로_플레이어-컨트롤러">인트로_플레이어 컨트롤러</h2>
<blockquote>
  <p>인트로용 플레이어 컨트롤러</p>
</blockquote>

<ul>
  <li>생성자
    <ul>
      <li>StartWidget 클래스 초기화 및 할당</li>
      <li>마우스 커서 보이게 <code class="language-plaintext highlighter-rouge">bShowMouseCursor</code> 불린 값 트루</li>
      <li><code class="language-plaintext highlighter-rouge">SetInputMode(모드)</code> 는 <code class="language-plaintext highlighter-rouge">FInputModeUIOnly</code>로</li>
      <li>뷰포트에서 StartWidget 위젯 보일 수 있게</li>
    </ul>
  </li>
</ul>

<h2 id="동영상-재생">동영상 재생</h2>
<blockquote>
  <p>엔진 내에서 동영상을 재생 시키는 트리거를 만들고 사용할 수 있다</p>
</blockquote>

<ul>
  <li>[Contents] - [Movies] 폴더에 넣기</li>
  <li>실행 방법
    <ul>
      <li>동영상 파일을 엔진에 삽입 후 재생
        <ul>
          <li><code class="language-plaintext highlighter-rouge">파일 미디어 소스</code> : 경로에 미디어 경로 삽입</li>
          <li><code class="language-plaintext highlighter-rouge">미디어 플레이어</code> : 플레이 리스트에 미디어 소스를 추가하여 사용</li>
          <li><code class="language-plaintext highlighter-rouge">미디어 텍스쳐</code> : 텍스쳐를 이용해 화면에 출력할 수 있게 조정 가능 (뷰 포트 상에)</li>
        </ul>
      </li>
      <li>url을 이용하여 재생</li>
      <li>미디어 플레이트 : 3D 공간에 동영상을 재생할 수 있게 해주는 컴포넌트</li>
    </ul>
  </li>
</ul>

<h3 id="intro-동영상">Intro 동영상</h3>
<blockquote>
  <p>블루 프린트를 활용해서 제작</p>
  <ul>
    <li><code class="language-plaintext highlighter-rouge">UI_Intro</code> UI 위젯 블루프린트를 만들고 화면에 나타날 수 있게 패널 배치</li>
    <li>패널에 출력할 머티리얼 <code class="language-plaintext highlighter-rouge">MT_Video_Master</code> 생성
      <ul>
        <li>머티리얼 도메인 UI로 변경</li>
        <li><code class="language-plaintext highlighter-rouge">TextureSampleParameter2D</code> 만들고 텍스쳐 베이스를 미디어 값으로 만들기</li>
        <li>머티리얼 인스턴스 생성 -&gt; UI로 이동 후 <code class="language-plaintext highlighter-rouge">UI_Intro</code>의 이미지 값으로 지정</li>
      </ul>
    </li>
    <li>재생
      <ul>
        <li><strong>인트로용 게임모드 블루프린트 클래스</strong> 만들기</li>
        <li><em>레벨 블루프린트 사용</em> : 레벨마다 하나씩 생성되는 블루프린트
          <ul>
            <li>Press Any key -&gt; Open Level by References</li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</blockquote>

<p align="center">
  <img src="https://github.com/user-attachments/assets/d477a60f-deba-4a0f-8a4e-f6f19ff96065" width="520" />
  <img src="https://github.com/user-attachments/assets/326335e8-6a1a-45c0-8be9-59f9a1a18a78" width="520" />
</p>]]></content><author><name>Jinsoo Lee</name><email>ljs4784@gmail.com</email></author><category term="develop" /><category term="cpp" /><category term="unreal" /><summary type="html"><![CDATA[본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다]]></summary></entry><entry><title type="html">[Unreal] 20.UI_Inventory_TileView, Quest</title><link href="https://jinlee0206.github.io/develop/Unreal_20.html" rel="alternate" type="text/html" title="[Unreal] 20.UI_Inventory_TileView, Quest" /><published>2024-08-10T00:00:00+09:00</published><updated>2024-08-15T00:00:00+09:00</updated><id>https://jinlee0206.github.io/develop/Unreal_20</id><content type="html" xml:base="https://jinlee0206.github.io/develop/Unreal_20.html"><![CDATA[<blockquote>
  <p><span style="font-size: 80%">
본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다 </span></p>
</blockquote>

<!--more-->

<ul id="markdown-toc">
  <li><a href="#ui_inventory" id="markdown-toc-ui_inventory">UI_Inventory</a>    <ul>
      <li><a href="#ui_tileview" id="markdown-toc-ui_tileview">UI_TileView</a></li>
    </ul>
  </li>
  <li><a href="#quest" id="markdown-toc-quest">Quest</a>    <ul>
      <li><a href="#ui_treeview" id="markdown-toc-ui_treeview">UI_TreeView</a></li>
    </ul>
  </li>
</ul>

<!-- <p align = "center">
  <img src ="https://github.com/user-attachments/assets/3b3d3969-f050-4a56-afde-3a731370edfb" width = 520>
</p> -->

<h1 id="ui_inventory">UI_Inventory</h1>

<h2 id="ui_tileview">UI_TileView</h2>
<blockquote>
  <p>타일 뷰 : 콘텐츠를 모두 일정한 크기의 타일로 표시하는 플로우 패널</p>
</blockquote>

<ul>
  <li>1 x 1 인벤토리를 구현할 때, 사용 가능</li>
</ul>

<h1 id="quest">Quest</h1>
<ul>
  <li>트리 뷰를 통해 퀘스트의 내용을 별도의 위젯에서 담아두고 퀘스트 위젯을 화면에 보여주기</li>
</ul>

<h2 id="ui_treeview">UI_TreeView</h2>
<blockquote>
  <p>트리 뷰 : 요소의 계층구조 트리를 표시할 수 있음</p>
</blockquote>

<ul>
  <li>GameInfo
    <ul>
      <li>퀘스트 타입과 퀘스트 잡 구조체를 만든다</li>
      <li>퀘스트 완성 데이터를 가진다
        <ul>
          <li>퀘스트 완성 조건을 다르게 설정 (아이템 수집, 몬스터 처치, NPC 대화 등)</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>QuestDataEntry
    <ul>
      <li>퀘스트 정보를 저장하기 위한 엔트리</li>
    </ul>
  </li>
</ul>]]></content><author><name>Jinsoo Lee</name><email>ljs4784@gmail.com</email></author><category term="develop" /><category term="cpp" /><category term="unreal" /><summary type="html"><![CDATA[본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다]]></summary></entry><entry><title type="html">[Unreal] 19.UI_Inventory</title><link href="https://jinlee0206.github.io/develop/Unreal_19.html" rel="alternate" type="text/html" title="[Unreal] 19.UI_Inventory" /><published>2024-08-04T00:00:00+09:00</published><updated>2024-08-11T00:00:00+09:00</updated><id>https://jinlee0206.github.io/develop/Unreal_19</id><content type="html" xml:base="https://jinlee0206.github.io/develop/Unreal_19.html"><![CDATA[<blockquote>
  <p><span style="font-size: 80%">
본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다 </span></p>
</blockquote>

<!--more-->

<ul id="markdown-toc">
  <li><a href="#ui_inventory" id="markdown-toc-ui_inventory">UI_Inventory</a>    <ul>
      <li><a href="#ui_리스트-뷰" id="markdown-toc-ui_리스트-뷰">UI_리스트 뷰</a></li>
      <li><a href="#아이템-매니저" id="markdown-toc-아이템-매니저">아이템 매니저</a>        <ul>
          <li><a href="#itemmanagerh" id="markdown-toc-itemmanagerh">ItemManager.h</a></li>
          <li><a href="#itemmanagercpp" id="markdown-toc-itemmanagercpp">ItemManager.cpp</a></li>
          <li><a href="#inventorylistwidgetcpp" id="markdown-toc-inventorylistwidgetcpp">InventoryListWidget.cpp</a></li>
          <li><a href="#inventorylistentrywidgetcpp" id="markdown-toc-inventorylistentrywidgetcpp">InventoryListEntryWidget.cpp</a></li>
          <li><a href="#iteminfowidgetcpp" id="markdown-toc-iteminfowidgetcpp">ItemInfoWidget.cpp</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<!-- <p align = "center">
  <img src ="https://github.com/user-attachments/assets/3b3d3969-f050-4a56-afde-3a731370edfb" width = 520>
</p> -->

<h1 id="ui_inventory">UI_Inventory</h1>
<ul>
  <li><strong>리스트 뷰</strong> : 수천 개의 항목을 하나의 가상화된 목록에서 볼 수 있도록 해 줌
    <ul>
      <li><em>항목(List)</em>과 <em>요소(Entry)</em>의 구분이 필요</li>
      <li>반드시 <code class="language-plaintext highlighter-rouge">IUserObjectListEntry</code> 인터페이스에서 상속을 받아야지 리스트 뷰에서 위젯 사용 가능</li>
      <li>언리얼 엔진은 기본적으로 다중 상속을 지원하지 않음</li>
      <li>인터페이스를 활용하여 다중 상속과 같은 효과를 낼 수 있다</li>
    </ul>
  </li>
  <li>타일 뷰 : 콘텐츠를 모두 일정한 크기의 타일로 표시하는 플로우 패널</li>
  <li>트리 뷰 : 요소의 계층구조 트리를 표시할 수 있음</li>
</ul>

<h2 id="ui_리스트-뷰">UI_리스트 뷰</h2>
<blockquote>
  <p>출처: https://husk321.tistory.com/423 [껍데기방:티스토리]</p>
</blockquote>

<ul>
  <li>ListView에 들어가는 각 <em>요소(Entry)</em>는 <code class="language-plaintext highlighter-rouge">IUserObjectListEntry</code> 인터페이스를 상속받은 클래스여야 함</li>
  <li><code class="language-plaintext highlighter-rouge">IUserObjectListEntry</code>를 상속받은 뒤 <code class="language-plaintext highlighter-rouge">NativeOnListItemObjectSet()</code> 함수를 재정의하면 이 요소(엔트리)가 Set 될 때 행동을 정의 가능하다</li>
  <li>ListView는 <code class="language-plaintext highlighter-rouge">TArray&lt;TObjectPtr&lt;UObject&gt;&gt;</code> 로 이루어져 있음
    <ul>
      <li>때문에 TArray를 그대로 전달할 수도 있음
        <ul>
          <li>이때는 <code class="language-plaintext highlighter-rouge">SetListItems()</code> 함수 활용</li>
        </ul>
      </li>
      <li>내부적으로 TArray의 함수를 활용하므로 단순 Add, Remove를 해주면 다 처리를 해 줌</li>
      <li>또한 각 요소가 UObject로 전달되기에 각 요소들의 <code class="language-plaintext highlighter-rouge">NativeOnListItemObjectSet()</code>에서는 캐스팅을 해줘야 함
        <ul>
          <li><code class="language-plaintext highlighter-rouge">NativeOnInitialized()</code> 함수에서 한번에 캐스팅하는 것이 비용적으로 이득
 </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
<p align="center">
  <img src="https://github.com/user-attachments/assets/ac106776-483b-47b4-9634-e3172424189d" width="420" />
</p>

<h2 id="아이템-매니저">아이템 매니저</h2>
<ul>
  <li>아이템 매니저를 이용해서 아이템 관리 UObject 타입으로 생성</li>
  <li>데이터 테이블 구조체로 항목 관리 테이블 만들기
    <ul>
      <li>각 아이템은 <code class="language-plaintext highlighter-rouge">ItemDataEntry</code>로 만들기</li>
      <li>그 구조체는 <em>GameInfo</em>에 선언</li>
    </ul>
  </li>
  <li>마우스 오버 시 리스트 엔트리 위젯의 변화를 주는 처리 하기
    <ul>
      <li>UI 컨버스 패널에서 <em>Select</em> 이미지를 만들고 Z order를 1로 두고(맨 위로) 컬러 &amp; Opacity에서 색조 변경</li>
    </ul>
  </li>
</ul>

<h3 id="itemmanagerh">ItemManager.h</h3>
<ul>
  <li><code class="language-plaintext highlighter-rouge">UDataTable*</code> 타입으로 데이터 테이블 멤버변수로 선언</li>
  <li>생성자에서 데이터 테이블 정보 불러오기</li>
</ul>

<h3 id="itemmanagercpp">ItemManager.cpp</h3>
<ul>
  <li>데이터 테이블 멤버변수 전방 선언</li>
  <li><code class="language-plaintext highlighter-rouge">FindItem()</code> 함수 만들어서 아이템 테이블의 <code class="language-plaintext highlighter-rouge">FindRow()</code> 함수</li>
  <li><code class="language-plaintext highlighter-rouge">GetItemCount()</code> 함수로 아이템 개수 리턴 하는 함수 만들기</li>
</ul>

<h3 id="inventorylistwidgetcpp">InventoryListWidget.cpp</h3>
<blockquote>
  <p>인벤토리 항목(List)를 보여주는 위젯. 리스트에는 항목(엔트리)이 하나씩 들어 있는 구조</p>
</blockquote>

<ul>
  <li><code class="language-plaintext highlighter-rouge">NativeOnInitialized()</code> 위젯 블루프린트에서 만든 각 이미지, 버튼, 리스트 뷰 각 타입으로 캐스팅 한 후 초기화</li>
  <li>[아이템 생성] - [UObject 생성] - [엔트리에 등록]</li>
  <li>버튼(Close, Clear)의 경우 Open / Close 델리게이트 등록</li>
  <li>mSelect 멤버변수를 만들고, 선택된 항목을 저장해 두는 변수로 사용</li>
  <li>마우스 오버
    <ul>
      <li><code class="language-plaintext highlighter-rouge">InventoryItemHovered(UObejct* Item, bool Hovered)</code> 함수 만들고 리스트 뷰에 존재하는 <code class="language-plaintext highlighter-rouge">OnItemIsHoveredChanged().AddUObject()</code> 델리게이트에 등록
        <ul>
          <li>아이템을 <code class="language-plaintext highlighter-rouge">ItemDataEntry</code>로 캐스팅 하고 (UObject 타입이기 때문에 캐스팅 필요) 선택한 아이템인지 확인하기</li>
          <li>연결된 EntryWidget을 얻어오기</li>
          <li>마우스 스테이트에 따라 색조 및 불투명도 조정 함수 만들기 <code class="language-plaintext highlighter-rouge">SetMouseOn()</code></li>
        </ul>
      </li>
    </ul>
  </li>
  <li>마우스 클릭
    <ul>
      <li><code class="language-plaintext highlighter-rouge">InventoryItemSelect(UObject* Item)</code> 함수를 만들고 리스트 뷰에 존재하는 <code class="language-plaintext highlighter-rouge">OnItemSelectionChanged().AddUObject()</code> or <code class="language-plaintext highlighter-rouge">OnItemClicked().AddUObject()</code> 델리게이트에 등록</li>
    </ul>
  </li>
  <li>마우스 더블클릭
    <ul>
      <li><code class="language-plaintext highlighter-rouge">IventoryItemDoubleClick(UObject* Item)</code> 함수를 만들고 리스트 뷰에 존재하는 <code class="language-plaintext highlighter-rouge">OnItemDoubleClicked().AddUObject()</code> 델리게이트에 등록</li>
    </ul>
  </li>
  <li>제거
    <ul>
      <li><code class="language-plaintext highlighter-rouge">ClearListItem()</code> : 리스트의 아이템(엔트리)을 전부 제거</li>
      <li><code class="language-plaintext highlighter-rouge">RemoveItem(아이템)</code> : 아이템(엔트리) 하나 제거</li>
    </ul>
  </li>
  <li>ItemInfo
    <ul>
      <li><code class="language-plaintext highlighter-rouge">NativeOnMouseMove()</code>
        <ul>
          <li><code class="language-plaintext highlighter-rouge">USlateBlueprintLibrary</code> 헤더 추가</li>
          <li>마우스 오버 상태라면, 아이템 정보창의 CanvasPanelSlot을 얻어 오고,</li>
          <li>마우스의 스크린에서의 위치를 얻어온다.</li>
          <li>스크린에서의 마우스 위치를 현재 이 위젯에서의 위치로 변경</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<h3 id="inventorylistentrywidgetcpp">InventoryListEntryWidget.cpp</h3>
<blockquote>
  <p><em>항목(List)</em>에 들어가는 실제 <em>요소(Entry)</em> 를 나타내는 위젯. 아이템 정보는 따로 아이템 매니저를 통해 UObject로 만들고 캐스팅해서 사용할 것</p>
  <ul>
    <li><code class="language-plaintext highlighter-rouge">IUserObjectListEntry</code> 인터페이스를 상속받은 클래스</li>
  </ul>
</blockquote>

<h3 id="iteminfowidgetcpp">ItemInfoWidget.cpp</h3>
<blockquote>
  <p>아이템 정보를 보여주는 위젯</p>
</blockquote>

<ul>
  <li>초기화
    <ul>
      <li><code class="language-plaintext highlighter-rouge">NativeOnInitialized()</code> 함수에서 각 위젯 초기화</li>
    </ul>
  </li>
  <li>할당
    <ul>
      <li><code class="language-plaintext highlighter-rouge">FInventoryItemData</code>에 있는 데이터를 <code class="language-plaintext highlighter-rouge">SetItemData()</code>을 통해 할당</li>
    </ul>
  </li>
  <li>동적 위젯 생성
    <ul>
      <li>가변적으로 내용을 추가, 제거를 할 수 있어야 한다</li>
      <li>위젯에서 마우스 위치를 추적해서, 위젯이 따라 움직이는 것과 같은 효과를 낼 수 있음</li>
      <li>마우스 오버 되있는지 확인하는 멤버변수 mHovered 추가</li>
    </ul>
  </li>
</ul>]]></content><author><name>Jinsoo Lee</name><email>ljs4784@gmail.com</email></author><category term="develop" /><category term="cpp" /><category term="unreal" /><summary type="html"><![CDATA[본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다]]></summary></entry></feed>