<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>이개 - 이것저것 개발 블로그</title>
    <link>https://igae-dev.tistory.com/</link>
    <description>공부한 내용, 실습한 내용 등을 정리합니다.</description>
    <language>ko</language>
    <pubDate>Sat, 25 Jul 2026 19:17:43 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>이개</managingEditor>
    <image>
      <title>이개 - 이것저것 개발 블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/6579813/attach/6fba31a45a7e4c96a56ef264f3f8fd4a</url>
      <link>https://igae-dev.tistory.com</link>
    </image>
    <item>
      <title>언리얼 엔진으로 좁은 에어리어 바닥 만들기</title>
      <link>https://igae-dev.tistory.com/178</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;카툰풍 3D 배경(고양이 파티 게임 마당 씬) 바닥 제작 과정 정리. 잔디+흙길 자연스럽게 섞인 바닥을 텍스처 두 장 + 버텍스 페인트로 구현.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;방식 선택 이유&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;랜드스케이프: 지형 굴곡엔 좋으나 마당 규모엔 과함&lt;/li&gt;
&lt;li&gt;대신 &lt;b&gt;Plane 하나 + 버텍스 컬러 블렌딩&lt;/b&gt; 채택 &amp;rarr; 작업량 절감&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 구조:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;잔디/흙 텍스처를 머티리얼에서 Lerp로 블렌딩&lt;/li&gt;
&lt;li&gt;흙길 위치는 &lt;b&gt;버텍스 컬러&lt;/b&gt;로 직접 페인팅&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1단계. 버텍스 페인트 가능한 Plane 제작&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 Plane = 폴리곤 2개(버텍스 4개) &amp;rarr; 버텍스 페인트 시 경계 각짐. 촘촘한 격자 필요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;601&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3tXp5/dJMcaglP99z/cFsKGVlkqknXKm0pB2BVNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3tXp5/dJMcaglP99z/cFsKGVlkqknXKm0pB2BVNk/img.png&quot; data-alt=&quot;모델링 모드에서 사각형을 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3tXp5/dJMcaglP99z/cFsKGVlkqknXKm0pB2BVNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3tXp5%2FdJMcaglP99z%2FcFsKGVlkqknXKm0pB2BVNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;568&quot; height=&quot;601&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;601&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모델링 모드에서 사각형을 선택&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1867&quot; data-origin-height=&quot;952&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sz1AP/dJMcaaeU8Yf/AnKlweIanZlYnJuLCgDZ5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sz1AP/dJMcaaeU8Yf/AnKlweIanZlYnJuLCgDZ5K/img.png&quot; data-alt=&quot;바닥의 가로세로 길이를 설정하고, 텍스처를 깨짐없이 적용하기 위해 너비와 뎁스 서브디비전을 적당히 설정한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sz1AP/dJMcaaeU8Yf/AnKlweIanZlYnJuLCgDZ5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsz1AP%2FdJMcaaeU8Yf%2FAnKlweIanZlYnJuLCgDZ5K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1867&quot; height=&quot;952&quot; data-origin-width=&quot;1867&quot; data-origin-height=&quot;952&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;바닥의 가로세로 길이를 설정하고, 텍스처를 깨짐없이 적용하기 위해 너비와 뎁스 서브디비전을 적당히 설정한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Select Mode 드롭다운 &amp;rarr; &lt;b&gt;Modeling&lt;/b&gt; 모드&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Create&lt;/b&gt; 탭 &amp;rarr; &lt;b&gt;Rectangle&lt;/b&gt; 툴 (Plane 역할)&lt;/li&gt;
&lt;li&gt;Details 패널 설정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Width / Height: 마당 크기 기준 (예: 2000 x 2000 = 20m x 20m)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Width/Height Subdivisions&lt;/b&gt;: 20 x 20 (버텍스 페인트 해상도 결정)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Accept&lt;/b&gt;로 생성&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2단계. 텍스처 준비&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요 텍스처:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Grass 계열 (Base Color)&lt;/li&gt;
&lt;li&gt;Dirt 계열 (Base Color)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;선정 기준&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리얼한 개별 잎사귀/흙 알갱이 텍스처 제외 &amp;mdash; 툰 캐릭터와 이질감 심함&lt;/li&gt;
&lt;li&gt;&quot;Stylized&quot;, &quot;Toon&quot;, &quot;Cartoon&quot; 태그 우선 검색&lt;/li&gt;
&lt;li&gt;해상도 1K~2K 충분, 4K는 낭비&lt;/li&gt;
&lt;li&gt;마땅한 것 없으면 직접 제작 가능. 단색 베이스 + 약한 노이즈 정도로 충분&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AI로 생성가능&lt;/li&gt;
&lt;li&gt;1024x1024정도로 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;직접 제작 시 &lt;b&gt;타일링 검증 필수&lt;/b&gt; &amp;mdash; Photoshop Filter &amp;rarr; Other &amp;rarr; Offset으로 이미지 절반 밀어서 이음새 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3단계. 머티리얼 그래프 구성&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1948&quot; data-origin-height=&quot;1174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/55bFq/dJMcabZdJqp/rw1tjK50ZCZ6nKwEQGywbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/55bFq/dJMcabZdJqp/rw1tjK50ZCZ6nKwEQGywbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/55bFq/dJMcabZdJqp/rw1tjK50ZCZ6nKwEQGywbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F55bFq%2FdJMcabZdJqp%2Frw1tjK50ZCZ6nKwEQGywbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1948&quot; height=&quot;1174&quot; data-origin-width=&quot;1948&quot; data-origin-height=&quot;1174&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UV 타일링&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;TexCoord[0] &amp;rarr; Multiply (B값: 10 정도) &amp;rarr; 각 텍스처 샘플 UV 입력에 연결
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타일링 값 = 텍스처 한 장이 덮는 실제 미터 수 기준 산출.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Grass/Dirt 블렌딩&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Texture Sample 노드 2개 &amp;mdash; Grass, Dirt 각각 할당, UV 타일링 노드 연결&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Vertex Color&lt;/b&gt; 노드 추가&lt;/li&gt;
&lt;li&gt;Vertex Color &amp;rarr; &lt;b&gt;Component Mask&lt;/b&gt; (R만 체크)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Lerp&lt;/b&gt; 노드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A = Grass&lt;/li&gt;
&lt;li&gt;B = Dirt&lt;/li&gt;
&lt;li&gt;Alpha = Mask(R) 결과&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Lerp 결과 &amp;rarr; &lt;b&gt;Base Color&lt;/b&gt; 핀&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버텍스 컬러 R=0 &amp;rarr; Grass / R=1 &amp;rarr; Dirt / 중간값 &amp;rarr; 자연 블렌딩&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;노멀맵 입체감&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;밋밋하면 노멀맵 추가. 세게 넣으면 실사틱해짐 &amp;rarr; 강도 낮춰야 함.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Texture Sample &amp;mdash; 노멀맵 텍스처 (동일 UV 타일링)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Flatten Normal&lt;/b&gt; 노드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Normal 입력 = 위 텍스처 샘플&lt;/li&gt;
&lt;li&gt;Flatness = Constant (0.7~0.8, 0에 가까울수록 원본, 1에 가까울수록 평평)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;결과 &amp;rarr; &lt;b&gt;Normal&lt;/b&gt; 핀&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;반사 제거 (매트한 표면)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Specular&lt;/b&gt;: 0.0&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Roughness&lt;/b&gt;: 1.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Constant 노드로 각각 연결.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4단계. 버텍스 페인트로 흙길 그리기&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2005&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GphxB/dJMcajbJ5rC/DhHV96XCkQPFKQ9wCmerN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GphxB/dJMcajbJ5rC/DhHV96XCkQPFKQ9wCmerN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GphxB/dJMcajbJ5rC/DhHV96XCkQPFKQ9wCmerN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGphxB%2FdJMcajbJ5rC%2FDhHV96XCkQPFKQ9wCmerN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2005&quot; height=&quot;1200&quot; data-origin-width=&quot;2005&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;머티리얼을 Plane에 할당&lt;/li&gt;
&lt;li&gt;Select Mode &amp;rarr; &lt;b&gt;Mesh Paint&lt;/b&gt; 모드&lt;/li&gt;
&lt;li&gt;메시 선택 후 좌측 패널
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Paint Color&lt;/b&gt;: 빨강 (R=1, G=0, B=0)&lt;/li&gt;
&lt;li&gt;Brush Size / Strength 조절&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;원하는 부분 브러시로 칠 &amp;rarr; 실시간 Dirt 전환 확인&lt;/li&gt;
&lt;li&gt;잘못 칠했으면 검정(R=0)으로 재작업&lt;/li&gt;
&lt;li&gt;초기 버텍스 컬러값이 예상과 다를 수 있음 &amp;mdash; 결과 이상하면 &lt;b&gt;채우기(Fill)&lt;/b&gt; 로 전체 리셋 후 재작업&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;팁&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Brush Strength 낮게 &amp;rarr; 덧칠할수록 진해짐 &amp;rarr; 자연스러운 그라데이션 경계&lt;/li&gt;
&lt;li&gt;경계 또렷하게: 작은 브러시 정교하게 / 부드럽게: 큰 브러시 여러 번 겹침&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;완성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텍스처 2장 + 노멀맵 1개로 원하는 형태의 흙길 있는 스타일라이즈드 바닥 완성. AO/Height 맵은 이 규모 씬에선 생략해도 무방 &amp;mdash; 결과물 차이 미미.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다음&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바닥 위에 담장/폴리지/원경 배경 추가 예정. 다음 글에서 정리.&lt;/p&gt;</description>
      <category>게임 개발/학습 일지</category>
      <author>이개</author>
      <guid isPermaLink="true">https://igae-dev.tistory.com/178</guid>
      <comments>https://igae-dev.tistory.com/178#entry178comment</comments>
      <pubDate>Mon, 13 Jul 2026 17:12:34 +0900</pubDate>
    </item>
    <item>
      <title>언리얼 내배캠 - 멀티플레이 채팅 구현</title>
      <link>https://igae-dev.tistory.com/177</link>
      <description>&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;517&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I8e1U/dJMcadWK0L3/icsGvkcwfTL7ZG64omxHc0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I8e1U/dJMcadWK0L3/icsGvkcwfTL7ZG64omxHc0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I8e1U/dJMcadWK0L3/icsGvkcwfTL7ZG64omxHc0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI8e1U%2FdJMcadWK0L3%2FicsGvkcwfTL7ZG64omxHc0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1198&quot; height=&quot;517&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;517&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;PlayerController.h에&amp;nbsp;ClientRPCPrintChatMessageString,&amp;nbsp;ServerRPCPrintChatMessageStirng 함수 추가&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;채팅이란 클라이언트에서 서버 RPC로 보내고, 서버에서 클라이언트 RPC로 전체 출력을 해주는 구조이다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1207&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bA9QXB/dJMcadI85V3/fHKF5nLoSumTLaWulWYX80/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bA9QXB/dJMcadI85V3/fHKF5nLoSumTLaWulWYX80/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bA9QXB/dJMcadI85V3/fHKF5nLoSumTLaWulWYX80/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbA9QXB%2FdJMcadI85V3%2FfHKF5nLoSumTLaWulWYX80%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1207&quot; height=&quot;264&quot; data-origin-width=&quot;1207&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;이 함수들을 구현할 때는 함수명 뒤에 _Implementation 접미사를 붙여주어야한다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;549&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kTPa0/dJMcacjdaHX/zQyK9INK399UQnbdpeT73k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kTPa0/dJMcacjdaHX/zQyK9INK399UQnbdpeT73k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kTPa0/dJMcacjdaHX/zQyK9INK399UQnbdpeT73k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkTPa0%2FdJMcacjdaHX%2FzQyK9INK399UQnbdpeT73k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1110&quot; height=&quot;549&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;549&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추가로 WithValidation 키워드를 붙이면 _Validate()도 반드시 구현해야하고, 여기서 치트 방지 검증을 한다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;for문으로 플레이어 컨트롤러 전체를 돌며 메시지 출력 함수를 실행해준다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C8B92/dJMcadWK0L6/U7qIg9rbrsOdG9WW9DskA1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C8B92/dJMcadWK0L6/U7qIg9rbrsOdG9WW9DskA1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C8B92/dJMcadWK0L6/U7qIg9rbrsOdG9WW9DskA1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC8B92%2FdJMcadWK0L6%2FU7qIg9rbrsOdG9WW9DskA1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1249&quot; height=&quot;436&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;529&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bc9IKf/dJMcadWK0L2/qxYM37IROggKaVFj2zPqb0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bc9IKf/dJMcadWK0L2/qxYM37IROggKaVFj2zPqb0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bc9IKf/dJMcadWK0L2/qxYM37IROggKaVFj2zPqb0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbc9IKf%2FdJMcadWK0L2%2FqxYM37IROggKaVFj2zPqb0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;529&quot; height=&quot;100&quot; data-origin-width=&quot;529&quot; data-origin-height=&quot;100&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;EngineUtils.h를 추가해야 GetWorld의 ActorIterator를 사용할 수 있다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ClientRPC 대신 NetMulticastRPC를 사용하면 안 되는 이유&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1035&quot; data-origin-height=&quot;319&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m2muV/dJMcadWK0L5/KuKkyaHBKHrqDwuon9uTS1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m2muV/dJMcadWK0L5/KuKkyaHBKHrqDwuon9uTS1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m2muV/dJMcadWK0L5/KuKkyaHBKHrqDwuon9uTS1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm2muV%2FdJMcadWK0L5%2FKuKkyaHBKHrqDwuon9uTS1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1035&quot; height=&quot;319&quot; data-origin-width=&quot;1035&quot; data-origin-height=&quot;319&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;SetChatMessageString을 구현한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Run Under One Process를 체크 해제했으면, 서버를 켠 상태에서는 에디터가 꺼져도 서버 등은 계속 실행이 되는 경우가 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1411&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A7Hag/dJMcajbwHuy/3oFklCKeLcx5TAbbFXNq1K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A7Hag/dJMcajbwHuy/3oFklCKeLcx5TAbbFXNq1K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A7Hag/dJMcajbwHuy/3oFklCKeLcx5TAbbFXNq1K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA7Hag%2FdJMcajbwHuy%2F3oFklCKeLcx5TAbbFXNq1K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1411&quot; height=&quot;1080&quot; data-origin-width=&quot;1411&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;빌드해서 실행한 모습을 보면 정상적으로 플레이어 화면들에 채팅 메시지가 출력된다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;누군가가 접속하면 메세지 출력&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;플레이어가 접속할 때마다 호출되는 함수&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;NetMulticast RPC를 통한 서버 접속 알리기&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GameMode같은 경우에는 Server에만 존재하므로, 접속 메시지의 경우 모든 플레이어에 존재하는 GameState에서 NetMulticast로 호출해 주는 것이 맞다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;826&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PVd0Z/dJMcacjdaHZ/daGoZR67iPuYjN7oRsJ3PK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PVd0Z/dJMcacjdaHZ/daGoZR67iPuYjN7oRsJ3PK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PVd0Z/dJMcacjdaHZ/daGoZR67iPuYjN7oRsJ3PK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPVd0Z%2FdJMcacjdaHZ%2FdaGoZR67iPuYjN7oRsJ3PK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1390&quot; height=&quot;826&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;826&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;861&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VO4Ae/dJMcacjdaH1/NATxhzn9AQ390f7kmnXI0k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VO4Ae/dJMcacjdaH1/NATxhzn9AQ390f7kmnXI0k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VO4Ae/dJMcacjdaH1/NATxhzn9AQ390f7kmnXI0k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVO4Ae%2FdJMcacjdaH1%2FNATxhzn9AQ390f7kmnXI0k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1402&quot; height=&quot;861&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;861&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GameModeBase를 만들었으므로 GameStateBase를 새로 만들어준다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;709&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzsKmF/dJMcacjdaH0/4TbRXIKy9JjPVwJp56hBn1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzsKmF/dJMcacjdaH0/4TbRXIKy9JjPVwJp56hBn1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzsKmF/dJMcacjdaH0/4TbRXIKy9JjPVwJp56hBn1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzsKmF%2FdJMcacjdaH0%2F4TbRXIKy9JjPVwJp56hBn1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1135&quot; height=&quot;709&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;709&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;헤더에&amp;nbsp;MulticastRPCBroadcastLoginMessage라는 함수를 선언한다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1489&quot; data-origin-height=&quot;835&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tmHhW/dJMcajbwHuA/b81GL5yIbGVr2x9qJIDOQk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tmHhW/dJMcajbwHuA/b81GL5yIbGVr2x9qJIDOQk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tmHhW/dJMcajbwHuA/b81GL5yIbGVr2x9qJIDOQk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtmHhW%2FdJMcajbwHuA%2Fb81GL5yIbGVr2x9qJIDOQk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1489&quot; height=&quot;835&quot; data-origin-width=&quot;1489&quot; data-origin-height=&quot;835&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;MulticastRPCBroadcastLoginMessage_Implementation으로 함수를 구현해준다.&lt;/div&gt;
&lt;div&gt;UFUNCTION(NetMulticast, Reliable) 매크로를 선언하면 UHT가 자동으로 코드를 생성한다.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;원본 함수는 UHT가 이미 구현해버리기 때문에, 실제 로직은 함수명에&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;_Implementation을 붙여 구현해야한다. 그렇게 하지 않으면 중복 정의 에러가 난다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1521&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvtafR/dJMcadWK0L7/6pUUM1h62bcNiFxAVytgd1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvtafR/dJMcadWK0L7/6pUUM1h62bcNiFxAVytgd1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvtafR/dJMcadWK0L7/6pUUM1h62bcNiFxAVytgd1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvtafR%2FdJMcadWK0L7%2F6pUUM1h62bcNiFxAVytgd1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1521&quot; height=&quot;646&quot; data-origin-width=&quot;1521&quot; data-origin-height=&quot;646&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1186&quot; data-origin-height=&quot;598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsbp8d/dJMcajbwHuz/kBccII9neqpYvetdzeD860/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsbp8d/dJMcajbwHuz/kBccII9neqpYvetdzeD860/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsbp8d/dJMcajbwHuz/kBccII9neqpYvetdzeD860/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbsbp8d%2FdJMcajbwHuz%2FkBccII9neqpYvetdzeD860%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1186&quot; height=&quot;598&quot; data-origin-width=&quot;1186&quot; data-origin-height=&quot;598&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;GameStateBase에 OnPostLogin을 오버라이드하여 채팅 출력 코드를 작성한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;445&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/umgih/dJMcacjdaHY/VFWxVbld7ouZoq3iIbLR40/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/umgih/dJMcacjdaHY/VFWxVbld7ouZoq3iIbLR40/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/umgih/dJMcacjdaHY/VFWxVbld7ouZoq3iIbLR40/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fumgih%2FdJMcacjdaHY%2FVFWxVbld7ouZoq3iIbLR40%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;798&quot; height=&quot;445&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;445&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;에디터에서 만든 게임스테이트를 설정한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;712&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbsUNb/dJMcajbwHux/bRme19kFLQYnDt1zz0VZAk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbsUNb/dJMcajbwHux/bRme19kFLQYnDt1zz0VZAk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbsUNb/dJMcajbwHux/bRme19kFLQYnDt1zz0VZAk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbsUNb%2FdJMcajbwHux%2FbRme19kFLQYnDt1zz0VZAk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1492&quot; height=&quot;712&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;712&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1777&quot; data-origin-height=&quot;766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EIUtW/dJMcacjdaH2/0btzODAkNarPMqXUk3cKw1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EIUtW/dJMcacjdaH2/0btzODAkNarPMqXUk3cKw1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EIUtW/dJMcacjdaH2/0btzODAkNarPMqXUk3cKw1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEIUtW%2FdJMcacjdaH2%2F0btzODAkNarPMqXUk3cKw1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1777&quot; height=&quot;766&quot; data-origin-width=&quot;1777&quot; data-origin-height=&quot;766&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;클라이언트를 추가 실행할 때마다 다른 클라이언트에 메시지가 뜨는 것을 확인할 수 있다.&lt;/div&gt;</description>
      <category>게임 개발/학습 일지</category>
      <author>이개</author>
      <guid isPermaLink="true">https://igae-dev.tistory.com/177</guid>
      <comments>https://igae-dev.tistory.com/177#entry177comment</comments>
      <pubDate>Mon, 22 Jun 2026 19:39:48 +0900</pubDate>
    </item>
    <item>
      <title>언리얼 내배캠 - 언리얼 멀티플레이 기초 RPC(Remote Procedue Call)</title>
      <link>https://igae-dev.tistory.com/176</link>
      <description>&lt;div&gt;RPC란?&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;호출하는 PC와 실행하는 PC가 달라도 되게끔 해주는 통신 기법&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2198&quot; data-origin-height=&quot;747&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfqPMs/dJMcagMGy4F/1NGHb3p1jmsPg8lvbLviT1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfqPMs/dJMcagMGy4F/1NGHb3p1jmsPg8lvbLviT1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfqPMs/dJMcagMGy4F/1NGHb3p1jmsPg8lvbLviT1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfqPMs%2FdJMcagMGy4F%2F1NGHb3p1jmsPg8lvbLviT1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2198&quot; height=&quot;747&quot; data-origin-width=&quot;2198&quot; data-origin-height=&quot;747&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;대부분 게임에 큰 영향을 끼치지 않는 일시적인 효과들에 사용해야한다.&lt;/li&gt;
&lt;li&gt;게임에 큰 영향을 끼치는 것들은 프로퍼티 레플리케이션을 사용해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;488&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/64q73/dJMcagZ7uF3/9e6oh11QYrcssf3UQLrL50/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/64q73/dJMcagZ7uF3/9e6oh11QYrcssf3UQLrL50/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/64q73/dJMcagZ7uF3/9e6oh11QYrcssf3UQLrL50/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F64q73%2FdJMcagZ7uF3%2F9e6oh11QYrcssf3UQLrL50%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;666&quot; height=&quot;488&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;488&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;669&quot; data-origin-height=&quot;491&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0NndN/dJMcaiRczB5/B3hcdVo8gWA7buK3uyDYB0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0NndN/dJMcaiRczB5/B3hcdVo8gWA7buK3uyDYB0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0NndN/dJMcaiRczB5/B3hcdVo8gWA7buK3uyDYB0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0NndN%2FdJMcaiRczB5%2FB3hcdVo8gWA7buK3uyDYB0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;669&quot; height=&quot;491&quot; data-origin-width=&quot;669&quot; data-origin-height=&quot;491&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;671&quot; data-origin-height=&quot;561&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Cywhk/dJMcagZ7uF2/94Ay1J4QoT0gLp8IisjPaK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Cywhk/dJMcagZ7uF2/94Ay1J4QoT0gLp8IisjPaK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Cywhk/dJMcagZ7uF2/94Ay1J4QoT0gLp8IisjPaK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCywhk%2FdJMcagZ7uF2%2F94Ay1J4QoT0gLp8IisjPaK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;671&quot; height=&quot;561&quot; data-origin-width=&quot;671&quot; data-origin-height=&quot;561&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Call vs Invoke&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Call&lt;/li&gt;
&lt;li&gt;Invoke&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Actor Ownership&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네트워크 멀티플레이가 적용되려면, 액터는 서버에서 스폰되고 bReplicated가 true여야한다.&lt;/li&gt;
&lt;li&gt;서버에서 스폰된 후 SetOwner(PlayerController) 함수를 호출해야 Client-Owned Actor가 된다.&lt;/li&gt;
&lt;li&gt;PlayerController가 Local PlayerController와 같다면, 호출한 클라이언트가 소유한 액터가 되어야 한다.&lt;/li&gt;
&lt;li&gt;PlayerController가 Local PlayerController와 다르다면 다른 클라이언트가 소유한 액터가 되어야한다.&lt;/li&gt;
&lt;li&gt;서버에서 스폰되었지만 SetOwner() 함수 호출이 없으면, Server-Owned Actor가 되어야한다.&lt;/li&gt;
&lt;li&gt;Unowned Actor와 Server-Owned Actor를 같은 개념으로 생각하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;NetMulticast, Server, Client 키워드&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UFUNCTION() 매크로와 함께 사용되는 키워드&lt;/li&gt;
&lt;li&gt;해당 원격 PC에서 RPC를 실행시켜달라는 요청을 나타내야함&lt;/li&gt;
&lt;li&gt;실제로 실행될지는 표에 따라 판단&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;1039&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coXqzo/dJMcaiRczB6/RhvClIthlDI1oKKAKrsxl1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coXqzo/dJMcaiRczB6/RhvClIthlDI1oKKAKrsxl1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coXqzo/dJMcaiRczB6/RhvClIthlDI1oKKAKrsxl1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoXqzo%2FdJMcaiRczB6%2FRhvClIthlDI1oKKAKrsxl1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1608&quot; height=&quot;1039&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;1039&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;NetMulticast RPC는 액터가 레플리케이트 되어있는 모든 컴퓨터에서 실행&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1622&quot; data-origin-height=&quot;1041&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cI4qFe/dJMcaaTbVbm/Yj9IJvszoZMBBD67EnuTQK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cI4qFe/dJMcaaTbVbm/Yj9IJvszoZMBBD67EnuTQK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cI4qFe/dJMcaaTbVbm/Yj9IJvszoZMBBD67EnuTQK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcI4qFe%2FdJMcaaTbVbm%2FYj9IJvszoZMBBD67EnuTQK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1622&quot; height=&quot;1041&quot; data-origin-width=&quot;1622&quot; data-origin-height=&quot;1041&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;Server RPC는 클라이언트에서 호출되고 서버에서 실행&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Server 키워드를 사용&lt;/li&gt;
&lt;li&gt;ClientConnection이 소유하고 있는 액터에서 RPC가 호출되어야함&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1624&quot; data-origin-height=&quot;1013&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NzKju/dJMcagZ7uF4/3Tv8Sjg8vTb2XdYdxNcF71/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NzKju/dJMcagZ7uF4/3Tv8Sjg8vTb2XdYdxNcF71/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NzKju/dJMcagZ7uF4/3Tv8Sjg8vTb2XdYdxNcF71/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNzKju%2FdJMcagZ7uF4%2F3Tv8Sjg8vTb2XdYdxNcF71%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1624&quot; height=&quot;1013&quot; data-origin-width=&quot;1624&quot; data-origin-height=&quot;1013&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;Client RPC는 서버에서 호출되고 클라이언트에서 실행&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 ClientConnection이 소유하고 있는 액터에서 RPC가 호출되어야 한다.&lt;/li&gt;
&lt;li&gt;PlayerController의 멤버 함수로 UFUNCTION 달고 클라이언트 키워드를 넣어주면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;WithValidation&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UFUNCTION() 매크로와 함께 사용되는 키워드&lt;/li&gt;
&lt;li&gt;서버에서 실행되는 RPC인 경우에 사용&lt;/li&gt;
&lt;li&gt;_Implementation() 함수와 _Validate() 함수로 나뉨&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;Unreliable VS Reliable&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UFUNCTION() 매크로와 함께 사용되는 키워드&lt;/li&gt;
&lt;li&gt;RPC는 기본적으로 Unreliable&lt;/li&gt;
&lt;li&gt;코스메틱(이펙트, 사운드)처럼 큰 영향이 없으면 Unreliable, 충돌, 대미지, 스폰처럼 게임에 큰 영향을 끼치는 로직은 Reliable로 설정&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;</description>
      <category>게임 개발/학습 일지</category>
      <author>이개</author>
      <guid isPermaLink="true">https://igae-dev.tistory.com/176</guid>
      <comments>https://igae-dev.tistory.com/176#entry176comment</comments>
      <pubDate>Fri, 19 Jun 2026 11:31:55 +0900</pubDate>
    </item>
    <item>
      <title>언리얼 내배캠 - 언리얼 멀티플레이 기초 NetRole</title>
      <link>https://igae-dev.tistory.com/175</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;액터가 서버 PC에 스폰되어있는지, 클라이언트 PC에 스폰되어있는지, 그 액터의 멤버 함수가 서버 PC에서 실행되고 있는지, 클라이언트 PC에서 실행되고 있는지도 파악해야한다.&lt;/p&gt;
&lt;div&gt;서버에 스폰된 액터가 가진 NetRole 속성값은 언제나 Authority&lt;/div&gt;
&lt;div&gt;-&amp;gt; 그래서 게임에 중대한 영향을 끼치는 로직은 NetRole이 Authority일 때 수행&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;NetRole이 Authority인 액터가 클라이언트로 복제되었을 때 복제된 액터의 NetRole 속성값은 Proxy이다. 여기서는 중요한 로직을 수행해서는 안 된다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;로컬 롤과 리모트 롤&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 동작하는 컴퓨터에서의 롤을 로컬 롤(Local Role)이라고 한다.&lt;/li&gt;
&lt;li&gt;커넥션으로 연결된 컴퓨터에서의 롤을 리모트 롤(Remote Role)이라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;NetRole의 종류&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;None&lt;/li&gt;
&lt;li&gt;Authority&lt;/li&gt;
&lt;li&gt;Autonomous Proxy&lt;/li&gt;
&lt;li&gt;Simulated Proxy&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;로그 찍어보기&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;723&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4XoTW/dJMcahLxylC/td2xVdnIYlkUZCfmc8dFB0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4XoTW/dJMcahLxylC/td2xVdnIYlkUZCfmc8dFB0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4XoTW/dJMcahLxylC/td2xVdnIYlkUZCfmc8dFB0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4XoTW%2FdJMcahLxylC%2Ftd2xVdnIYlkUZCfmc8dFB0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1296&quot; height=&quot;723&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;723&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;FString LocalRoleString = UEnum::GetValueAsString(TEXT(&quot;Engine.EnetRole&quot;), InActor-&amp;gt;GetLocalRole());&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;GetValueAsString이 String을 만들어준다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1415&quot; data-origin-height=&quot;868&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dluCpF/dJMcahLxylD/I4GQcyMR7YS66IF9DsBO3k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dluCpF/dJMcahLxylD/I4GQcyMR7YS66IF9DsBO3k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dluCpF/dJMcahLxylD/I4GQcyMR7YS66IF9DsBO3k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdluCpF%2FdJMcahLxylD%2FI4GQcyMR7YS66IF9DsBO3k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1415&quot; height=&quot;868&quot; data-origin-width=&quot;1415&quot; data-origin-height=&quot;868&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;Pawn클래스를 하나 만든다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;519&quot; data-origin-height=&quot;455&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QLbKN/dJMcadvwg4t/jXHJsCKaXqR0IBF2lJlTMk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QLbKN/dJMcadvwg4t/jXHJsCKaXqR0IBF2lJlTMk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QLbKN/dJMcadvwg4t/jXHJsCKaXqR0IBF2lJlTMk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQLbKN%2FdJMcadvwg4t%2FjXHJsCKaXqR0IBF2lJlTMk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;519&quot; height=&quot;455&quot; data-origin-width=&quot;519&quot; data-origin-height=&quot;455&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1534&quot; data-origin-height=&quot;853&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dJ3Wc6/dJMcadvwg4u/MvSYl0tSkmtUz6XeBb3aI1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dJ3Wc6/dJMcadvwg4u/MvSYl0tSkmtUz6XeBb3aI1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dJ3Wc6/dJMcadvwg4u/MvSYl0tSkmtUz6XeBb3aI1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdJ3Wc6%2FdJMcadvwg4u%2FMvSYl0tSkmtUz6XeBb3aI1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1534&quot; height=&quot;853&quot; data-origin-width=&quot;1534&quot; data-origin-height=&quot;853&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;701&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crX0Gf/dJMcaaljkaT/5WlOvLuoWL4TDLBhFEenr1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crX0Gf/dJMcaaljkaT/5WlOvLuoWL4TDLBhFEenr1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crX0Gf/dJMcaaljkaT/5WlOvLuoWL4TDLBhFEenr1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrX0Gf%2FdJMcaaljkaT%2F5WlOvLuoWL4TDLBhFEenr1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;797&quot; height=&quot;701&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;701&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Wordl Settings에 만든 Pawn을 할당하고 실행해보면 로그를 확인할 수 있다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2183&quot; data-origin-height=&quot;840&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djBqTH/dJMcaaljkaV/gLVKhkuAZMojP1suYESgQ0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djBqTH/dJMcaaljkaV/gLVKhkuAZMojP1suYESgQ0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djBqTH/dJMcaaljkaV/gLVKhkuAZMojP1suYESgQ0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjBqTH%2FdJMcaaljkaV%2FgLVKhkuAZMojP1suYESgQ0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2183&quot; height=&quot;840&quot; data-origin-width=&quot;2183&quot; data-origin-height=&quot;840&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Client 2개는 로컬 롤이 ROLE_Authority, 리모트 롤은 ROLE_SimulatedProxy.&lt;/li&gt;
&lt;li&gt;PossessedBy가 된 뒤에 Autonomous Proxy가 됨.&lt;/li&gt;
&lt;li&gt;AActor::HasAuthority(): 주요 로직 실행 권한 확인. NetRole이 Authority이면 서버이므로 서버인지 확인 가능. 다만 리슨 서버는 플레이어도 겸하기 때문에 true라고 해서 플레이어가 아니라고 단정할 수는 없다. Standalone이어도 true가 나온다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;AController::IsLocalController(): 입력 관련 로직이나 UI는 Autonomous Proxy에서 수행되어야한다. 이를 확인하는 함수.&lt;/li&gt;
&lt;li&gt;APawn::IsLocallyControlled():&amp;nbsp; IsLocalController를 래핑했다고 보면 된다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;1273&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tsx14/dJMcaaljkaU/STu0bykShRwHXLgyMmxk50/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tsx14/dJMcaaljkaU/STu0bykShRwHXLgyMmxk50/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tsx14/dJMcaaljkaU/STu0bykShRwHXLgyMmxk50/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ftsx14%2FdJMcaaljkaU%2FSTu0bykShRwHXLgyMmxk50%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;904&quot; height=&quot;1273&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;1273&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;각 액터에 따른 특징&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;게임모드&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;폰&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애니메이션 재생이나 UI 관련 로직&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description>
      <category>게임 개발/학습 일지</category>
      <author>이개</author>
      <guid isPermaLink="true">https://igae-dev.tistory.com/175</guid>
      <comments>https://igae-dev.tistory.com/175#entry175comment</comments>
      <pubDate>Thu, 18 Jun 2026 12:57:19 +0900</pubDate>
    </item>
    <item>
      <title>언리얼 내배캠 - 언리얼 멀티플레이 기초 NetMode, NetConnection, NetDriver</title>
      <link>https://igae-dev.tistory.com/174</link>
      <description>&lt;div&gt;NetMode&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 게임 프로세스가 네트워크 상에서 어떤 역할을 하고 있는지를 의미&lt;/li&gt;
&lt;li&gt;싱글(NM_StandAlone), 서버(NM_Listen, NM_DedicatedServer), 클라이언트(NM_Client)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;NetMode의 필요성&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작성 중인 로직이 서버에서 도는지 클라이언트에서 돌고 있는지는 알아야할 때&lt;/li&gt;
&lt;li&gt;멀티플레이 시에 가장 큰 걸림돌은 같은 코드가 여러 PC에서 동작한다는 것&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2146&quot; data-origin-height=&quot;1199&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z9HBm/dJMcagy40iw/Yxazkea2UMb5T9FHax5CA1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z9HBm/dJMcagy40iw/Yxazkea2UMb5T9FHax5CA1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z9HBm/dJMcagy40iw/Yxazkea2UMb5T9FHax5CA1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz9HBm%2FdJMcagy40iw%2FYxazkea2UMb5T9FHax5CA1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2146&quot; height=&quot;1199&quot; data-origin-width=&quot;2146&quot; data-origin-height=&quot;1199&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;디버깅을 할 때 어떤 PC에서 동작중인지를 살펴보아야한다.&lt;/li&gt;
&lt;li&gt;NetMode는 월드 클래스의 속성값, NetRole은 액터의 속성값이라고 보면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;UWorld::InternalGetNetMode() 함수&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1335&quot; data-origin-height=&quot;1228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhy2Ah/dJMcaiDGC6T/HZNo6UBKWKKqlBjjB9xG2K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhy2Ah/dJMcaiDGC6T/HZNo6UBKWKKqlBjjB9xG2K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhy2Ah/dJMcaiDGC6T/HZNo6UBKWKKqlBjjB9xG2K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdhy2Ah%2FdJMcaiDGC6T%2FHZNo6UBKWKKqlBjjB9xG2K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1335&quot; height=&quot;1228&quot; data-origin-width=&quot;1335&quot; data-origin-height=&quot;1228&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1195&quot; data-origin-height=&quot;389&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caBwNf/dJMcaaFHGjH/d35lzKSSFK9lLPp8pEPHE1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caBwNf/dJMcaaFHGjH/d35lzKSSFK9lLPp8pEPHE1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caBwNf/dJMcaaFHGjH/d35lzKSSFK9lLPp8pEPHE1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaBwNf%2FdJMcaaFHGjH%2Fd35lzKSSFK9lLPp8pEPHE1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1195&quot; height=&quot;389&quot; data-origin-width=&quot;1195&quot; data-origin-height=&quot;389&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;NetDriver가 NULL이 아니면 클라이언트나 서버 중 하나다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;GetNetMode에서는 IsServer로 서버 여부를 먼저 판단하고, 클라이언트이자 서버면 리슨서버, 아니면 데디서버로 나눈다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;IsServer에서는 ServerConnection이 없다면 클라이언트로 판단한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;NetConnection이란?&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 PC와의 연결이 발생하면 그에 대응하는 UNetConnection 객체가 생성됨&lt;/li&gt;
&lt;li&gt;클라이언트가 접속하면 서버에는 ClientConnection객체, 클라이언트에는 ServerConnection 객체가 생성됨&lt;/li&gt;
&lt;li&gt;두 PC는 UNetConnection 객체를 통해 통신&lt;/li&gt;
&lt;li&gt;UNetDriver는 생성된 UNetConnection 객체를 소유하고 관리&lt;/li&gt;
&lt;li&gt;서버 PC에 생성된 UNetDriver는 접속한 클라이언트의 수만큼 UNetConnection을 관리&lt;/li&gt;
&lt;li&gt;클라이언트 PC에 생성된 UNetDriver는 ServerConnection 하나만 관리&lt;/li&gt;
&lt;li&gt;NetConnection은 PlayerController를 소유&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;클라이언트끼리의 통신은 불가능하고, 오직 서버와 클라이언트 사이의 통신만 가능하다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;NetDriver 구성요소&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1549&quot; data-origin-height=&quot;667&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKRtOx/dJMcaiDGC6R/uv5oVqGNjduGm3t4DDBDX1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKRtOx/dJMcaiDGC6R/uv5oVqGNjduGm3t4DDBDX1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKRtOx/dJMcaiDGC6R/uv5oVqGNjduGm3t4DDBDX1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKRtOx%2FdJMcaiDGC6R%2Fuv5oVqGNjduGm3t4DDBDX1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1549&quot; height=&quot;667&quot; data-origin-width=&quot;1549&quot; data-origin-height=&quot;667&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;ServerClient는 하나고 ClientConnections는 복수형인 것을 알 수 있다.&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NetDriver는 멀티플레이를 하기 위해서는 연결된 모든 디바이스에서 필수적으로 실행되어야한다. 오너가 서버인지 클라이언트에 따라&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ClientConnections 데이터를 가지고 있는지,&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ServerClient 데이터를 가지고 있는지가 다르다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;993&quot; data-origin-height=&quot;1064&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vp6VP/dJMcagy40it/7kXmA8qqx8yJFTRU0XFeG1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vp6VP/dJMcagy40it/7kXmA8qqx8yJFTRU0XFeG1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vp6VP/dJMcagy40it/7kXmA8qqx8yJFTRU0XFeG1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVp6VP%2FdJMcagy40it%2F7kXmA8qqx8yJFTRU0XFeG1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;993&quot; height=&quot;1064&quot; data-origin-width=&quot;993&quot; data-origin-height=&quot;1064&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;멀티플레이어에서의 OwnerShip&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2151&quot; data-origin-height=&quot;715&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/P8tKP/dJMcagy40iv/plOSxe01qHGkgE4uNP7CZ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/P8tKP/dJMcagy40iv/plOSxe01qHGkgE4uNP7CZ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/P8tKP/dJMcagy40iv/plOSxe01qHGkgE4uNP7CZ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FP8tKP%2FdJMcagy40iv%2FplOSxe01qHGkgE4uNP7CZ1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2151&quot; height=&quot;715&quot; data-origin-width=&quot;2151&quot; data-origin-height=&quot;715&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 ClientConnection은 하나의 PlayerController를 소유&lt;/li&gt;
&lt;li&gt;PlayerController의 Owning Connection은 ClientConnection인 셈&lt;/li&gt;
&lt;li&gt;PlayerController가 빙의하는 Pawn의 Owner 속성은 해당 PlayerController로 설정됨&lt;/li&gt;
&lt;li&gt;폰에 무기 액터가 생성되고, 무기 액터의 Owner 속성에 해당 폰을 설정할 수 있음&lt;/li&gt;
&lt;li&gt;ClientConnection에서부터 무기 액에터 이르는 소유관계를 패밀리라고도 부름&lt;/li&gt;
&lt;li&gt;소유 관계 속 액터가 본인의 Owing Connection을 얻으려면 AActor::GetNetConnection() 함수를 호출하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;NetDriver란?&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;언리얼 네트워크 통신에서 로우레벨 동작들을 관리하는 클래스&lt;/li&gt;
&lt;li&gt;싱글 플레이에서는 생성되지 않음&lt;/li&gt;
&lt;li&gt;멀티플레이에서만 UWorld::Listen()함수를 통해 UNetDriver 객체가 생성됨&lt;/li&gt;
&lt;li&gt;멀티플레이에 참여하는 각 PC마다 생성됨&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1035&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bosvGI/dJMcaiDGC6Q/tDxYt22HwreVqQRigV9mNk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bosvGI/dJMcaiDGC6Q/tDxYt22HwreVqQRigV9mNk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bosvGI/dJMcaiDGC6Q/tDxYt22HwreVqQRigV9mNk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbosvGI%2FdJMcaiDGC6Q%2FtDxYt22HwreVqQRigV9mNk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1035&quot; height=&quot;580&quot; data-origin-width=&quot;1035&quot; data-origin-height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;멀티플레이용 디버깅로그 작성하기&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1545&quot; data-origin-height=&quot;1263&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G29oj/dJMcaaFHGjJ/UXUJ6H5O9DbcKj603isZ6K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G29oj/dJMcaaFHGjJ/UXUJ6H5O9DbcKj603isZ6K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G29oj/dJMcaaFHGjJ/UXUJ6H5O9DbcKj603isZ6K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG29oj%2FdJMcaaFHGjJ%2FUXUJ6H5O9DbcKj603isZ6K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1545&quot; height=&quot;1263&quot; data-origin-width=&quot;1545&quot; data-origin-height=&quot;1263&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;데디서버는 뷰포트가 필요없다.&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;563&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uE7ci/dJMcagy40iu/4NWB8jn7KUgD4JfuQhJTZk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uE7ci/dJMcagy40iu/4NWB8jn7KUgD4JfuQhJTZk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uE7ci/dJMcagy40iu/4NWB8jn7KUgD4JfuQhJTZk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuE7ci%2FdJMcagy40iu%2F4NWB8jn7KUgD4JfuQhJTZk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1135&quot; height=&quot;563&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;563&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;771&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kwWtL/dJMcagy40ir/DEkekP39LxKkBnrKfN1tf1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kwWtL/dJMcagy40ir/DEkekP39LxKkBnrKfN1tf1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kwWtL/dJMcagy40ir/DEkekP39LxKkBnrKfN1tf1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkwWtL%2FdJMcagy40ir%2FDEkekP39LxKkBnrKfN1tf1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1288&quot; height=&quot;771&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;771&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;위와 같이 로그 코드를 추가하고 클라이언트에서 메시지를 치면 클라이언트로 나온다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;411&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oIVZP/dJMcagy40is/ziVizYoUYgXdEQEPzKOeA0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oIVZP/dJMcagy40is/ziVizYoUYgXdEQEPzKOeA0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oIVZP/dJMcagy40is/ziVizYoUYgXdEQEPzKOeA0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoIVZP%2FdJMcagy40is%2FziVizYoUYgXdEQEPzKOeA0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;935&quot; height=&quot;411&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;411&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;플레이어 수 1, 넷모드는 Standalone으로 변경한다.&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;if (IsLocalController() == false)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;return;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;이 부분을 빼고&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;코드를 추가 수정하면 StandAlone인지 알 수 있다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;로깅할 때 이런 식으로 어느 쪽에서 작동하는지를 표시해주어야한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;StandAlone&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;게임이 원격 클라이언트의 연결을 허용하지 않는 서버로 실행 중&lt;/li&gt;
&lt;li&gt;커넥션 없음&lt;/li&gt;
&lt;li&gt;모든 플레이어는 로컬 플레이어&lt;/li&gt;
&lt;li&gt;싱글 및 로컬 플레이에 사용&lt;/li&gt;
&lt;li&gt;로컬 플레이어에 맞게 서버측 로직과 클라이언트축 로직을 모두 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;Client&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;게임이 네트워크 멀티플레이 세션에 서 서버에 연결된 클라이언트로 실행됨&lt;/li&gt;
&lt;li&gt;서버 측 로직을 실행하지 않음&lt;/li&gt;
&lt;li&gt;서버로부터 복제된 Proxy만 보여주는 역할을 함&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;Listen 서버&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;게임이 네트워크 멀티플레이어 세션을 호스팅하는 서버로 실행 중&lt;/li&gt;
&lt;li&gt;원격 클라이언트의 연결을 수락하고 로컬 플레이어를 서버에 직접 배치&lt;/li&gt;
&lt;li&gt;서버 자신도 게임에 참여&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;Dedicated Server&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;게임이 네트워크 멀티플레이 세션을 호스팅하는 서버로 실행됨&lt;/li&gt;
&lt;li&gt;로컬 플레이어가 없음&lt;/li&gt;
&lt;li&gt;그래픽, 사운드 등 플레이어 중심 기능 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;서버에만 존재하는 액터&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;게임모드&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;서버와 모든 클라이언트에 존재하는 액터&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배경 액터와 폰&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;서버와 클라이언트에만 존재하는 액터&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;플레이어 컨트롤러&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;클라이언트에만 존재하는 언리얼 오브젝트&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;애니메이션 블루프린트, UI&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;클라이언트에서 GameMode를 호출하면 nullptr이 반환된다. 그래서 GameMode에 접근하려면 Server RPC 함수 내에서 접근하거나, 서버에서도 수행되는 함수 내에서 HasAuthority() 함수로 서버임을 확인하고 접근한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>게임 개발/학습 일지</category>
      <category>언리얼멀티플레이</category>
      <author>이개</author>
      <guid isPermaLink="true">https://igae-dev.tistory.com/174</guid>
      <comments>https://igae-dev.tistory.com/174#entry174comment</comments>
      <pubDate>Wed, 17 Jun 2026 10:03:06 +0900</pubDate>
    </item>
    <item>
      <title>언리얼 내배캠 - 언리얼 멀티플레이 기초 실습 환경 설정</title>
      <link>https://igae-dev.tistory.com/173</link>
      <description>&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플레이모드 메뉴에서 플레이어 수를 2, 넷모드는 클라이언트로 지정해준다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1708&quot; data-origin-height=&quot;953&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r4wIG/dJMcah5TivR/9k9yyp7IG8OtGo5wJqPF80/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r4wIG/dJMcah5TivR/9k9yyp7IG8OtGo5wJqPF80/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r4wIG/dJMcah5TivR/9k9yyp7IG8OtGo5wJqPF80/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr4wIG%2FdJMcah5TivR%2F9k9yyp7IG8OtGo5wJqPF80%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1708&quot; height=&quot;953&quot; data-origin-width=&quot;1708&quot; data-origin-height=&quot;953&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2087&quot; data-origin-height=&quot;1186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VYVWE/dJMcah5TivO/bynWkt1if8HIp8zrFNfyH0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VYVWE/dJMcah5TivO/bynWkt1if8HIp8zrFNfyH0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VYVWE/dJMcah5TivO/bynWkt1if8HIp8zrFNfyH0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVYVWE%2FdJMcah5TivO%2FbynWkt1if8HIp8zrFNfyH0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2087&quot; height=&quot;1186&quot; data-origin-width=&quot;2087&quot; data-origin-height=&quot;1186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;PIE 모드로 실행시키고 채팅을 치면 동기화가 되는 것을 볼 수 있다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5OYLb/dJMcahEJuHz/noFX4LkhOW1KCTZUyFFqRk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5OYLb/dJMcahEJuHz/noFX4LkhOW1KCTZUyFFqRk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5OYLb/dJMcahEJuHz/noFX4LkhOW1KCTZUyFFqRk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5OYLb%2FdJMcahEJuHz%2FnoFX4LkhOW1KCTZUyFFqRk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1294&quot; height=&quot;146&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;146&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;출력 로그는 이러하다.&lt;/div&gt;
&lt;div&gt;모든 것이 동기화 될 필요는 없다. 위젯 객체같은 경우 Owning Client에서만 생성되면 된다. 로컬 플레이어 컨트롤러가 아니면 위와 같은 에러가 뜨게 된다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1220&quot; data-origin-height=&quot;789&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GAnPW/dJMcah5TivP/G8oDfHU78My6V0DYDmVPE0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GAnPW/dJMcah5TivP/G8oDfHU78My6V0DYDmVPE0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GAnPW/dJMcah5TivP/G8oDfHU78My6V0DYDmVPE0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGAnPW%2FdJMcah5TivP%2FG8oDfHU78My6V0DYDmVPE0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1220&quot; height=&quot;789&quot; data-origin-width=&quot;1220&quot; data-origin-height=&quot;789&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;Ctrl + T를 눌러 코드를 검색할 수 있다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;CXPlayerController.cpp&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;239&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1sXQu/dJMcah5TivM/shRBTyApheXi68vp3kpGxK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1sXQu/dJMcah5TivM/shRBTyApheXi68vp3kpGxK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1sXQu/dJMcah5TivM/shRBTyApheXi68vp3kpGxK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1sXQu%2FdJMcah5TivM%2FshRBTyApheXi68vp3kpGxK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;699&quot; height=&quot;239&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;239&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;IsLocalController() 조건을 걸어주면 정상 처리된다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;채팅을 치면 다른 클라이언트에서 보이는 이유&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Run Under One Process 속성 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;데디케이티드 서버 환경 설정&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1761&quot; data-origin-height=&quot;838&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLqSo8/dJMcai4GdRj/rXWkJ78JPzEKa7nTpk6wvK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLqSo8/dJMcai4GdRj/rXWkJ78JPzEKa7nTpk6wvK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLqSo8/dJMcai4GdRj/rXWkJ78JPzEKa7nTpk6wvK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLqSo8%2FdJMcai4GdRj%2FrXWkJ78JPzEKa7nTpk6wvK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1761&quot; height=&quot;838&quot; data-origin-width=&quot;1761&quot; data-origin-height=&quot;838&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;에디터 개인설정-&amp;gt;레벨 에디터 카테고리의 플레이-&amp;gt; 단일 프로세스 하 실행 체크 해제&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;체크할 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2134&quot; data-origin-height=&quot;1168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/enVXQ1/dJMcafNMHRh/rEk6MgQmErRq8f2hxhsiXk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/enVXQ1/dJMcafNMHRh/rEk6MgQmErRq8f2hxhsiXk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/enVXQ1/dJMcafNMHRh/rEk6MgQmErRq8f2hxhsiXk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FenVXQ1%2FdJMcafNMHRh%2FrEk6MgQmErRq8f2hxhsiXk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2134&quot; height=&quot;1168&quot; data-origin-width=&quot;2134&quot; data-origin-height=&quot;1168&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;체크 해제 후 실행하면 서버가 따로 실행되며 Join Succeeded라는 메뉴가 출력된다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2085&quot; data-origin-height=&quot;1167&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGDwg8/dJMcah5TivQ/Um3nKSxlnMv6kVHSo0e2T0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGDwg8/dJMcah5TivQ/Um3nKSxlnMv6kVHSo0e2T0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGDwg8/dJMcah5TivQ/Um3nKSxlnMv6kVHSo0e2T0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGDwg8%2FdJMcah5TivQ%2FUm3nKSxlnMv6kVHSo0e2T0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2085&quot; height=&quot;1167&quot; data-origin-width=&quot;2085&quot; data-origin-height=&quot;1167&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이렇게 멀티 프로세스로 실행 시에는 내 화면에서만 문장이 출력된다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1133&quot; data-origin-height=&quot;273&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EOpIZ/dJMcai4GdRi/jDpEVDhbt9bXVoNt8PO4Mk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EOpIZ/dJMcai4GdRi/jDpEVDhbt9bXVoNt8PO4Mk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EOpIZ/dJMcai4GdRi/jDpEVDhbt9bXVoNt8PO4Mk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEOpIZ%2FdJMcai4GdRi%2FjDpEVDhbt9bXVoNt8PO4Mk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1133&quot; height=&quot;273&quot; data-origin-width=&quot;1133&quot; data-origin-height=&quot;273&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;추가로 Allow Late Joining을 체크하여 Add another cliner 버튼으로 클라이언트 추가가 가능하게 한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;889&quot; data-origin-height=&quot;396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZY5Sc/dJMcahEJuHA/nMvZUn6iyle9xjwSNULSSK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZY5Sc/dJMcahEJuHA/nMvZUn6iyle9xjwSNULSSK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZY5Sc/dJMcahEJuHA/nMvZUn6iyle9xjwSNULSSK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZY5Sc%2FdJMcahEJuHA%2FnMvZUn6iyle9xjwSNULSSK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;889&quot; height=&quot;396&quot; data-origin-width=&quot;889&quot; data-origin-height=&quot;396&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;클라이언트 추가 버튼으로 클라이언트를 추가할 수 있다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1097&quot; data-origin-height=&quot;297&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDWdqa/dJMcafNMHRg/AwXhEIyxyHDmhbd9XL2DW0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDWdqa/dJMcafNMHRg/AwXhEIyxyHDmhbd9XL2DW0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDWdqa/dJMcafNMHRg/AwXhEIyxyHDmhbd9XL2DW0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDWdqa%2FdJMcafNMHRg%2FAwXhEIyxyHDmhbd9XL2DW0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1097&quot; height=&quot;297&quot; data-origin-width=&quot;1097&quot; data-origin-height=&quot;297&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;Always on top 체크하면 새 클라이언트 화면이 항상 위에 뜬다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Multiplayer Options에서 추가설정이 가능하다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1389&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQklAn/dJMcah5TivN/8U3b9Hi3DvdIKmk57tklkK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQklAn/dJMcah5TivN/8U3b9Hi3DvdIKmk57tklkK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQklAn/dJMcah5TivN/8U3b9Hi3DvdIKmk57tklkK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQklAn%2FdJMcah5TivN%2F8U3b9Hi3DvdIKmk57tklkK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1389&quot; height=&quot;456&quot; data-origin-width=&quot;1389&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개별 서버 실행&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;체크 시 서버를 따로 띄워준다&lt;/li&gt;
&lt;li&gt;미체크 시 에디터 화면이 클라이언트이자 서버가 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>게임 개발/학습 일지</category>
      <author>이개</author>
      <guid isPermaLink="true">https://igae-dev.tistory.com/173</guid>
      <comments>https://igae-dev.tistory.com/173#entry173comment</comments>
      <pubDate>Tue, 16 Jun 2026 09:14:16 +0900</pubDate>
    </item>
    <item>
      <title>언리얼 내배캠 마스터반 - Subsystem 기반으로 아이템 매니저 만들기</title>
      <link>https://igae-dev.tistory.com/172</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;총 세 가지의 클래스를 만든다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GameInstanceSubsystem &amp;rarr; ItemManagerSubsystem&lt;/li&gt;
&lt;li&gt;PrimaryDataAsset &amp;rarr; ItemDataAsset&lt;/li&gt;
&lt;li&gt;플레이하고 아이템 장착 할 액터 &amp;rarr; ItemManagerTestCharacter&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1069&quot; data-origin-height=&quot;1289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcztgi/dJMcagTmnur/aZI8norxx8pNOkos8ytSp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcztgi/dJMcagTmnur/aZI8norxx8pNOkos8ytSp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcztgi/dJMcagTmnur/aZI8norxx8pNOkos8ytSp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbcztgi%2FdJMcagTmnur%2FaZI8norxx8pNOkos8ytSp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1069&quot; height=&quot;1289&quot; data-origin-width=&quot;1069&quot; data-origin-height=&quot;1289&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1781062250731&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &quot;Engine/AssetManager.h&quot;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnItemLoaded, FPrimaryAssetId, AssetId);


public:
    // 서브시스템 초기화 시 호출
    virtual void Initialize(FSubsystemCollectionBase&amp;amp; Collection) override;

    // 아이템 비동기 로드 요청
    UFUNCTION(BlueprintCallable, Category = &quot;ItemManager&quot;)
    void RequestAsyncLoadItem(FPrimaryAssetId AssetId);

    // 로드된 아이템 가져오기 (이미 로드된 경우만 반환)
    UFUNCTION(BlueprintCallable, Category = &quot;ItemManager&quot;)
    class UMyItemDataAsset* GetItemData(FPrimaryAssetId AssetId);

    // 아이템 메모리 해제
    UFUNCTION(BlueprintCallable, Category = &quot;ItemManager&quot;)
    void UnloadItem(FPrimaryAssetId AssetId);



    //델리게이트
    UPROPERTY(BlueprintAssignable, Category = &quot;ItemManager&quot;)
    FOnItemLoaded OnItemLoaded;


private:
    void OnLoadCompleted(FPrimaryAssetId AssetId);

    // 로드된 핸들을 보관하여 가비지 컬렉션을 방지
    TMap&amp;lt;FPrimaryAssetId, TSharedPtr&amp;lt;FStreamableHandle&amp;gt;&amp;gt; LoadingHandles;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1781062265125&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void UItemManagerSubsystem::Initialize(FSubsystemCollectionBase&amp;amp; Collection)
{
	Super::Initialize(Collection);
	UE_LOG(LogTemp, Log, TEXT(&quot;Item Manager Subsystem Initialized!&quot;));
}

void UItemManagerSubsystem::RequestAsyncLoadItem(FPrimaryAssetId AssetId)
{
    if (!AssetId.IsValid()) return;

    // 이미 로드 중이거나 로드 완료되었는지 확인
    if (LoadingHandles.Contains(AssetId) &amp;amp;&amp;amp; LoadingHandles[AssetId]-&amp;gt;IsActive())
    {
        return;
    }

    UAssetManager&amp;amp; Manager = UAssetManager::Get();

    // 비동기 로드 시작
    TSharedPtr&amp;lt;FStreamableHandle&amp;gt; Handle = Manager.LoadPrimaryAsset(
        AssetId,
        TArray&amp;lt;FName&amp;gt;(),
        FStreamableDelegate::CreateUObject(this, &amp;amp;UItemManagerSubsystem::OnLoadCompleted, AssetId)
    );

    LoadingHandles.Add(AssetId, Handle);
}

UMyItemDataAsset* UItemManagerSubsystem::GetItemData(FPrimaryAssetId AssetId)
{
    // 에셋 매니저를 통해 메모리에 올라온 객체 포인터를 즉시 반환
    return UAssetManager::Get().GetPrimaryAssetObject&amp;lt;UMyItemDataAsset&amp;gt;(AssetId);
}

void UItemManagerSubsystem::UnloadItem(FPrimaryAssetId AssetId)
{
    if (LoadingHandles.Contains(AssetId))
    {
        // 핸들을 해제하여 에셋 매니저가 참조를 끊게 함 (GC 대상이 됨)
        LoadingHandles.Remove(AssetId);
        UAssetManager::Get().UnloadPrimaryAsset(AssetId);
        UE_LOG(LogTemp, Log, TEXT(&quot;Item Unloaded: %s&quot;), *AssetId.ToString());
    }
}

void UItemManagerSubsystem::OnLoadCompleted(FPrimaryAssetId AssetId)
{
    UE_LOG(LogTemp, Log, TEXT(&quot;Item Loaded via Subsystem: %s&quot;), *AssetId.ToString());

    // 로드 완료 알림
    if (OnItemLoaded.IsBound())
    {
        OnItemLoaded.Broadcast(AssetId);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Primary Data Asset&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;614&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sRNJv/dJMcajbm5WN/HVlUK35JEarcSEBYjZQPUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sRNJv/dJMcajbm5WN/HVlUK35JEarcSEBYjZQPUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sRNJv/dJMcajbm5WN/HVlUK35JEarcSEBYjZQPUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsRNJv%2FdJMcajbm5WN%2FHVlUK35JEarcSEBYjZQPUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;979&quot; height=&quot;614&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;614&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1781062300535&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public:
    // 에셋 매니저에서 식별할 타입 이름 (예: &quot;Weapon&quot;)
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = &quot;Item&quot;)
    FPrimaryAssetType ItemType;

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = &quot;Stats&quot;)
    float AttackDamage;

    // 무거운 에셋은 SoftObjectPtr로 선언해서 로드 시점을 제어합니다.
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = &quot;Visual&quot;)
    TSoftObjectPtr&amp;lt;USkeletalMesh&amp;gt; ItemMesh;

    // ID를 반환하는 함수 오버라이드 (Asset Manager가 식별할 때 사용)
    virtual FPrimaryAssetId GetPrimaryAssetId() const override
    {
        return FPrimaryAssetId(ItemType, GetFName());
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>게임 개발/학습 일지</category>
      <author>이개</author>
      <guid isPermaLink="true">https://igae-dev.tistory.com/172</guid>
      <comments>https://igae-dev.tistory.com/172#entry172comment</comments>
      <pubDate>Mon, 15 Jun 2026 08:05:38 +0900</pubDate>
    </item>
    <item>
      <title>언리얼 내배캠 마스터반 수업 - Subsystem과 수명 관리</title>
      <link>https://igae-dev.tistory.com/171</link>
      <description>&lt;div&gt;Subsystem이란?&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내가 직접 만들고 관리하지 않아도 엔진이 알아서 켜고 꺼주는 시스템&lt;/li&gt;
&lt;li&gt;실행 시점과 수명을 직접 결정할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1043&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pPxsR/dJMcaftl7co/VqiWTVef0YgxlCz503Mu3K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pPxsR/dJMcaftl7co/VqiWTVef0YgxlCz503Mu3K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pPxsR/dJMcaftl7co/VqiWTVef0YgxlCz503Mu3K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpPxsR%2FdJMcaftl7co%2FVqiWTVef0YgxlCz503Mu3K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1043&quot; height=&quot;424&quot; data-origin-width=&quot;1043&quot; data-origin-height=&quot;424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Engine&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속받는 원본 클래스&lt;/li&gt;
&lt;li&gt;태어나는 시점&lt;/li&gt;
&lt;li&gt;사라지는 시점&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;Editor&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속받는 원본 클래스&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;태어나는 시점&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;사라지는 시점&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;GameInstance&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속받는 원본 클래스&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;태어나는 시점&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사라지는 시점&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
World(UE5에서 추가)&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속받는 원본 클래스&lt;/li&gt;
&lt;li&gt;태어나는 시점&lt;/li&gt;
&lt;li&gt;사라지는 시점&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
LocalPlayer&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속받는 원본 클래스&lt;/li&gt;
&lt;li&gt;태어나는 시점&lt;/li&gt;
&lt;li&gt;사라지는 시점&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;서브시스템의 장점&lt;/div&gt;
&lt;div&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;통계, UI 관리 기능 등을 별도 파일로 분리해 관리 가능하여 코드가 깔끔해진다.&lt;/li&gt;
&lt;li&gt;NewObject로 생성하고 가비지 컬렉션을 걱정할 필요없다. 엔진이 생명주기를 책임진다.&lt;/li&gt;
&lt;li&gt;플러그인을 만들 때 사용자가 따로 설정할 필요없이, 플러그인을 넣기만 하면 서브시스템이 자동으로 활성화되어 기능을 수행한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;내부 에셋들을 할당받기는 힘들다. 블루프린트로 할당하기에는 불안정하다. 하드코딩으로 넣어놓을 수는 있다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;실습&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;840&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmV3xM/dJMcaicBThL/WxjPVpblIKhb1KNtPv0lb0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmV3xM/dJMcaicBThL/WxjPVpblIKhb1KNtPv0lb0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmV3xM/dJMcaicBThL/WxjPVpblIKhb1KNtPv0lb0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmV3xM%2FdJMcaicBThL%2FWxjPVpblIKhb1KNtPv0lb0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1396&quot; height=&quot;840&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;840&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;WorldSubsystem을 상속받은 새 클래스&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;MyWorldSubsystem을&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;만든다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1397&quot; data-origin-height=&quot;837&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vEyEr/dJMcagZ4bEF/kZxE25xuvOYlZCq8kgkxfk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vEyEr/dJMcagZ4bEF/kZxE25xuvOYlZCq8kgkxfk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vEyEr/dJMcagZ4bEF/kZxE25xuvOYlZCq8kgkxfk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvEyEr%2FdJMcagZ4bEF%2FkZxE25xuvOYlZCq8kgkxfk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1397&quot; height=&quot;837&quot; data-origin-width=&quot;1397&quot; data-origin-height=&quot;837&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;648&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qvq1c/dJMcagZ4bEG/cNsl9qIkaryH2CggyYkW9K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qvq1c/dJMcagZ4bEG/cNsl9qIkaryH2CggyYkW9K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qvq1c/dJMcagZ4bEG/cNsl9qIkaryH2CggyYkW9K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqvq1c%2FdJMcagZ4bEG%2FcNsl9qIkaryH2CggyYkW9K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;982&quot; height=&quot;648&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;virtual void Initialize(FSubsystemCollectionBase&amp;amp; Collection) override;&lt;/div&gt;
&lt;div&gt;virtual void Deinitialize() override;&lt;/div&gt;
&lt;div&gt;두 함수를 오버라이드한다.&lt;/div&gt;
&lt;div&gt;Deinitialize에서는 파일 저장이나 Unbind 등을 진행해주면 된다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;671&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kV03L/dJMcaftl7cq/vRCearGN8NZND31ShIKH51/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kV03L/dJMcaftl7cq/vRCearGN8NZND31ShIKH51/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kV03L/dJMcaftl7cq/vRCearGN8NZND31ShIKH51/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkV03L%2FdJMcaftl7cq%2FvRCearGN8NZND31ShIKH51%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1088&quot; height=&quot;671&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;671&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;UE_LOG로 서브시스템의 시작과 끝을 확인한다.&lt;/div&gt;
&lt;div&gt;종료되는 함수는 Super를 뒤에 붙인다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1504&quot; data-origin-height=&quot;972&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BdUJn/dJMcaicBThQ/pHW3Ia23qQ6NXenScUSKf0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BdUJn/dJMcaicBThQ/pHW3Ia23qQ6NXenScUSKf0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BdUJn/dJMcaicBThQ/pHW3Ia23qQ6NXenScUSKf0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBdUJn%2FdJMcaicBThQ%2FpHW3Ia23qQ6NXenScUSKf0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1504&quot; height=&quot;972&quot; data-origin-width=&quot;1504&quot; data-origin-height=&quot;972&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;로그를 확인하기 위해 레벨 플루프린트에 Open Level 노드를 배치한다.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1348&quot; data-origin-height=&quot;925&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pgFmT/dJMcagZ4bEH/sxD0fk5BPHdYjEX00A4MWK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pgFmT/dJMcagZ4bEH/sxD0fk5BPHdYjEX00A4MWK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pgFmT/dJMcagZ4bEH/sxD0fk5BPHdYjEX00A4MWK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpgFmT%2FdJMcagZ4bEH%2FsxD0fk5BPHdYjEX00A4MWK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1348&quot; height=&quot;925&quot; data-origin-width=&quot;1348&quot; data-origin-height=&quot;925&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;새 월드가 열릴 때마다 로그가 출력되는 것을 확인할 수 있다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;서브시스템 자동활성화 제어&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;673&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FF0p3/dJMcaicBThR/PCOlfKiwX5KXxUu1oD863K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FF0p3/dJMcaicBThR/PCOlfKiwX5KXxUu1oD863K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FF0p3/dJMcaicBThR/PCOlfKiwX5KXxUu1oD863K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFF0p3%2FdJMcaicBThR%2FPCOlfKiwX5KXxUu1oD863K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1212&quot; height=&quot;673&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;673&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;UWorldSubsystem에 들어가면 ShouldCreateSubsystem이라는 함수가 있는데, 여기서 활성화 여부를 제어할 수 있다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;84&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkWWGS/dJMcaicBThM/oWBxHV8VkBFhF5mlWuZLUk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkWWGS/dJMcaicBThM/oWBxHV8VkBFhF5mlWuZLUk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkWWGS/dJMcaicBThM/oWBxHV8VkBFhF5mlWuZLUk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkWWGS%2FdJMcaicBThM%2FoWBxHV8VkBFhF5mlWuZLUk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;769&quot; height=&quot;84&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;84&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTGi1N/dJMcaicBThN/FQp3FbhqtddEm5tao2AJZ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTGi1N/dJMcaicBThN/FQp3FbhqtddEm5tao2AJZ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTGi1N/dJMcaicBThN/FQp3FbhqtddEm5tao2AJZ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTGi1N%2FdJMcaicBThN%2FFQp3FbhqtddEm5tao2AJZ1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;186&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;true면 생성, false면 미생성&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;UWorld* World = Cast&amp;lt;UWorld&amp;gt;(Outer);&amp;nbsp;&lt;/div&gt;
&lt;div&gt;-&amp;gt; 현재 액터의 상위 액터&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;ex) 스타터 맵에서만 실행하고 싶은 경우&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkjQl7/dJMcaftl7cn/kPqZL7WtWXIkgOVC7OUsnk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkjQl7/dJMcaftl7cn/kPqZL7WtWXIkgOVC7OUsnk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkjQl7/dJMcaftl7cn/kPqZL7WtWXIkgOVC7OUsnk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkjQl7%2FdJMcaftl7cn%2FkPqZL7WtWXIkgOVC7OUsnk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;836&quot; height=&quot;219&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;219&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;World를 가져오고, World의 맵 이름에 StaterMap이 들어가는지 확인해서 해당 맵에서만 띄우기&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1553&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cck3xg/dJMcaftl7cr/QN4J5uQftli65WduXKZH9k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cck3xg/dJMcaftl7cr/QN4J5uQftli65WduXKZH9k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cck3xg/dJMcaftl7cr/QN4J5uQftli65WduXKZH9k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcck3xg%2FdJMcaftl7cr%2FQN4J5uQftli65WduXKZH9k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1553&quot; height=&quot;796&quot; data-origin-width=&quot;1553&quot; data-origin-height=&quot;796&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;블루프린트에서 서브시스템을 갖고 오고싶다면 바로 호출이 가능하다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqYySg/dJMcagZ4bEE/NkaW5agsHOBW5vQjGeqScK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqYySg/dJMcagZ4bEE/NkaW5agsHOBW5vQjGeqScK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqYySg/dJMcagZ4bEE/NkaW5agsHOBW5vQjGeqScK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqYySg%2FdJMcagZ4bEE%2FNkaW5agsHOBW5vQjGeqScK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;831&quot; height=&quot;362&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;362&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;날씨 서브시스템과 시간 서브시스템의 관계&lt;/div&gt;
&lt;div&gt;만약 시간에 따라 날씨를 조정하고 싶다고하면, 시간 서브시스템이 먼저 생성되고 날씨 시스템은 시간을 가져와서 조정을 할 수 있어야 한다. 그래서 Collection을 통해 의존성을 주입하여 선행 초기화를 시켜준다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1371&quot; data-origin-height=&quot;844&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cX1RZY/dJMcaicBThO/vOKQwUo0UKYgif24dhX2z0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cX1RZY/dJMcaicBThO/vOKQwUo0UKYgif24dhX2z0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cX1RZY/dJMcaicBThO/vOKQwUo0UKYgif24dhX2z0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcX1RZY%2FdJMcaicBThO%2FvOKQwUo0UKYgif24dhX2z0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1371&quot; height=&quot;844&quot; data-origin-width=&quot;1371&quot; data-origin-height=&quot;844&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;847&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lkaBi/dJMcaicBThS/oQRu8rCvK5yEcYaf6AvZL1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lkaBi/dJMcaicBThS/oQRu8rCvK5yEcYaf6AvZL1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lkaBi/dJMcaicBThS/oQRu8rCvK5yEcYaf6AvZL1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlkaBi%2FdJMcaicBThS%2FoQRu8rCvK5yEcYaf6AvZL1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1386&quot; height=&quot;847&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;847&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;TimeWorldSubsystem을 만들어준다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LUU6Z/dJMcaicBThP/tJLpGQmRUrcK1QxF4BGbtk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LUU6Z/dJMcaicBThP/tJLpGQmRUrcK1QxF4BGbtk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LUU6Z/dJMcaicBThP/tJLpGQmRUrcK1QxF4BGbtk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLUU6Z%2FdJMcaicBThP%2FtJLpGQmRUrcK1QxF4BGbtk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1052&quot; height=&quot;634&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bx0cS/dJMcaftl7cp/Geu3cSWQXBqblAFFKfTUb1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bx0cS/dJMcaftl7cp/Geu3cSWQXBqblAFFKfTUb1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bx0cS/dJMcaftl7cp/Geu3cSWQXBqblAFFKfTUb1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBx0cS%2FdJMcaftl7cp%2FGeu3cSWQXBqblAFFKfTUb1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1075&quot; height=&quot;658&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;GetCurrentHour 함수를 만들고 시간을 리턴해준다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;MyWorldSubsystem.cpp에서 연동해준다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1175&quot; data-origin-height=&quot;1064&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QjlKT/dJMcaftl7cs/NJ3zTxhrazlL3PrkMdg2ik/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QjlKT/dJMcaftl7cs/NJ3zTxhrazlL3PrkMdg2ik/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QjlKT/dJMcaftl7cs/NJ3zTxhrazlL3PrkMdg2ik/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQjlKT%2FdJMcaftl7cs%2FNJ3zTxhrazlL3PrkMdg2ik%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1175&quot; height=&quot;1064&quot; data-origin-width=&quot;1175&quot; data-origin-height=&quot;1064&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;UTimeWorldSubsystem* TimeSub = Collection.InitializeDependency&amp;lt;UTimeWorldSubsystem&amp;gt;(); 로&amp;nbsp;UTimeWorldSubsystem을 먼저 생성해주는 것이다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1501&quot; data-origin-height=&quot;998&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buXPg7/dJMcaicBThT/gJmyg3JX6EYFMamjZTPkkK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buXPg7/dJMcaicBThT/gJmyg3JX6EYFMamjZTPkkK/img.jpg&quot; data-alt=&quot;실행 화면. 생성 초기에만 한번 실행하기 때문에 0이 뜬다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buXPg7/dJMcaicBThT/gJmyg3JX6EYFMamjZTPkkK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuXPg7%2FdJMcaicBThT%2FgJmyg3JX6EYFMamjZTPkkK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1501&quot; height=&quot;998&quot; data-origin-width=&quot;1501&quot; data-origin-height=&quot;998&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 화면. 생성 초기에만 한번 실행하기 때문에 0이 뜬다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>게임 개발/학습 일지</category>
      <author>이개</author>
      <guid isPermaLink="true">https://igae-dev.tistory.com/171</guid>
      <comments>https://igae-dev.tistory.com/171#entry171comment</comments>
      <pubDate>Wed, 10 Jun 2026 12:28:19 +0900</pubDate>
    </item>
    <item>
      <title>언리얼 내배캠 - 언리얼 멀티플레이 기초 채팅 프로젝트 생성</title>
      <link>https://igae-dev.tistory.com/170</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;패키징을 하기 위해서는 200GB 넘게 필요하기 때문에 넉넉한 용량(웬만하면 2TB이상)이 필요하다.&lt;/p&gt;
&lt;div&gt;또한, 경로 문제가 발생할 수 있어서 한 드라이브에 다 설치해주는 것이 좋다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;프로젝트 생성&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1777&quot; data-origin-height=&quot;1279&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1SSx7/dJMcaijjM8z/2NlvLpAKKwbzDDsxsBtRRK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1SSx7/dJMcaijjM8z/2NlvLpAKKwbzDDsxsBtRRK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1SSx7/dJMcaijjM8z/2NlvLpAKKwbzDDsxsBtRRK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1SSx7%2FdJMcaijjM8z%2F2NlvLpAKKwbzDDsxsBtRRK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1777&quot; height=&quot;1279&quot; data-origin-width=&quot;1777&quot; data-origin-height=&quot;1279&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;ChatX라는 이름의 프로젝트를 하나 생성한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;새 레벨을 만든다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;893&quot; data-origin-height=&quot;772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xdcEr/dJMcageJWLR/oF81C0uKW2ezBjuNR193KK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xdcEr/dJMcageJWLR/oF81C0uKW2ezBjuNR193KK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xdcEr/dJMcageJWLR/oF81C0uKW2ezBjuNR193KK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxdcEr%2FdJMcageJWLR%2FoF81C0uKW2ezBjuNR193KK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;893&quot; height=&quot;772&quot; data-origin-width=&quot;893&quot; data-origin-height=&quot;772&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;539&quot; data-origin-height=&quot;333&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DrLXJ/dJMcaijjM8l/HkfrWcbTkra7xh9TRaQAkk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DrLXJ/dJMcaijjM8l/HkfrWcbTkra7xh9TRaQAkk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DrLXJ/dJMcaijjM8l/HkfrWcbTkra7xh9TRaQAkk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDrLXJ%2FdJMcaijjM8l%2FHkfrWcbTkra7xh9TRaQAkk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;539&quot; height=&quot;333&quot; data-origin-width=&quot;539&quot; data-origin-height=&quot;333&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;컨텐츠 폴더 안에 프로젝트와 같은 이름의 폴더를 만든다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Ctrl+Shift+S로 저장해줘야만 전체 상황이 저장된다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;945&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLyeR6/dJMcadPMIKL/DF38bU8sh6JKHojEw4gxk1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLyeR6/dJMcadPMIKL/DF38bU8sh6JKHojEw4gxk1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLyeR6/dJMcadPMIKL/DF38bU8sh6JKHojEw4gxk1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLyeR6%2FdJMcadPMIKL%2FDF38bU8sh6JKHojEw4gxk1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1530&quot; height=&quot;945&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;945&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;맵 &amp;amp; 모드에서 만든 레벨로 레벨을 수정해준다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1348&quot; data-origin-height=&quot;819&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvY95V/dJMcah5Pp8n/rQo1bQOx11CN586t3DlgCK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvY95V/dJMcah5Pp8n/rQo1bQOx11CN586t3DlgCK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvY95V/dJMcah5Pp8n/rQo1bQOx11CN586t3DlgCK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvY95V%2FdJMcah5Pp8n%2FrQo1bQOx11CN586t3DlgCK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1348&quot; height=&quot;819&quot; data-origin-width=&quot;1348&quot; data-origin-height=&quot;819&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1368&quot; data-origin-height=&quot;807&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsafeD/dJMcaijjM8x/URnEQGIODJDzyxnjs9Xlw0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsafeD/dJMcaijjM8x/URnEQGIODJDzyxnjs9Xlw0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsafeD/dJMcaijjM8x/URnEQGIODJDzyxnjs9Xlw0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsafeD%2FdJMcaijjM8x%2FURnEQGIODJDzyxnjs9Xlw0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1368&quot; height=&quot;807&quot; data-origin-width=&quot;1368&quot; data-origin-height=&quot;807&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;새 게임모드 베이스를 만들어준다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;라이브코딩은 꺼준다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2sQof/dJMcaijjM8r/Kk5e6NzFEfeb4SDwwT2NO0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2sQof/dJMcaijjM8r/Kk5e6NzFEfeb4SDwwT2NO0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2sQof/dJMcaijjM8r/Kk5e6NzFEfeb4SDwwT2NO0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2sQof%2FdJMcaijjM8r%2FKk5e6NzFEfeb4SDwwT2NO0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;816&quot; height=&quot;262&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;262&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;cpp파일 include에서 에러가 뜨는 경우는 경로 오류이다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqvL2D/dJMcaijjM8p/UtURAGUaQuIjXYkBi1vQKk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqvL2D/dJMcaijjM8p/UtURAGUaQuIjXYkBi1vQKk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqvL2D/dJMcaijjM8p/UtURAGUaQuIjXYkBi1vQKk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqvL2D%2FdJMcaijjM8p%2FUtURAGUaQuIjXYkBi1vQKk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;305&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;같은 폴더 안에 있는 경우 Game/을 지워주면 된다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1373&quot; data-origin-height=&quot;683&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLGDaa/dJMcadPMIKS/2VkZGdiR6FuMnHzMgz2V41/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLGDaa/dJMcadPMIKS/2VkZGdiR6FuMnHzMgz2V41/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLGDaa/dJMcadPMIKS/2VkZGdiR6FuMnHzMgz2V41/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLGDaa%2FdJMcadPMIKS%2F2VkZGdiR6FuMnHzMgz2V41%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1373&quot; height=&quot;683&quot; data-origin-width=&quot;1373&quot; data-origin-height=&quot;683&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Build.cs 파일에&amp;nbsp;PublicIncludePaths,AddRange(new string[] { &quot;ChatX&quot; });를 추가해주어야 경로가 제대로 잡힌다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1369&quot; data-origin-height=&quot;817&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SzBE2/dJMcadPMIKP/0XEFcC6v8RZrwkW6PvoPJk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SzBE2/dJMcadPMIKP/0XEFcC6v8RZrwkW6PvoPJk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SzBE2/dJMcadPMIKP/0XEFcC6v8RZrwkW6PvoPJk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSzBE2%2FdJMcadPMIKP%2F0XEFcC6v8RZrwkW6PvoPJk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1369&quot; height=&quot;817&quot; data-origin-width=&quot;1369&quot; data-origin-height=&quot;817&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;PlayerController도 생성한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;이름은 CXPlayerController&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;PlayerCharacter는 필요없다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3L16o/dJMcadPMIKK/PBpNtdBxrOU1Q5hQH7CBo0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3L16o/dJMcadPMIKK/PBpNtdBxrOU1Q5hQH7CBo0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3L16o/dJMcadPMIKK/PBpNtdBxrOU1Q5hQH7CBo0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3L16o%2FdJMcadPMIKK%2FPBpNtdBxrOU1Q5hQH7CBo0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1034&quot; height=&quot;497&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;497&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;Blueprint 폴더와 그 안에 Game, Player 폴더를 만든다.&lt;/div&gt;
&lt;div&gt;보통 C++ 클래스를 상속받기 때문에 C++폴더와 유사한 구조를 가진다고 보면 된다.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;872&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpxaM1/dJMcageJWLT/FTYkkZOCYKSwDRNlkLpUQ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpxaM1/dJMcageJWLT/FTYkkZOCYKSwDRNlkLpUQ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpxaM1/dJMcageJWLT/FTYkkZOCYKSwDRNlkLpUQ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdpxaM1%2FdJMcageJWLT%2FFTYkkZOCYKSwDRNlkLpUQ1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;964&quot; height=&quot;872&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;872&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;블루프린트로 CXGameModeBase를 상속받아 새 게임모드 클래스 BP_GameModeBase를 만든다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;516&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tQph6/dJMcadPMIKJ/hqk14gGftlRtrPQFnlOQf1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tQph6/dJMcadPMIKJ/hqk14gGftlRtrPQFnlOQf1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tQph6/dJMcadPMIKJ/hqk14gGftlRtrPQFnlOQf1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtQph6%2FdJMcadPMIKJ%2Fhqk14gGftlRtrPQFnlOQf1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;872&quot; height=&quot;516&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;516&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;BP_PlayerController도 만들어준다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;511&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLxGFg/dJMcaijjM8v/lkyWEsPWcPCBpA51gSrz4k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLxGFg/dJMcaijjM8v/lkyWEsPWcPCBpA51gSrz4k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLxGFg/dJMcaijjM8v/lkyWEsPWcPCBpA51gSrz4k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLxGFg%2FdJMcaijjM8v%2FlkyWEsPWcPCBpA51gSrz4k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;553&quot; height=&quot;511&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;511&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;WorldSettings 탭에서 게임 모드 오버라이드에 BP_GameModeBase를 할당해준다&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;570&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mAUbU/dJMcah5Pp8m/SIuV2ohtqB1Jk8abVKHsUk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mAUbU/dJMcah5Pp8m/SIuV2ohtqB1Jk8abVKHsUk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mAUbU/dJMcah5Pp8m/SIuV2ohtqB1Jk8abVKHsUk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmAUbU%2FdJMcah5Pp8m%2FSIuV2ohtqB1Jk8abVKHsUk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;492&quot; height=&quot;570&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;570&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;선택된 게임모드에서는 만든 블루프린트를 할당해준다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2025&quot; data-origin-height=&quot;577&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdYbqG/dJMcadPMIKO/RkeBCpZt1ivmakckjaPQF0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdYbqG/dJMcadPMIKO/RkeBCpZt1ivmakckjaPQF0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdYbqG/dJMcadPMIKO/RkeBCpZt1ivmakckjaPQF0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdYbqG%2FdJMcadPMIKO%2FRkeBCpZt1ivmakckjaPQF0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2025&quot; height=&quot;577&quot; data-origin-width=&quot;2025&quot; data-origin-height=&quot;577&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;그러면 게임 실행 시 아웃라이너에 만든 블루프린트가생성된다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1367&quot; data-origin-height=&quot;822&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pTggF/dJMcafNITe3/0staRj500VEAq3yGAsBfAk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pTggF/dJMcafNITe3/0staRj500VEAq3yGAsBfAk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pTggF/dJMcafNITe3/0staRj500VEAq3yGAsBfAk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpTggF%2FdJMcafNITe3%2F0staRj500VEAq3yGAsBfAk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1367&quot; height=&quot;822&quot; data-origin-width=&quot;1367&quot; data-origin-height=&quot;822&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;UserWidget C++ 클래스를 만든다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;822&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UxQfi/dJMcaijjM8w/90crQsRcwovfl4IjQkF1r1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UxQfi/dJMcaijjM8w/90crQsRcwovfl4IjQkF1r1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UxQfi/dJMcaijjM8w/90crQsRcwovfl4IjQkF1r1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUxQfi%2FdJMcaijjM8w%2F90crQsRcwovfl4IjQkF1r1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1370&quot; height=&quot;822&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;822&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;UI 하위에 소스를 만든다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;458&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G1ghT/dJMcaijjM8y/1HCrnmzFDOohyuHoAYbz31/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G1ghT/dJMcaijjM8y/1HCrnmzFDOohyuHoAYbz31/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G1ghT/dJMcaijjM8y/1HCrnmzFDOohyuHoAYbz31/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG1ghT%2FdJMcaijjM8y%2F1HCrnmzFDOohyuHoAYbz31%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1608&quot; height=&quot;458&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;458&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;Build.cs에 UMG 모듈을 추가한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;UCXChatInput.h에&amp;nbsp; 멤버를 추가한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;863&quot; data-origin-height=&quot;605&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rAHyk/dJMcaijjM8u/cUOTg6MlNgXLiioPhnE2f1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rAHyk/dJMcaijjM8u/cUOTg6MlNgXLiioPhnE2f1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rAHyk/dJMcaijjM8u/cUOTg6MlNgXLiioPhnE2f1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrAHyk%2FdJMcaijjM8u%2FcUOTg6MlNgXLiioPhnE2f1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;863&quot; height=&quot;605&quot; data-origin-width=&quot;863&quot; data-origin-height=&quot;605&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;UPROPERTY(meta = (BindWidget))에서 BindWidget이 메타 키워드로 들어가면,&amp;nbsp;EditableTextBox_ChatInput이라는 이름의&amp;nbsp;UEditableTextBox를 구현하는 것을 강제한다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;527&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cezsbX/dJMcaijjM8t/OudY59zdpDDu1u8itwDxvk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cezsbX/dJMcaijjM8t/OudY59zdpDDu1u8itwDxvk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cezsbX/dJMcaijjM8t/OudY59zdpDDu1u8itwDxvk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcezsbX%2FdJMcaijjM8t%2FOudY59zdpDDu1u8itwDxvk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;997&quot; height=&quot;527&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;527&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;375&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Kvqpc/dJMcaijjM8q/6xVtoe8dFU3WBJpxTn2v6K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Kvqpc/dJMcaijjM8q/6xVtoe8dFU3WBJpxTn2v6K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Kvqpc/dJMcaijjM8q/6xVtoe8dFU3WBJpxTn2v6K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKvqpc%2FdJMcaijjM8q%2F6xVtoe8dFU3WBJpxTn2v6K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;482&quot; height=&quot;375&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;375&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;WBP_ChatInput을 만들어준다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1470&quot; data-origin-height=&quot;1192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K9uZg/dJMcah5Pp8s/6G6K99iKKQ7LAnJEwkzBGK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K9uZg/dJMcah5Pp8s/6G6K99iKKQ7LAnJEwkzBGK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K9uZg/dJMcah5Pp8s/6G6K99iKKQ7LAnJEwkzBGK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK9uZg%2FdJMcah5Pp8s%2F6G6K99iKKQ7LAnJEwkzBGK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1470&quot; height=&quot;1192&quot; data-origin-width=&quot;1470&quot; data-origin-height=&quot;1192&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;EditableTextBox_ChatInput을 만들지 않으면 에러가 뜬다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;팔레트에서 캔버스 패널을 하나 만들고, 라이브러리에서 EditableTextBox를 캔버스 패널 밑에 드래그앤드롭으로 생성한다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;893&quot; data-origin-height=&quot;836&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxoEBk/dJMcadPMIKQ/LrVwub8aDeGzyfHp4oZuOk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxoEBk/dJMcadPMIKQ/LrVwub8aDeGzyfHp4oZuOk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxoEBk/dJMcadPMIKQ/LrVwub8aDeGzyfHp4oZuOk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxoEBk%2FdJMcadPMIKQ%2FLrVwub8aDeGzyfHp4oZuOk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;893&quot; height=&quot;836&quot; data-origin-width=&quot;893&quot; data-origin-height=&quot;836&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2559&quot; data-origin-height=&quot;903&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cWABqu/dJMcadPMIKT/G5HKQeFukYKQSSRUHKKgB1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cWABqu/dJMcadPMIKT/G5HKQeFukYKQSSRUHKKgB1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cWABqu/dJMcadPMIKT/G5HKQeFukYKQSSRUHKKgB1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcWABqu%2FdJMcadPMIKT%2FG5HKQeFukYKQSSRUHKKgB1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2559&quot; height=&quot;903&quot; data-origin-width=&quot;2559&quot; data-origin-height=&quot;903&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;그리고&amp;nbsp; 이름을 바꿔주면 에러가 사라진다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;685&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/slvVA/dJMcah5Pp8o/KImk5oYPqneDFY1tC69BHK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/slvVA/dJMcah5Pp8o/KImk5oYPqneDFY1tC69BHK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/slvVA/dJMcah5Pp8o/KImk5oYPqneDFY1tC69BHK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FslvVA%2FdJMcah5Pp8o%2FKImk5oYPqneDFY1tC69BHK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;685&quot; height=&quot;602&quot; data-origin-width=&quot;685&quot; data-origin-height=&quot;602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;텍스트박스의 앵커는 하단으로 설정한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;657&quot; data-origin-height=&quot;1026&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DJBZx/dJMcadPMIKM/HWLvmYsSrkgxWSX9C1AoUk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DJBZx/dJMcadPMIKM/HWLvmYsSrkgxWSX9C1AoUk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DJBZx/dJMcadPMIKM/HWLvmYsSrkgxWSX9C1AoUk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDJBZx%2FdJMcadPMIKM%2FHWLvmYsSrkgxWSX9C1AoUk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;657&quot; height=&quot;1026&quot; data-origin-width=&quot;657&quot; data-origin-height=&quot;1026&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;오프셋은 위와 같다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;739&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xeBeI/dJMcah5Pp8l/bLN9C8KwKx7ByVu1Gs3g60/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xeBeI/dJMcah5Pp8l/bLN9C8KwKx7ByVu1Gs3g60/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xeBeI/dJMcah5Pp8l/bLN9C8KwKx7ByVu1Gs3g60/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxeBeI%2FdJMcah5Pp8l%2FbLN9C8KwKx7ByVu1Gs3g60%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;678&quot; height=&quot;739&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;739&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;폰트 크기는 24, 컬러는 검정색으로 해준다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;플레이어 컨트롤러의 헤더를 수정한다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1224&quot; data-origin-height=&quot;909&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbQvEz/dJMcadPMIKR/UAfHKHwNgKgw4i4SOVUkFK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbQvEz/dJMcadPMIKR/UAfHKHwNgKgw4i4SOVUkFK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbQvEz/dJMcadPMIKR/UAfHKHwNgKgw4i4SOVUkFK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbQvEz%2FdJMcadPMIKR%2FUAfHKHwNgKgw4i4SOVUkFK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1224&quot; height=&quot;909&quot; data-origin-width=&quot;1224&quot; data-origin-height=&quot;909&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkZyih/dJMcadPMIKN/vSOTpgBFmOqjkwnAshVHnK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkZyih/dJMcadPMIKN/vSOTpgBFmOqjkwnAshVHnK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkZyih/dJMcadPMIKN/vSOTpgBFmOqjkwnAshVHnK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkZyih%2FdJMcadPMIKN%2FvSOTpgBFmOqjkwnAshVHnK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;602&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;코드는 이렇게 쓴다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1699&quot; data-origin-height=&quot;522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b02YvK/dJMcah5Pp8q/0N3kMazEjmHOxWKhJCp5h1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b02YvK/dJMcah5Pp8q/0N3kMazEjmHOxWKhJCp5h1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b02YvK/dJMcah5Pp8q/0N3kMazEjmHOxWKhJCp5h1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb02YvK%2FdJMcah5Pp8q%2F0N3kMazEjmHOxWKhJCp5h1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1699&quot; height=&quot;522&quot; data-origin-width=&quot;1699&quot; data-origin-height=&quot;522&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;캐릭터 블루프린트에 WBP_ChatInput을 할당한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;959&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GHcjW/dJMcaijjM8o/TmmIx9BFX8ykllFMPZQ141/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GHcjW/dJMcaijjM8o/TmmIx9BFX8ykllFMPZQ141/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GHcjW/dJMcaijjM8o/TmmIx9BFX8ykllFMPZQ141/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGHcjW%2FdJMcaijjM8o%2FTmmIx9BFX8ykllFMPZQ141%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;774&quot; height=&quot;959&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;959&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;게임을 실행하면 이렇게 텍스트 입력창이 나온다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1563&quot; data-origin-height=&quot;190&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUSXR8/dJMcah5Pp8k/wiRiTEVEXcCpy86K6mbFL1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUSXR8/dJMcah5Pp8k/wiRiTEVEXcCpy86K6mbFL1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUSXR8/dJMcah5Pp8k/wiRiTEVEXcCpy86K6mbFL1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUSXR8%2FdJMcah5Pp8k%2FwiRiTEVEXcCpy86K6mbFL1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1563&quot; height=&quot;190&quot; data-origin-width=&quot;1563&quot; data-origin-height=&quot;190&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Build.cs에 Slate, SlateCore도 추가해준다.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;621&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lFtyF/dJMcah5Pp8p/KQ3sn3TxSH9X0jISk4qZNk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lFtyF/dJMcah5Pp8p/KQ3sn3TxSH9X0jISk4qZNk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lFtyF/dJMcah5Pp8p/KQ3sn3TxSH9X0jISk4qZNk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlFtyF%2FdJMcah5Pp8p%2FKQ3sn3TxSH9X0jISk4qZNk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;916&quot; height=&quot;621&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;621&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;컨트롤러 헤더에 FString타입 ChatMessageString과 Setter를 만들어준다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1149&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b17VT0/dJMcageJWLS/TJgojKlfWm54SnyFNS8pA1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b17VT0/dJMcageJWLS/TJgojKlfWm54SnyFNS8pA1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b17VT0/dJMcageJWLS/TJgojKlfWm54SnyFNS8pA1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb17VT0%2FdJMcageJWLS%2FTJgojKlfWm54SnyFNS8pA1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1149&quot; height=&quot;722&quot; data-origin-width=&quot;1149&quot; data-origin-height=&quot;722&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;ChatInput 클래스에 Native 생성자와 소멸자를 넣고 채팅 입력시 실행될 함수를 만든다. 함수에 UFUNCTION() 붙여줘야한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1943&quot; data-origin-height=&quot;1128&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EDIpL/dJMcah5Pp8t/Vq3hyGbThVH2GHNyQgW93k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EDIpL/dJMcah5Pp8t/Vq3hyGbThVH2GHNyQgW93k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EDIpL/dJMcah5Pp8t/Vq3hyGbThVH2GHNyQgW93k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEDIpL%2FdJMcah5Pp8t%2FVq3hyGbThVH2GHNyQgW93k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1943&quot; height=&quot;1128&quot; data-origin-width=&quot;1943&quot; data-origin-height=&quot;1128&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;델리게이트 바인딩 및 텍스트 commit시 동작을 구현한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;665&quot; data-origin-height=&quot;1327&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dBDSUP/dJMcah5Pp8r/baGN4JmOf2mA5afUFAUez1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dBDSUP/dJMcah5Pp8r/baGN4JmOf2mA5afUFAUez1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dBDSUP/dJMcah5Pp8r/baGN4JmOf2mA5afUFAUez1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdBDSUP%2FdJMcah5Pp8r%2FbaGN4JmOf2mA5afUFAUez1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;665&quot; height=&quot;1327&quot; data-origin-width=&quot;665&quot; data-origin-height=&quot;1327&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;EditableTextBox에는 텍스트 커밋 시 이벤트가 발생하는데 이것을 델리게이트로&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;if (EditableTextBox_ChatInput-&amp;gt;OnTextCommitted.IsAlreadyBound(this, &amp;amp;ThisClass::OnChatInputTextCommitted) == false)&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;EditableTextBox_ChatInput-&amp;gt;OnTextCommitted.AddDynamic(this, &amp;amp;ThisClass::OnChatInputTextCommitted);&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;이렇게 바인딩해서 사용할 수가 있다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;347&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TurLs/dJMcaijjM8m/yJX5zhJOCQXNYIsA65G6Z1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TurLs/dJMcaijjM8m/yJX5zhJOCQXNYIsA65G6Z1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TurLs/dJMcaijjM8m/yJX5zhJOCQXNYIsA65G6Z1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTurLs%2FdJMcaijjM8m%2FyJX5zhJOCQXNYIsA65G6Z1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;932&quot; height=&quot;347&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;347&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;이 상태로 실행하면 입력 후 엔터를 누를 시 텍스트가 사라지며 String에 저장된다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;바인딩이 잘 되었는지 확인하려면 아래와 같이 진행한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;#include &quot;Kismet/KismetSystemLibrary.h&quot;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1174&quot; data-origin-height=&quot;176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmagDu/dJMcafNITe2/AznoX5Kc9UXXh6TQhNzn6K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmagDu/dJMcafNITe2/AznoX5Kc9UXXh6TQhNzn6K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmagDu/dJMcafNITe2/AznoX5Kc9UXXh6TQhNzn6K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmagDu%2FdJMcafNITe2%2FAznoX5Kc9UXXh6TQhNzn6K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1174&quot; height=&quot;176&quot; data-origin-width=&quot;1174&quot; data-origin-height=&quot;176&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;UKismetSystemLibrary::PrintString(this, ChatMessageString, true, true, FLinearColor::Red, 5.0f);으로&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;SetChatMessageString 실행 시&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;화면에 출력해본다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LoFi2/dJMcaijjM8s/XVh8vjFzJriV7zubaPuIT0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LoFi2/dJMcaijjM8s/XVh8vjFzJriV7zubaPuIT0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LoFi2/dJMcaijjM8s/XVh8vjFzJriV7zubaPuIT0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLoFi2%2FdJMcaijjM8s%2FXVh8vjFzJriV7zubaPuIT0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1034&quot; height=&quot;186&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;841&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Robj9/dJMcaijjM8n/QCTKi59gg7fXkEZgkeP5t1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Robj9/dJMcaijjM8n/QCTKi59gg7fXkEZgkeP5t1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Robj9/dJMcaijjM8n/QCTKi59gg7fXkEZgkeP5t1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRobj9%2FdJMcaijjM8n%2FQCTKi59gg7fXkEZgkeP5t1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1100&quot; height=&quot;841&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;841&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;SetString이 되면 화면에 입력한 내용이 출력된다.&lt;/div&gt;</description>
      <category>게임 개발/학습 일지</category>
      <author>이개</author>
      <guid isPermaLink="true">https://igae-dev.tistory.com/170</guid>
      <comments>https://igae-dev.tistory.com/170#entry170comment</comments>
      <pubDate>Tue, 9 Jun 2026 22:31:09 +0900</pubDate>
    </item>
    <item>
      <title>언리얼 내배캠 마스터반 - 소프트 레퍼런스</title>
      <link>https://igae-dev.tistory.com/169</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;C++ 액터를 하나 만든다. 이름은 TestActor&lt;/p&gt;
&lt;div&gt;소프트 오브젝트 레퍼런스&lt;/div&gt;
&lt;div&gt;소프트 클래스 레퍼런스&lt;/div&gt;
&lt;div&gt;비동기, 동기, 데이터 에셋&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;UPROPERTY(EditAnywhere)&lt;/div&gt;
&lt;div&gt;ConstructorHelper: ...(하드코딩으로 경로, 위치 넣어줌. 찾으면 반환, 없으면 nullptr)&lt;/div&gt;
&lt;div&gt;간접 프로퍼티&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주소만 들고 있다가 로드 시점을 정해주는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;블루프린트에서 변수를 생성하면 오브젝트 레퍼런스, 클래스 레퍼런스, 소프트 오브젝트 레퍼런스, 소프트 클래스 오브젝트 레퍼런스가 있다. 소프트 오브젝트 레퍼런스가 뭘까?&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;일반 레퍼런스는 하드 레퍼런스다. 항상 같이 로드된다.&lt;/div&gt;
&lt;div&gt;소프트 오브젝트 레퍼런스는 필요할 때만 로드된다.&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예를 들면 특정 스테이지에서만 나타나는 몬스터, 고해상도 텍스쳐 등이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;210&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hjxr6/dJMcadvq97e/TIzHlvUtdZWRr1xK2Fzqu0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hjxr6/dJMcadvq97e/TIzHlvUtdZWRr1xK2Fzqu0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hjxr6/dJMcadvq97e/TIzHlvUtdZWRr1xK2Fzqu0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHjxr6%2FdJMcadvq97e%2FTIzHlvUtdZWRr1xK2Fzqu0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;656&quot; height=&quot;210&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;210&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;소프트 오브젝트 만들기&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1373&quot; data-origin-height=&quot;464&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6Ck35/dJMcadvq97f/xzGAF2Eh9JZstgoE9UQxCK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6Ck35/dJMcadvq97f/xzGAF2Eh9JZstgoE9UQxCK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6Ck35/dJMcadvq97f/xzGAF2Eh9JZstgoE9UQxCK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6Ck35%2FdJMcadvq97f%2FxzGAF2Eh9JZstgoE9UQxCK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1373&quot; height=&quot;464&quot; data-origin-width=&quot;1373&quot; data-origin-height=&quot;464&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oCRrI/dJMcacKcc07/UKj0jLy5fDqLJeDZ8Dsmik/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oCRrI/dJMcacKcc07/UKj0jLy5fDqLJeDZ8Dsmik/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oCRrI/dJMcacKcc07/UKj0jLy5fDqLJeDZ8Dsmik/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoCRrI%2FdJMcacKcc07%2FUKj0jLy5fDqLJeDZ8Dsmik%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;773&quot; height=&quot;340&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;340&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;동기 로드 함수&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1336&quot; data-origin-height=&quot;944&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CUbBD/dJMcadvq97g/EDeBwKt1pcOds4memhT271/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CUbBD/dJMcadvq97g/EDeBwKt1pcOds4memhT271/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CUbBD/dJMcadvq97g/EDeBwKt1pcOds4memhT271/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCUbBD%2FdJMcadvq97g%2FEDeBwKt1pcOds4memhT271%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1336&quot; height=&quot;944&quot; data-origin-width=&quot;1336&quot; data-origin-height=&quot;944&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;이 상태로 빌드&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;보통 메인 스레드에서 동기로 로드를 하는데, 리소스를 많이 먹는 오브젝트는 서브스레드에서 로드를 하는 것이 비동기.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1693&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEkPUu/dJMcadvq97i/vIAiQknPXzHjA1N8BjeKAK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEkPUu/dJMcadvq97i/vIAiQknPXzHjA1N8BjeKAK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEkPUu/dJMcadvq97i/vIAiQknPXzHjA1N8BjeKAK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEkPUu%2FdJMcadvq97i%2FvIAiQknPXzHjA1N8BjeKAK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1693&quot; height=&quot;796&quot; data-origin-width=&quot;1693&quot; data-origin-height=&quot;796&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;액터를 화면에 올리고 메시에 아직 아무데서도 사용되지 않은 메시를 할당한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;603&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Cyrix/dJMcaip3zzz/GzuEHFpzec2Yjy6PJ7EeCK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Cyrix/dJMcaip3zzz/GzuEHFpzec2Yjy6PJ7EeCK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Cyrix/dJMcaip3zzz/GzuEHFpzec2Yjy6PJ7EeCK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCyrix%2FdJMcaip3zzz%2FGzuEHFpzec2Yjy6PJ7EeCK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1046&quot; height=&quot;603&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;603&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;처음 실행 시&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;458&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EywN4/dJMcacKcc08/nqQNDu5J7Ke7Qkcr5kyWMK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EywN4/dJMcacKcc08/nqQNDu5J7Ke7Qkcr5kyWMK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EywN4/dJMcacKcc08/nqQNDu5J7Ke7Qkcr5kyWMK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEywN4%2FdJMcacKcc08%2FnqQNDu5J7Ke7Qkcr5kyWMK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1029&quot; height=&quot;458&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;458&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;두 번째 실행 시&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;엔진 실행 자체가 게임 실행이나 다름없기 때문에 엔진 자체를 끄지 않고 두 번째 실행하면 이미 오브젝트가 로드가 되어있는 것이다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;비동기 호출&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AfU63/dJMcacKcc05/shWTT1sfrJyZb8QEUsUpo0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AfU63/dJMcacKcc05/shWTT1sfrJyZb8QEUsUpo0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AfU63/dJMcacKcc05/shWTT1sfrJyZb8QEUsUpo0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAfU63%2FdJMcacKcc05%2FshWTT1sfrJyZb8QEUsUpo0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1510&quot; height=&quot;438&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;새로운 함수&amp;nbsp;MyOnLoadCompleted 선언&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;아래 헤더를 인클루드해주어야한다.&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;#include &quot;Engine/AssetManager.h&quot;&lt;/li&gt;
&lt;li&gt;#include &quot;Engine/StreamableManager.h&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIds7A/dJMcacKcc06/7QxexuKPxKc4vvmf7NbXz0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIds7A/dJMcacKcc06/7QxexuKPxKc4vvmf7NbXz0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIds7A/dJMcacKcc06/7QxexuKPxKc4vvmf7NbXz0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIds7A%2FdJMcacKcc06%2F7QxexuKPxKc4vvmf7NbXz0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1390&quot; height=&quot;380&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1355&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbt1RK/dJMcadvq97h/3XPd7XOAB4nhPfnkBUXG91/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbt1RK/dJMcadvq97h/3XPd7XOAB4nhPfnkBUXG91/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbt1RK/dJMcadvq97h/3XPd7XOAB4nhPfnkBUXG91/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbbt1RK%2FdJMcadvq97h%2F3XPd7XOAB4nhPfnkBUXG91%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1355&quot; height=&quot;532&quot; data-origin-width=&quot;1355&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;LoadWithSoftPtr()의 이미 로드된 부분 밑에 추가해준다.&amp;nbsp;RequestAsyncLoad가 비동기로 가져와서 바인딩 해주는 부분이다. ToSoftObejctPath는 경로를 가져와주는 것이다.&lt;/div&gt;</description>
      <category>게임 개발/학습 일지</category>
      <author>이개</author>
      <guid isPermaLink="true">https://igae-dev.tistory.com/169</guid>
      <comments>https://igae-dev.tistory.com/169#entry169comment</comments>
      <pubDate>Mon, 8 Jun 2026 09:56:53 +0900</pubDate>
    </item>
  </channel>
</rss>