<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Unity Archives - 어제와 내일의 나 그 사이의 이야기</title>
	<atom:link href="https://lycos7560.com/tag/unity/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>생각의 흐름을 타고 다니며 만드는 블로그</description>
	<lastBuildDate>Tue, 10 Feb 2026 21:02:50 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://lycos7560.com/wp-content/uploads/2022/11/cropped-cropped-cropped-log-1-150x150-1-80x80.png</url>
	<title>Unity Archives - 어제와 내일의 나 그 사이의 이야기</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Unity Package Manager &#8220;Invalid Signature&#8221;</title>
		<link>https://lycos7560.com/unity/unity-package-manager-invalid-signature/40434/</link>
					<comments>https://lycos7560.com/unity/unity-package-manager-invalid-signature/40434/#respond</comments>
		
		<dc:creator><![CDATA[lycos7560]]></dc:creator>
		<pubDate>Tue, 10 Feb 2026 21:02:46 +0000</pubDate>
				<category><![CDATA[Unity]]></category>
		<category><![CDATA[개인 공부 저장용]]></category>
		<category><![CDATA[기타]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[Invalid Signature]]></category>
		<category><![CDATA[Manager]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[Package Manager]]></category>
		<category><![CDATA[study]]></category>
		<category><![CDATA[공부]]></category>
		<category><![CDATA[기초]]></category>
		<category><![CDATA[버그]]></category>
		<category><![CDATA[유나티]]></category>
		<guid isPermaLink="false">https://lycos7560.com/?p=40434</guid>

					<description><![CDATA[<p>문제 상황 Unity 에디터의 Package Manager에서 Services Core 패키지가 빨간색 경고와 함께 &#8220;Invalid Signature&#8221; 표시 광고 초기화 실패(Gateway communication failure) 등의 문제가 발생 이는 패키지 자체의 손상이 아니라 Package Manager의 서명 검증 시스템 오류 오류의 의미와 영향 Package Manager의 서명 검증 실패 Unity Package Manager는 모든 패키지의 디지털 서명을 확인하는 검증 메커니즘을 가지고 있 &#8220;Invalid [&#8230;]</p>
<p>The post <a href="https://lycos7560.com/unity/unity-package-manager-invalid-signature/40434/">Unity Package Manager &#8220;Invalid Signature&#8221;</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></description>
										<content:encoded><![CDATA[				<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-31667817      "
					data-scroll= "1"
					data-offset= "30"
					style=""
				>
				<div class="uagb-toc__wrap">
						<div class="uagb-toc__title">
							목차						</div>
																						<div class="uagb-toc__list-wrap ">
						<ol class="uagb-toc__list"><li class="uagb-toc__list"><a href="#문제-상황" class="uagb-toc-link__trigger">문제 상황</a><li class="uagb-toc__list"><a href="#오류의-의미와-영향" class="uagb-toc-link__trigger">오류의 의미와 영향</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#package-manager의-서명-검증-실패" class="uagb-toc-link__trigger">Package Manager의 서명 검증 실패</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#unity-ads-초기화-실패와의-연결" class="uagb-toc-link__trigger">Unity Ads 초기화 실패와의 연결</a></li></ul></li><li class="uagb-toc__list"><a href="#해결-방법-개인적인" class="uagb-toc-link__trigger">해결 방법 (개인적인)</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#package-manager-캐시-삭제" class="uagb-toc-link__trigger">Package Manager 캐시 삭제</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#reset-packages-to-defaults-마지막-수단" class="uagb-toc-link__trigger">Reset Packages to Defaults (마지막 수단)</a></ul></ul></ol>					</div>
									</div>
				</div>
			


<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">문제 상황</h2>



<p>Unity 에디터의 Package Manager에서 <strong>Services Core 패키지가 빨간색 경고와 함께 &#8220;Invalid Signature&#8221;</strong> 표시</p>



<p>광고 초기화 실패(<code>Gateway communication failure</code>) 등의 문제가 발생</p>



<p>이는 패키지 자체의 손상이 아니라 <strong>Package Manager의 서명 검증 시스템 오류</strong></p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="828" height="320" src="https://lycos7560.com/wp-content/uploads/2026/02/image.png" alt="" class="wp-image-40435" srcset="https://lycos7560.com/wp-content/uploads/2026/02/image.png 828w, https://lycos7560.com/wp-content/uploads/2026/02/image-300x116.png 300w, https://lycos7560.com/wp-content/uploads/2026/02/image-768x297.png 768w" sizes="(max-width: 828px) 100vw, 828px" /></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">오류의 의미와 영향</h2>



<h3 class="wp-block-heading">Package Manager의 서명 검증 실패</h3>



<p>Unity Package Manager는 모든 패키지의 디지털 서명을 확인하는 검증 메커니즘을 가지고 있</p>



<p>&#8220;Invalid Signature&#8221;는 <strong>Package Manager의 서명 검증 로직이 정상적인 패키지를 잘못 거부하는 버그</strong></p>



<p>실제 패키지는 정상이지만, Package Manager가 잘못된 판단을 내리고 있는 상태로 생각됨</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Unity Ads 초기화 실패와의 연결</h3>



<p>Services Core는 단순한 라이브러리가 아니라 <strong>Unity Ads를 포함한 모든 유니티 서비스의 핵심 패키지</strong>입니다. </p>



<p>이 패키지가 손상되면:</p>



<ul class="wp-block-list">
<li>Unity Ads 초기화 실패 <code>Gateway communication failure</code> 오류 발생 광고 로드 및 표시 불가 기타 Unity Services(Analytics, Crash Reporting 등) 동작 불능</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">해결 방법 (개인적인)</h2>



<h3 class="wp-block-heading">Package Manager 캐시 삭제 </h3>



<p>로컬에 저장된 손상된 패키지 캐시를 강제로 삭제</p>



<p><strong>Unity 에디터를 완전히 종료</strong>합니다 다음 폴더로 이동:</p>



<ul class="wp-block-list">
<li><strong>Windows</strong>: <code>%AppData%/Local/Unity/cache/upm</code></li>



<li><strong>Mac</strong>: <code>~/Library/Caches/Unity/upm</code></li>



<li><strong>Linux</strong>: <code>~/.cache/unity/upm</code></li>
</ul>



<p><code>upm</code> 폴더 전체를 삭제합니다 </p>



<p>Unity 에디터를 다시 열면 Package Manager가 서버에서 패키지를 새로 다운로드하고 서명을 다시 검증</p>



<p><strong>주의</strong>: 이 작업은 안전하며, 폴더를 다시 열면 필요한 캐시가 자동으로 재생성됩니다.</p>



<h3 class="wp-block-heading">Reset Packages to Defaults (마지막 수단)</h3>



<p>프로젝트의 패키지 설정이 꼬인 경우 초기화가 필요합니다.</p>



<p>Unity 상단 메뉴: Help &gt; Reset Packages to defaults 선택</p>



<p>확인 대화상자에서 &#8220;Yes&#8221; 클릭</p>



<p>프로젝트의 manifest.json이 기본값으로 되돌려집니다</p>



<p>주의: 이 작업은 프로젝트의 패키지 설정을 초기화하므로:</p>



<p>수동으로 추가했던 다른 패키지가 있다면 다시 설치해야 합니다</p>



<p>Packages/manifest.json 파일이 변경됩니다</p>



<p></p>
<p>The post <a href="https://lycos7560.com/unity/unity-package-manager-invalid-signature/40434/">Unity Package Manager &#8220;Invalid Signature&#8221;</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://lycos7560.com/unity/unity-package-manager-invalid-signature/40434/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Unity Netcode for Entities – Connecting server and clients</title>
		<link>https://lycos7560.com/c/unity-netcode-for-entities-creating-multiplayer-gameplay/39997/</link>
					<comments>https://lycos7560.com/c/unity-netcode-for-entities-creating-multiplayer-gameplay/39997/#respond</comments>
		
		<dc:creator><![CDATA[lycos7560]]></dc:creator>
		<pubDate>Thu, 01 May 2025 06:21:00 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[client]]></category>
		<category><![CDATA[Client / Server worlds]]></category>
		<category><![CDATA[dtls]]></category>
		<category><![CDATA[IP]]></category>
		<category><![CDATA[multiplayer]]></category>
		<category><![CDATA[Netcode]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[study]]></category>
		<category><![CDATA[TCP]]></category>
		<category><![CDATA[UDP]]></category>
		<category><![CDATA[WSS]]></category>
		<category><![CDATA[공부]]></category>
		<category><![CDATA[기초]]></category>
		<category><![CDATA[유니티]]></category>
		<guid isPermaLink="false">https://lycos7560.com/?p=39997</guid>

					<description><![CDATA[<p>🔥 Connecting server and clients Netcode for Entities 1.5.0v https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/creating-multiplayer-gameplay.html 주제 설명 서버와 클라이언트 연결Connecting server and clients Netcode for Entities는 Unity Transport 패키지를 사용하여 연결을 관리합니다. 각 연결은 하나의 엔티티로 저장되며, 해당 엔티티는 NetworkStreamConnection 컴포넌트를 포함하고 있어, 연결에 사용되는 Transport 핸들을 참조합니다. 이 엔티티의 이름은 일반적으로 'NetworkConnection [nid]' 형식입니다. 상태 및 입력 동기화Synchronizing states [&#8230;]</p>
<p>The post <a href="https://lycos7560.com/c/unity-netcode-for-entities-creating-multiplayer-gameplay/39997/">Unity Netcode for Entities – Connecting server and clients</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></description>
										<content:encoded><![CDATA[				<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-cbe7176c      "
					data-scroll= "1"
					data-offset= "30"
					style=""
				>
				<div class="uagb-toc__wrap">
						<div class="uagb-toc__title">
							목차						</div>
																						<div class="uagb-toc__list-wrap ">
						<ol class="uagb-toc__list"><li class="uagb-toc__list"><a href="#connecting-server-and-clients" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Connecting server and clients</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#서버와-클라이언트-연결" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 서버와 클라이언트 연결</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#명령-수신-대상-설정" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270f.png" alt="✏" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 명령 수신 대상 설정</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#게임-상태-진입" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270f.png" alt="✏" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 게임 상태 진입</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#연결-해제-요청" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270f.png" alt="✏" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 연결 해제 요청</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#수신-버퍼-incoming-buffers" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 수신 버퍼 (Incoming Buffers)</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#송신-버퍼-outgoing-buffers" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 송신 버퍼 (Outgoing Buffers)</a></li></ul><li class="uagb-toc__list"><a href="#연결-흐름-connection-flow" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 연결 흐름 (Connection flow)</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-수동-연결-리스닝-manually-listen-or-connect" class="uagb-toc-link__trigger">1&#x20e3; 수동 연결 / 리스닝 (Manually listen or connect )</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#2-autoconnectport-사용-using-theautoconnectport" class="uagb-toc-link__trigger">2&#x20e3; AutoConnectPort 사용 (Using the AutoConnectPort)</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#3-networkstreamrequest로-연결-흐름-제어" class="uagb-toc-link__trigger">3&#x20e3; NetworkStreamRequest로 연결 흐름 제어</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#4-network-simulator" class="uagb-toc-link__trigger">4&#x20e3; Network simulator</a></li></ul><li class="uagb-toc__list"><a href="#클라이언트-연결-이벤트-수신" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 클라이언트 연결 이벤트 수신</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-netcodeconnectionevents-on-the-client" class="uagb-toc-link__trigger">1&#x20e3; NetCodeConnectionEvents on the client</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#2-netcodeconnectionevents-on-the-server" class="uagb-toc-link__trigger">2&#x20e3; NetCodeConnectionEvents on the server</a></li></ul><li class="uagb-toc__list"><a href="#connection-approval" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Connection approval</a></li></ul></li><li class="uagb-toc__list"><a href="#연결-확인-sample-코드" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 연결 확인 Sample 코드</a></ul></ol>					</div>
									</div>
				</div>
			


<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Connecting server and clients</h2>



<p><strong>Netcode for Entities 1.5.0v</strong></p>



<p><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/creating-multiplayer-gameplay.html" target="_blank" rel="noreferrer noopener">https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/creating-multiplayer-gameplay.html</a></p>



<figure class="wp-block-table"><table><thead><tr><th>주제</th><th>설명</th></tr></thead><tbody><tr><td><strong>서버와 클라이언트 연결</strong><br><strong><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/network-connection.html" target="_blank" rel="noreferrer noopener">Connecting server and clients</a></strong></td><td>Netcode for Entities는 Unity Transport 패키지를 사용하여 연결을 관리합니다. <br>각 연결은 하나의 엔티티로 저장되며, 해당 엔티티는 <code><strong>NetworkStreamConnection</strong></code> 컴포넌트를 포함하고 있어, 연결에 사용되는 Transport 핸들을 참조합니다. <br>이 엔티티의 이름은 일반적으로 <code><strong>'NetworkConnection [nid]'</strong></code> 형식입니다.</td></tr><tr><td><strong>상태 및 입력 동기화</strong><br><strong><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/synchronization.html" target="_blank" rel="noreferrer noopener">Synchronizing states and inputs</a></strong></td><td>Netcode는 고스트(ghost) 상태와 입력/명령을 동기화합니다. <br>이 항목에서는 지원되는 타입 목록과, 어떤 필드와 컴포넌트를 <strong>eventual consistency 모델</strong>을 통해 복제할지 표시하는 방법(마크업)을 설명합니다.</td></tr><tr><td><strong>시간 동기화</strong><br><strong><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/time-synchronization.html" target="_blank" rel="noreferrer noopener">Time synchronization</a></strong></td><td>Netcode는 <strong>서버 권한 모델(server authoritative model)</strong> 을 사용합니다. <br>서버는 고정된 시간 간격으로 시뮬레이션을 실행하며, 이 간격은 마지막 업데이트 이후 경과한 시간에 따라 결정됩니다. <br>따라서 <strong>클라이언트는 항상 서버 시간과 동기화되어야 이 모델이 제대로 작동</strong>합니다.</td></tr><tr><td><strong>보간 및 예측보간</strong><br><strong><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/interpolation.html" target="_blank" rel="noreferrer noopener">Interpolation and extrapolation</a></strong></td><td>게임에서 <strong>보간(interpolation)</strong> 및 <strong>예측보간(extrapolation)</strong> 을 사용하여, 불안정한 네트워크 환경에서도 부드러운 게임플레이 경험을 제공할 수 있습니다.</td></tr><tr><td><strong>예측</strong><br><strong><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/prediction.html" target="_blank" rel="noreferrer noopener">Prediction</a></strong></td><td>게임의 지연(latency)을 보완하기 위해 <strong>예측 로직</strong>을 사용할 수 있습니다. <br>예측은 클라이언트가 로컬에서 먼저 행동을 시뮬레이션하고, 이후 서버로부터 확정된 결과를 받는 방식입니다.</td></tr><tr><td><strong>물리</strong><br><strong><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/physics.html" target="_blank" rel="noreferrer noopener">Physics</a></strong></td><td><strong>Netcode 패키지는 Unity Physics와의 일부 통합 기능을 제공</strong>합니다. <br>이를 통해 네트워크 환경에서도 물리 기반 오브젝트를 보다 쉽게 사용할 수 있습니다. <br>이 통합 기능은 <strong>predicted ghosts</strong>와 <strong>interpolated ghosts</strong> 양쪽 모두에 대한 물리 처리를 지원합니다.</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 서버와 클라이언트 연결</h3>



<p><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/network-connection.html" target="_blank" rel="noreferrer noopener">https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/network-connection.html</a></p>



<p><strong>Netcode for Entities</strong>는 연결을 관리하기 위해 <strong>Unity Transport 패키지</strong>를 사용하며, 각 연결을 하나의 <strong>엔티티</strong>로 저장합니다.</p>



<p>이 엔티티는 <code>NetworkStreamConnection</code> 컴포넌트를 가지며, 연결에 사용된 <strong>Transport 핸들</strong>을 포함합니다. </p>



<p>연결이 종료되면(서버가 유저 연결을 끊거나 클라이언트가 요청한 경우) 이 엔티티는 삭제됩니다.</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270f.png" alt="✏" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 명령 수신 대상 설정</h4>



<p><code>[AutoCommandTarget feature]</code>를 사용하지 않거나 더 세밀한 제어가 필요한 경우, <strong>CommandTarget</strong>을 설정해야 합니다. </p>



<p>이 설정은 클라이언트에서 받은 명령을 저장할 엔티티를 지정합니다. </p>



<p>이 엔티티 참조를 최신 상태로 유지하는 것은 게임 개발자의 책임입니다.</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270f.png" alt="✏" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 게임 상태 진입</h4>



<p>게임은 <code>NetworkStreamInGame</code> 컴포넌트를 연결 엔티티에 수동으로 추가해야 합니다. 이 작업은 자동으로 이루어지지 않습니다. </p>



<p>이 컴포넌트가 추가되기 전에는 클라이언트가 명령을 전송하지 않으며, 서버도 스냅샷을 전송하지 않습니다.</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270f.png" alt="✏" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 연결 해제 요청</h4>



<p>연결을 해제하려면 해당 엔티티에 <code>NetworkStreamRequestDisconnect</code> 컴포넌트를 추가하세요. </p>



<p>Transport 드라이버를 통한 <strong>직접적인 연결 해제는 지원되지 않습니다.</strong></p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 수신 버퍼 (Incoming Buffers)</h4>



<p>각 연결은 최대 3개의 수신 버퍼를 가질 수 있습니다:</p>



<ul class="wp-block-list">
<li>명령: <code><strong><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.IncomingRpcDataStreamBuffer.html" target="_blank" rel="noreferrer noopener">IncomingRpcDataStreamBuffer</a></strong></code></li>



<li>RPC: <code><strong><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.IncomingCommandDataStreamBuffer.html" target="_blank" rel="noreferrer noopener">IncomingCommandDataStreamBuffer</a></strong></code></li>



<li>스냅샷 (클라이언트 전용): <code><strong><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.IncomingSnapshotDataStreamBuffer.html" target="_blank" rel="noreferrer noopener">IncomingSnapshotDataStreamBuffer</a></strong></code></li>
</ul>



<p>서버에서 클라이언트로 스냅샷이 전송되면 버퍼에 저장되고 나중에 <code><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.IncomingSnapshotDataStreamBuffer.html" target="_blank" rel="noreferrer noopener"><strong>GhostReceiveSystem</strong></a></code>에 의해 처리됩니다.</p>



<p>RPC 및 명령도 동일한 방식으로 <code><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.NetworkStreamReceiveSystem.html"><strong>NetworkStreamReceiveSystem</strong></a></code>이 수집하고, 이후 각각의 시스템이 처리합니다.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 서버는 <code>IncomingSnapshotDataStreamBuffer</code>를 가지지 않습니다.</p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 송신 버퍼 (Outgoing Buffers)</h4>



<p>각 연결은 최대 2개의 송신 버퍼를 가질 수 있습니다:</p>



<ul class="wp-block-list">
<li>명령 (클라이언트 전용): <code><strong><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.OutgoingRpcDataStreamBuffer.html" target="_blank" rel="noreferrer noopener">OutgoingRpcDataStreamBuffer</a></strong></code></li>



<li>RPC:<strong> <code>OutgoingRpcDataStreamBuffer</code></strong></li>
</ul>



<p>생성된 명령은 먼저 송신 버퍼에 저장되고, 클라이언트가 매 틱마다 이 버퍼를 전송합니다. </p>



<p>RPC도 마찬가지로 해당 송신 시스템이 버퍼에 인코딩하고, <code>RpcSystem</code>이 이를 묶어 MTU 단위로 전송합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 연결 흐름 (Connection flow)</h3>



<p>Netcode는 게임 시작 시 <strong>자동으로 서버 또는 클라이언트 연결을 설정하지 않습니다</strong>. </p>



<p>기본적으로 <code>ClientServerBootstrap</code>는 클라이언트와 서버 월드만 생성합니다. </p>



<p>연결 채널을 여는 방식은 개발자가 결정합니다.</p>



<p><strong>선택 가능한 방법:</strong></p>



<ul class="wp-block-list">
<li>1&#x20e3; <code><strong>NetworkStreamDriver</strong></code>를 사용하여 직접 <strong><code>Connect</code> </strong>또는 <strong><code>Listen</code> </strong>호출</li>



<li>2&#x20e3; <strong><code>AutoConnectPort</code> </strong>및 <strong><code>DefaultConnectAddress</code> </strong>설정</li>



<li><strong><code>NetworkStreamRequestConnect</code> </strong>및 <strong><code>NetworkStreamRequestListen</code> </strong>요청 엔티티 생성</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 주의 </p>



<p>연결 중에는 반드시 <code>Application.runInBackground = true</code>로 설정해야 하며, 그렇지 않으면 <strong>포커스를 잃었을 때 연결이 끊길 수 있습니다.</strong></p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">1&#x20e3; 수동 연결 / 리스닝 (Manually listen or connect )</h4>



<p><code><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.NetworkStreamDriver.html" target="_blank" rel="noreferrer noopener">NetworkStreamDriver</a></code> 싱글톤을 사용해 <code>Connect</code> 또는 <code>Listen</code> 메서드를 호출합니다. </p>



<p>코드 예시는 <a href="https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/NetcodeSamples/Assets/Samples/HelloNetcode/1_Basics/01_BootstrapAndFrontend/Frontend/Frontend.cs#L80" target="_blank" rel="noreferrer noopener">DOTS samples repository</a> 참고</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">        public void StartClientServer(string sceneName)
        {
            Debug.Log($"[StartClientServer] Called with '{sceneName}'.");
            if (ClientServerBootstrap.RequestedPlayType != ClientServerBootstrap.PlayType.ClientAndServer)
            {
                Debug.LogError($"Creating client/server worlds is not allowed if playmode is set to {ClientServerBootstrap.RequestedPlayType}");
                return;
            }

            var server = ClientServerBootstrap.CreateServerWorld("ServerWorld");
            var client = ClientServerBootstrap.CreateClientWorld("ClientWorld");

            SceneManager.LoadScene("FrontendHUD");

            //Destroy the local simulation world to avoid the game scene to be loaded into it
            //This prevent rendering (rendering from multiple world with presentation is not greatly supported)
            //and other issues.
            DestroyLocalSimulationWorld();
            if (World.DefaultGameObjectInjectionWorld == null)
                World.DefaultGameObjectInjectionWorld = server;
            SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);

            var port = ParsePortOrDefault(Port.text);

            NetworkEndpoint ep = NetworkEndpoint.AnyIpv4.WithPort(port);
            {
                using var drvQuery = server.EntityManager.CreateEntityQuery(ComponentType.ReadWrite&lt;NetworkStreamDriver>());
                drvQuery.GetSingletonRW&lt;NetworkStreamDriver>().ValueRW.RequireConnectionApproval = sceneName.Contains("ConnectionApproval", StringComparison.OrdinalIgnoreCase);
                drvQuery.GetSingletonRW&lt;NetworkStreamDriver>().ValueRW.Listen(ep);
            }

            ep = NetworkEndpoint.LoopbackIpv4.WithPort(port);
            {
                using var drvQuery = client.EntityManager.CreateEntityQuery(ComponentType.ReadWrite&lt;NetworkStreamDriver>());
                drvQuery.GetSingletonRW&lt;NetworkStreamDriver>().ValueRW.Connect(client.EntityManager, ep);
            }
        }</pre>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">2&#x20e3; <strong>AutoConnectPort 사용 (Using the&nbsp;AutoConnectPort)</strong></h4>



<p><code>ClientServerBootstrap</code>  <a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ClientServerBootstrap.html#Unity_NetCode_ClientServerBootstrap_AutoConnectPort" target="_blank" rel="noreferrer noopener"><code>AutoConnectPort</code></a>필드에는 서버와 클라이언트가 처음 설정될 때 각각 자동으로 수신하고 연결하도록 지시하는 데 사용할 수 있는 두 가지 특수 속성이 포함되어 있습니다.</p>



<ul class="wp-block-list">
<li><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ClientServerBootstrap.html#Unity_NetCode_ClientServerBootstrap_DefaultConnectAddress" target="_blank" rel="noreferrer noopener">DefaultConnectAddress</a></li>



<li><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ClientServerBootstrap.html#Unity_NetCode_ClientServerBootstrap_DefaultListenAddress" target="_blank" rel="noreferrer noopener">DefaultListenAddress</a></li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">public class AutoConnectBootstrap : ClientServerBootstrap
{
    public override bool Initialize(string defaultWorldName)
    {
        AutoConnectPort = 7979;
        CreateDefaultClientServerWorlds();
        return true;
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>서버는 와일드카드 주소(<code>DefaultListenAddress:AutoConnectPort</code>)에서 리슨을 시작합니다. </p>



<p><code>DefaultConnectAddress</code>는 기본적으로 <code>NetworkEndpoint.AnyIpv4</code>로 설정되어 있습니다. </p>



<p>클라이언트는 서버 주소(<code>DefaultConnectAddress:AutoConnectPort</code>)로 연결을 시작하며, 이 <code>DefaultConnectAddress</code>는 기본적으로 <code>NetworkEndpoint.Loopback</code>으로 설정되어 있습니다.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>참고:</strong></p>



<p>에디터에서는 <strong>PlayMode 도구</strong>를 사용해 <code>AutoConnectAddress</code>와 <code>AutoConnectPort</code> 값을 오버라이드할 수 있습니다. </p>



<p>그러나 <strong><code>AutoConnectPort</code>를 0으로 설정한 경우</strong>에는 PlayMode 도구의 오버라이드 기능이 작동하지 않으며, 이 경우 <strong>수동으로 연결을 트리거해야 합니다.</strong></p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">3&#x20e3; <strong>NetworkStreamRequest로 연결 흐름 제어</strong></h4>



<p><code><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.NetworkStreamDriver.html" target="_blank" rel="noreferrer noopener">NetworkStreamDriver</a></code>에서 직접 메서드를 호출하는 대신, 다음과 같은 싱글톤을 생성하여 연결 흐름을 제어할 수 있습니다:</p>



<ul class="wp-block-list">
<li><strong><code><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.NetworkStreamRequestConnect.html" target="_blank" rel="noreferrer noopener">NetworkStreamRequestConnect</a></code> singleton&nbsp;</strong>: 원하는 서버 주소/포트로 연결을 요청할 때 사용합니다.</li>



<li><strong><code><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.NetworkStreamRequestListen.html" target="_blank" rel="noreferrer noopener">NetworkStreamRequestListen</a></code> singleton&nbsp;</strong>: 서버가 원하는 주소/포트에서 리슨을 시작하도록 요청할 때 사용합니다.</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 클라이언트 월드에서, NetworkStreamRequestConnect가 있는 새 엔티티 생성
// 이 엔티티는 이후 NetworkStreamReceiveSystem에 의해 처리됩니다.
var connectRequest = clientWorld.EntityManager.CreateEntity(typeof(NetworkStreamRequestConnect));
EntityManager.SetComponentData(connectRequest, new NetworkStreamRequestConnect { Endpoint = serverEndPoint });

// 서버 월드에서, NetworkStreamRequestListen이 있는 새 엔티티 생성
// 이 엔티티도 마찬가지로 NetworkStreamReceiveSystem에 의해 처리됩니다.
var listenRequest = serverWorld.EntityManager.CreateEntity(typeof(NetworkStreamRequestListen));
EntityManager.SetComponentData(listenRequest, new NetworkStreamRequestListen { Endpoint = serverEndPoint });
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>이러한 요청은 런타임에 <code><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.NetworkStreamReceiveSystem.html" target="_blank" rel="noreferrer noopener">NetworkStreamReceiveSystem</a></code>에 의해 소비되어 실제 연결 동작을 수행합니다.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>참고 :</strong></p>



<p>실행 중 오류가 발생하면 <strong>PlayMode Tools</strong> 창을 열고 다시 <strong>Play Mode</strong>로 진입해 보세요.</p>



<p>만약 월드가 이미 존재한다면, 부트스트랩 코드(위 설명 참조)에 의해 자동으로 월드가 생성되고 있을 가능성이 큽니다.</p>



<p>서버가 이미 리슨 중이거나 클라이언트가 이미 연결 중이라면, 자동 연결 기능이 이미 활성화되어 있는 것입니다.</p>



<p>이 경우 수동 연결 방식을 사용하려면 <strong>부트스트랩 코드에서 자동 연결을 비활성화</strong>해야 합니다.</p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">4&#x20e3; <strong>Network simulator</strong></h4>



<p>Unity Transport는 <code><strong>SimulatorUtility</strong></code>를 제공합니다. </p>



<p>이 도구는 <strong>Netcode for Entities 패키지</strong>에 포함되어 있으며, 에디터 내에서 다음 경로를 통해 접근하고 설정할 수 있습니다:</p>



<p>Multiplayer &gt; PlayMode Tools</p>



<p>실제 네트워크 상황을 보다 현실적으로 반영하기 위해, 시뮬레이터를 활성화한 상태로 자주 게임플레이를 테스트해보는 것이 좋습니다.</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="1261" height="990" src="https://lycos7560.com/wp-content/uploads/2025/05/image-6.png" alt="" class="wp-image-39999" style="width:838px;height:auto" srcset="https://lycos7560.com/wp-content/uploads/2025/05/image-6.png 1261w, https://lycos7560.com/wp-content/uploads/2025/05/image-6-300x236.png 300w, https://lycos7560.com/wp-content/uploads/2025/05/image-6-768x603.png 768w" sizes="(max-width: 1261px) 100vw, 1261px" /><figcaption class="wp-element-caption">PlayMode Tools</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 클라이언트 연결 이벤트 수신</h3>



<p><code>NetworkStreamDriver</code> 싱글톤을 통해 제공되는 <code>ConnectionEventsForTick</code> (형식: <code>NativeArray&lt;NetCodeConnectionEvent&gt;.ReadOnly</code>) 컬렉션을 사용하여, </p>



<p>클라이언트 및 서버에서 클라이언트 연결 이벤트를 반복(iterate)하면서 반응할 수 있습니다.</p>



<p>이 이벤트는 오직 <strong>단일 SimulationSystemGroup 틱 동안만 존재</strong>하며, 각각 <code>NetworkStreamConnectSystem</code>과 <code>NetworkStreamListenSystem</code>에서 초기화됩니다.</p>



<p>시스템이 위 시스템들의 job 이후에 실행되면, 같은 틱에서 발생한 이벤트를 수신하게 됩니다.</p>



<p>반면, 그 이전에 컬렉션을 조회하면 <strong>이전 틱의 값들을 반복</strong>하게 됩니다.</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 예제 시스템
[UpdateAfter(typeof(NetworkReceiveSystemGroup))]
[BurstCompile]
public partial struct NetCodeConnectionEventListener : ISystem
{
    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        var connectionEventsForClient = SystemAPI.GetSingleton&lt;NetworkStreamDriver>().ConnectionEventsForTick;
        foreach (var evt in connectionEventsForClient)
        {
            UnityEngine.Debug.Log($"[{state.WorldUnmanaged.Name}] {evt.ToFixedString()}!");
        }
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>주의 :</strong></p>



<p>서버는 고정된 델타 타임으로 실행되기 때문에, <code>SimulationSystemGroup</code>은 각 렌더 프레임마다 <strong>0번 이상 실행</strong>될 수 있습니다.</p>



<p>따라서 <code>ConnectionEventsForTick</code>은 반드시 <code>SimulationSystemGroup</code> 내에서 실행되는 시스템 안에서만 읽어야 합니다.</p>



<p>예를 들어 <code>InitializationSystemGroup</code>, <code>PresentationSystemGroup</code>, 또는 어떤 MonoBehaviour 메서드 내에서 접근하면 다음과 같은 문제가 발생할 수 있습니다:</p>



<p>b) 시뮬레이션이 <strong>이 프레임에서 실행되지 않을 경우, 이벤트를 중복 수신</strong></p>



<p>a) 이전 틱 이벤트를 <strong>놓치고 현재 틱만 받음</strong></p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">1&#x20e3; NetCodeConnectionEvents on the client</h4>



<figure class="wp-block-table"><table><thead><tr><th>상태</th><th>호출 규칙</th></tr></thead><tbody><tr><td>Unknown</td><td>절대 발생하지 않음</td></tr><tr><td>Connecting</td><td>자신의 클라이언트에서 한 번 발생. <code>NetworkStreamReceiveSystem</code>이 <code>Connect</code> 호출을 인식한 시점 (호출 프레임 다음일 수 있음)</td></tr><tr><td>Handshake</td><td>내부 transport 드라이버가 <code>Connected</code> 상태에 진입하면 한 번 발생</td></tr><tr><td>Approval</td><td>연결 승인 기능이 활성화된 경우에만 발생. Handshake 이후</td></tr><tr><td>Connected</td><td>서버가 <code>NetworkId</code>를 보내면 발생</td></tr><tr><td>Disconnected</td><td>연결 종료 또는 타임아웃 또는 서버에 의해 연결 해제 시 발생. <code>DisconnectReason</code>이 설정됨</td></tr></tbody></table></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>주의 :</strong></p>



<p>클라이언트는 다른 클라이언트의 이벤트를 수신하지 않습니다. 클라이언트 월드에서 발생한 이벤트는 <strong>자신의 클라이언트</strong>에 대한 이벤트뿐입니다.</p>



<p>Handshake 및 Approval 단계는 실패할 수 있으며, <code>ClientServerTickRate.HandshakeApprovalTimeoutMS</code> (기본값: 5000ms)의 타임아웃을 가집니다.</p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">2&#x20e3; NetCodeConnectionEvents on the server</h4>



<figure class="wp-block-table"><table><thead><tr><th>상태</th><th>호출 규칙</th></tr></thead><tbody><tr><td>Unknown</td><td>절대 발생하지 않음</td></tr><tr><td>Connecting</td><td>클라이언트가 연결을 시작하는 순간을 서버는 알 수 없으므로 발생하지 않음</td></tr><tr><td>Handshake</td><td>모든 클라이언트에 대해 발생. transport 연결이 수락되면 진입</td></tr><tr><td>Approval</td><td>승인 기능이 활성화된 경우에만 발생. Handshake 성공 후</td></tr><tr><td>Connected</td><td>클라이언트가 <code>NetworkId</code>를 부여받는 순간 발생</td></tr><tr><td>Disconnected</td><td>클라이언트가 연결 해제되거나 타임아웃되면 발생. <code>DisconnectReason</code> 설정됨</td></tr></tbody></table></figure>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>주의 :</strong></p>



<p>서버는 바인딩 성공이나 리스닝 시작에 대한 이벤트는 발생시키지 않습니다. <strong>기존 API를 통해 상태를 확인해야 합니다.</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Connection approval</h3>



<p>서버에서 각 클라이언트 연결에 대해 <strong>승인을 요구하도록 설정할 수 있습니다</strong>.</p>



<p>연결 승인은 다음과 같은 목적으로 사용됩니다:</p>



<ul class="wp-block-list">
<li>플레이어 편의성: 화이트리스트 / 블랙리스트, 비밀번호 보호된 서버 등</li>



<li>보안 검증: 매치메이킹 응답으로 받은 <strong>시크릿 토큰</strong>을 사용하여, 매치메이킹된 플레이어만 서버에 입장하도록 제한</li>
</ul>



<p>연결 승인이 활성화되면 다음과 같은 변경이 발생 :</p>



<ol class="wp-block-list">
<li>클라이언트는 <strong>Handshake</strong> 및 <strong>Approval</strong> 단계에서만 <code>IApprovalRpcCommand</code> 형식의 RPC를 서버에 전송할 수 있습니다.</li>



<li>모든 클라이언트는 <strong>Handshake</strong> 상태에서 곧바로 <strong>Connected</strong>로 넘어가는 것이 아니라 <strong>Approval</strong> 상태로 이동합니다.</li>



<li>서버는 연결된 각 클라이언트의 엔티티에 <strong><code>ConnectionApproved</code> 컴포넌트</strong>를 <strong>직접 추가</strong>해야만 승인됩니다.</li>



<li><code>NetworkId</code>는 <strong>승인 성공 이후</strong>에만 할당됩니다. 승인에 실패하면 클라이언트는 연결이 끊어집니다.</li>



<li>승인 과정에는 <strong>타임아웃</strong>이 존재합니다 (<code>ClientServerTickRate.HandshakeApprovalTimeoutMS</code> 참조, 기본값: 5000ms)</li>
</ol>



<p>다시 강조하면:</p>



<ul class="wp-block-list">
<li>Handshake 및 Approval 단계 동안, 클라이언트는 <strong>여러 개의 RPC 메시지를 보낼 수 있습니다.</strong></li>



<li>단, 이들 모두 <code>IApprovalRpcCommand</code> 타입이어야 합니다.</li>



<li>이 RPC의 payload에는 인증 토큰, 플레이어 정보 등 클라이언트의 유효성을 검증하기 위한 모든 정보를 담을 수 있습니다.</li>



<li>서버는 <code>ConnectionApproved</code> 컴포넌트를 클라이언트의 연결 엔티티에 추가함으로써 연결을 승인합니다. 이후 연결 흐름이 계속 진행됩니다.</li>
</ul>



<p><code>NetworkStreamDriver</code>에는 <code>RequireConnectionApproval</code> 필드가 있으며, <strong>클라이언트와 서버 모두에서 true로 설정</strong>해야 연결 승인 흐름이 올바르게 작동합니다.</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div style="height:2px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">if (isServer)
{
    using var drvQuery = server.EntityManager.CreateEntityQuery(ComponentType.ReadWrite&lt;NetworkStreamDriver>());
    drvQuery.GetSingletonRW&lt;NetworkStreamDriver>().ValueRW.RequireConnectionApproval = true;
    drvQuery.GetSingletonRW&lt;NetworkStreamDriver>().ValueRW.Listen(ep);
}
else
{
    using var drvQuery = client.EntityManager.CreateEntityQuery(ComponentType.ReadWrite&lt;NetworkStreamDriver>());
    drvQuery.GetSingletonRW&lt;NetworkStreamDriver>().ValueRW.RequireConnectionApproval = true;
    drvQuery.GetSingletonRW&lt;NetworkStreamDriver>().ValueRW.Connect(client.EntityManager, ep);
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>연결 승인 처리도 다음과 같이 설정할 수 있습니다 : </p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// The approval RPC, here it contains a hypothetical payload the server will validate
public struct ApprovalFlow : IApprovalRpcCommand
{
    public FixedString512Bytes Payload;
}

// This is used to indicate we've already sent an approval RPC and don't need to do so again
public struct ApprovalStarted : IComponentData
{
}

[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation | WorldSystemFilterFlags.ThinClientSimulation)]
public partial struct ClientConnectionApprovalSystem : ISystem
{
    public void OnCreate(ref SystemState state)
    {
        state.RequireForUpdate&lt;RpcCollection>();
    }

    public void OnUpdate(ref SystemState state)
    {
        var ecb = new EntityCommandBuffer(Allocator.Temp);
        // Check connections which have not yet fully connected and send connection approval message
        foreach (var (connection, entity) in SystemAPI.Query&lt;RefRW&lt;NetworkStreamConnection>>().WithNone&lt;NetworkId>().WithNone&lt;ApprovalStarted>().WithEntityAccess())
        {
            var sendApprovalMsg = ecb.CreateEntity();
            ecb.AddComponent(sendApprovalMsg, new ApprovalFlow { Payload = "ABC" });
            ecb.AddComponent&lt;SendRpcCommandRequest>(sendApprovalMsg);

            ecb.AddComponent&lt;ApprovalStarted>(entity);
        }
        ecb.Playback(state.EntityManager);
    }
}

[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
public partial struct ServerConnectionApprovalSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        var ecb = new EntityCommandBuffer(Allocator.Temp);
        // Check connections which have not yet fully connected and send connection approval message
        foreach (var (receiveRpc, approvalMsg, entity) in SystemAPI.Query&lt;RefRO&lt;ReceiveRpcCommandRequest>,RefRW&lt;ApprovalFlow>>().WithEntityAccess())
        {
            var connectionEntity = receiveRpc.ValueRO.SourceConnection;
            if (approvalMsg.ValueRO.Payload.Equals("ABC"))
            {
                ecb.AddComponent&lt;ConnectionApproved>(connectionEntity);

                // Destroy RPC message
                ecb.DestroyEntity(entity);
            }
            else
            {
                // Failed approval messages should be disconnected
                ecb.AddComponent&lt;NetworkStreamRequestDisconnect>(connectionEntity);
            }
        }
        ecb.Playback(state.EntityManager);
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 연결 확인 Sample 코드</h2>



<p><a href="https://discussions.unity.com/t/lobby-relay-and-netcode-for-entities/1538817/8" target="_blank" rel="noreferrer noopener">https://discussions.unity.com/t/lobby-relay-and-netcode-for-entities/1538817/8</a></p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>WorldManager.cs</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using System.Diagnostics.CodeAnalysis;
using Unity.Entities;

namespace Managers 
{
    public static class WorldManager 
    {
        private static World _clientWorld, _serverWorld;
		
        [SuppressMessage("ReSharper", "ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator")]
        public static void DestroyLocalSimulationWorld() {
            foreach (var world in World.All) {
                if (world.Flags != WorldFlags.Game) continue;
                world.Dispose();
                break;
            }
        }
		
        public static void RegisterServerWorld(World world) => _serverWorld = world;
        public static void RegisterClientWorld(World world) => _clientWorld = world;

        public static World GetServerWorld() => _serverWorld;
        public static World GetClientWorld() => _clientWorld;
    }
}</pre>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>RelayServerDataHelper.cs</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Networking.Transport;
using Unity.Networking.Transport.Relay;
using Unity.Services.Relay.Models;

namespace Extension 
{
    public static class RelayServerDataHelper 
    {
        private static RelayServerData GetRelayData(List&lt;RelayServerEndpoint> endpoints, byte[] allocationIdBytes, byte[] connectionDataBytes, byte[] hostConnectionDataBytes, byte[] keyBytes) 
        {
            
            var endpoint = endpoints.FirstOrDefault(e => e.ConnectionType == "dtls") ?? throw new InvalidOperationException($"Endpoint for connectionType dtls not found");
            
            var server = NetworkEndpoint.Parse(endpoint.Host, (ushort)endpoint.Port);
    
            var allocationId = RelayAllocationId.FromByteArray(allocationIdBytes);
            var connData = RelayConnectionData.FromByteArray(connectionDataBytes);
            var hostData = RelayConnectionData.FromByteArray(hostConnectionDataBytes);
            var key = RelayHMACKey.FromByteArray(keyBytes);

            return new RelayServerData(ref server, 0, ref allocationId, ref connData, ref hostData, ref key, true); 
        }

        public static RelayServerData RelayData(JoinAllocation a) => GetRelayData(a.ServerEndpoints, a.AllocationIdBytes, a.ConnectionData, a.HostConnectionData, a.Key);

        public static RelayServerData RelayData(Allocation a) => GetRelayData(a.ServerEndpoints, a.AllocationIdBytes, a.ConnectionData, a.ConnectionData, a.Key);
    }
}</pre>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>RelayInitializer.cs</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using System;
using System.Collections;
using System.Threading.Tasks;
using Unity.Entities;
using Unity.NetCode;
using Unity.Networking.Transport;
using Unity.Networking.Transport.Relay;
using Unity.Services.Authentication;
using Unity.Services.Core;
using Unity.Services.Relay;
using UnityEngine;
using Extension;

namespace Managers 
{
    public class RelayInitializer : MonoBehaviour 
    {
        private static RelayServerData? _relayServerData, _relayClientData;
        private static Action OnConnectionComplete;
        public static string _joinCode;
    
        // Singleton (without duplicate destroy logic) for access to the class instance from within the static methods
        private static RelayInitializer Instance { get; set; }
        protected void Awake() => Instance = this;
        
        // HOSTING

        public static void StartHost() => Instance.StartCoroutine(InitializeHost());

        private static IEnumerator InitializeHost() 
        {
            var initializeTask = UnityServices.InitializeAsync();
            while (!initializeTask.IsCompleted)
                yield return null;
            if (ProcessTaskFail(initializeTask, nameof(initializeTask)))
                yield break;

            var signInTask = Task.CompletedTask;
            if (!AuthenticationService.Instance.IsSignedIn) {
                signInTask = AuthenticationService.Instance.SignInAnonymouslyAsync();
                while (!signInTask.IsCompleted)
                    yield return null; 
            }
            
            if (ProcessTaskFail(signInTask, nameof(signInTask)))
                yield break;

            var allocationTask = RelayService.Instance.CreateAllocationAsync(5);
            
            while (!allocationTask.IsCompleted)
                yield return null;
            
            if (ProcessTaskFail(allocationTask, nameof(allocationTask)))
                yield break;

            var joinCodeTask = RelayService.Instance.GetJoinCodeAsync(allocationTask.Result.AllocationId);
            
            while (!joinCodeTask.IsCompleted)
                yield return null;
            
            if (ProcessTaskFail(joinCodeTask, nameof(joinCodeTask)))
                yield break;

            _joinCode = joinCodeTask.Result;

            try 
            {
                Debug.Log("Hosting relay data");
                _relayServerData = RelayServerDataHelper.RelayData(allocationTask.Result);
            } catch (Exception e) {
                Debug.LogException(e);
                _relayServerData = null;
                yield break;
            }

            Debug.Log("Success, players may now connect");
            while (_relayServerData == null || (!_relayServerData?.Endpoint.IsValid ?? false))
                yield return null;
                
            yield return JoinUsingCode(_joinCode);
            yield return WaitRelayConnection();
            SetupRelayHostedServerAndConnect();
        }

        private static void SetupRelayHostedServerAndConnect() 
        {
            if (ClientServerBootstrap.RequestedPlayType != ClientServerBootstrap.PlayType.ClientAndServer) 
            {
                UnityEngine.Debug.LogError($"Creating client/server worlds is not allowed if playmode is set to {ClientServerBootstrap.RequestedPlayType}");
                return;
            }

            var relayServerData = _relayServerData.GetValueOrDefault();
            var relayClientData = _relayClientData.GetValueOrDefault();

            var oldConstructor = NetworkStreamReceiveSystem.DriverConstructor;
            NetworkStreamReceiveSystem.DriverConstructor = new RelayDriverConstructor(relayServerData, relayClientData);
            var server = ClientServerBootstrap.CreateServerWorld("ServerWorld");
            WorldManager.RegisterServerWorld(server);
            var client = ClientServerBootstrap.CreateClientWorld("ClientWorld");
            WorldManager.RegisterClientWorld(client);
            NetworkStreamReceiveSystem.DriverConstructor = oldConstructor;

            

            WorldManager.DestroyLocalSimulationWorld();
            World.DefaultGameObjectInjectionWorld ??= server;

            // Load scene here if you want to.
            
            Debug.Log(_joinCode);

            var networkStreamEntity = server.EntityManager.CreateEntity(ComponentType.ReadWrite&lt;NetworkStreamRequestListen>());
            server.EntityManager.SetName(networkStreamEntity, "NetworkStreamRequestListen");
            server.EntityManager.SetComponentData(networkStreamEntity,
                new NetworkStreamRequestListen { Endpoint = NetworkEndpoint.AnyIpv4 });

            networkStreamEntity =
                client.EntityManager.CreateEntity(ComponentType.ReadWrite&lt;NetworkStreamRequestConnect>());
            client.EntityManager.SetName(networkStreamEntity, "NetworkStreamRequestConnect");
            client.EntityManager.SetComponentData(networkStreamEntity,
                new NetworkStreamRequestConnect { Endpoint = relayClientData.Endpoint });
            
            ProcessConnectionComplete();
        }

        // CONNECTING
    
        public static void ConnectByCode(string joinCode) => Instance.StartCoroutine(ProcessCodeConnection(joinCode));
    
        private static IEnumerator ProcessCodeConnection(string joinCode) 
        {
            Instance.StartCoroutine(JoinExternalServer(joinCode));
            yield return WaitRelayConnection();
            ConnectToRelayServer();
        }

        private static IEnumerator WaitRelayConnection() {
            while (_relayClientData == null || (!_relayClientData?.Endpoint.IsValid ?? false))
                yield return null;
        }
        
        private static IEnumerator JoinExternalServer(string joinCode) {
            Debug.Log("Waiting for relay response");
            var setupTask = UnityServices.InitializeAsync();

            while (!setupTask.IsCompleted)
                yield return null;
            
            var signInTask = Task.CompletedTask;
            if (!AuthenticationService.Instance.IsSignedIn) {
                signInTask = AuthenticationService.Instance.SignInAnonymouslyAsync();
                while (!signInTask.IsCompleted)
                    yield return null;
            }
            if (ProcessTaskFail(signInTask, nameof(signInTask)))
                yield break;

            yield return JoinUsingCode(joinCode);
        }

        private static IEnumerator JoinUsingCode(string joinCode) 
        {
            // Send the join request to the Relay service
            var joinTask = RelayService.Instance.JoinAllocationAsync(joinCode);
            while (!joinTask.IsCompleted)
                yield return null;
            
            if (ProcessTaskFail(joinTask, nameof(joinTask)))
                yield break;
            
            // Format the server data, based on desired connectionType
            try {
                _relayClientData = RelayServerDataHelper.RelayData(joinTask.Result);
            } catch (Exception e) 
            {
                Debug.LogException(e);
                _relayClientData = null;
            }

            _joinCode = joinCode;
        }
    
        private static void ConnectToRelayServer() 
        {
            var relayClientData = _relayClientData.GetValueOrDefault();
            
            var oldConstructor = NetworkStreamReceiveSystem.DriverConstructor;
            NetworkStreamReceiveSystem.DriverConstructor = new RelayDriverConstructor(new RelayServerData(), relayClientData);
            var client = ClientServerBootstrap.CreateClientWorld("ClientWorld");
            WorldManager.RegisterClientWorld(client);
            NetworkStreamReceiveSystem.DriverConstructor = oldConstructor;

            WorldManager.DestroyLocalSimulationWorld();
            World.DefaultGameObjectInjectionWorld ??= client;
        
            var networkStreamEntity =
                client.EntityManager.CreateEntity(ComponentType.ReadWrite&lt;NetworkStreamRequestConnect>());
            client.EntityManager.SetName(networkStreamEntity, "NetworkStreamRequestConnect");
            client.EntityManager.SetComponentData(networkStreamEntity,
                new NetworkStreamRequestConnect { Endpoint = relayClientData.Endpoint });
            ProcessConnectionComplete();
        }

        // COMMON
    
        private static bool ProcessTaskFail(Task task, string taskName) {
            if (!task.IsFaulted) return false;
            Debug.LogError($"Task {taskName} failed.");
            Debug.LogException(task.Exception);
            return true;
        }

        public static void SubscribeToConnectionComplete(Action handler) => OnConnectionComplete += handler;

        public static void ProcessConnectionComplete() {
            if (OnConnectionComplete == null)
                return;
            OnConnectionComplete?.Invoke();
            foreach (var handler in OnConnectionComplete?.GetInvocationList()!)
                OnConnectionComplete -= (Action)handler;
        }
    }

    public class RelayDriverConstructor : INetworkStreamDriverConstructor 
    {
        private RelayServerData _relayServerData, _relayClientData;
    
        public RelayDriverConstructor(RelayServerData serverData, RelayServerData clientData) {
            _relayServerData = serverData;
            _relayClientData = clientData;
        }

        public void CreateClientDriver(World world, ref NetworkDriverStore driverStore, NetDebug netDebug) {
            var settings = DefaultDriverBuilder.GetNetworkSettings();
            settings.WithRelayParameters(ref _relayClientData);
            DefaultDriverBuilder.RegisterClientDriver(world, ref driverStore, netDebug, settings);
        }

        public void CreateServerDriver(World world, ref NetworkDriverStore driverStore, NetDebug netDebug) =>
            DefaultDriverBuilder.RegisterServerDriver(world, ref driverStore, netDebug, ref _relayServerData);
    }
}</pre>
<p>The post <a href="https://lycos7560.com/c/unity-netcode-for-entities-creating-multiplayer-gameplay/39997/">Unity Netcode for Entities – Connecting server and clients</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://lycos7560.com/c/unity-netcode-for-entities-creating-multiplayer-gameplay/39997/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Unity Netcode for Entities &#8211; Client / Server worlds</title>
		<link>https://lycos7560.com/unity/unity-netcode-for-entities-client-server-worlds/39993/</link>
					<comments>https://lycos7560.com/unity/unity-netcode-for-entities-client-server-worlds/39993/#respond</comments>
		
		<dc:creator><![CDATA[lycos7560]]></dc:creator>
		<pubDate>Thu, 01 May 2025 00:50:19 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[client]]></category>
		<category><![CDATA[Client / Server worlds]]></category>
		<category><![CDATA[dtls]]></category>
		<category><![CDATA[IP]]></category>
		<category><![CDATA[multiplayer]]></category>
		<category><![CDATA[Netcode]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[study]]></category>
		<category><![CDATA[TCP]]></category>
		<category><![CDATA[UDP]]></category>
		<category><![CDATA[WSS]]></category>
		<category><![CDATA[공부]]></category>
		<category><![CDATA[기초]]></category>
		<category><![CDATA[유니티]]></category>
		<guid isPermaLink="false">https://lycos7560.com/?p=39993</guid>

					<description><![CDATA[<p>🔥 Client / Server worlds Setting Netcode for Entities 1.5.0v https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/set-up-client-server-worlds.html Netcode for Entities의 네트워킹 모델을 사용하여client 와 server를 설정합니다. ✅ 클라이언트 / 서버 World 네트워크 모델 https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/client-server-worlds.html Netcode for Entities는 Client와 Server의 로직을 각각 Client world와 Server world로 분리하여 처리합니다. 월드(World)는 Unity의 ECS(Entity Component System) 개념으로, 엔티티와 시스템을 시스템 그룹(SystemGroup)으로 구성한 단위입니다. 기본적인 Client [&#8230;]</p>
<p>The post <a href="https://lycos7560.com/unity/unity-netcode-for-entities-client-server-worlds/39993/">Unity Netcode for Entities &#8211; Client / Server worlds</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></description>
										<content:encoded><![CDATA[				<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-cbe7176c      "
					data-scroll= "1"
					data-offset= "30"
					style=""
				>
				<div class="uagb-toc__wrap">
						<div class="uagb-toc__title">
							목차						</div>
																						<div class="uagb-toc__list-wrap ">
						<ol class="uagb-toc__list"><li class="uagb-toc__list"><a href="#client-server-worlds-setting" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Client / Server worlds Setting</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#클라이언트-서버-world-네트워크-모델" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 클라이언트 / 서버 World 네트워크 모델</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#시스템-생성-및-업데이트-구성" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 시스템 생성 및 업데이트 구성</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-특정-시스템-그룹에-할당하기" class="uagb-toc-link__trigger">1&#x20e3; 특정 시스템 그룹에 할당하기</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#2-worldsystemfilter-사용" class="uagb-toc-link__trigger">2&#x20e3; WorldSystemFilter 사용</a></li></ul><li class="uagb-toc__list"><a href="#client-server-worlds-with-bootstrapping" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Client / Server worlds with bootstrapping</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#0-bootstrapping-커스터-마이징" class="uagb-toc-link__trigger">0&#x20e3; Bootstrapping 커스터 마이징</a></li></ul><li class="uagb-toc__list"><a href="#client-server-업데이트-주기" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Client / Server 업데이트 주기</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#성능-문제-방지" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 성능 문제 방지</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#프레임-속도-유지-방식-설정" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270f.png" alt="✏" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 프레임 속도 유지 방식 설정</a></li></ul><li class="uagb-toc__list"><a href="#월드-마이그레이션-world-migration" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 월드 마이그레이션 (World Migration)</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#additional-resources" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2795.png" alt="➕" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Additional resources</a></li></ul><li class="uagb-toc__list"><a href="#네트워크-프로토콜-검사" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 네트워크 프로토콜 검사</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#개발-중-발생할-수-있는-문제" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 개발 중 발생할 수 있는 문제</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#프로토콜-검사-해제" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 프로토콜 검사 해제</a></li></ul><li class="uagb-toc__list"><a href="#additional-resources" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2795.png" alt="➕" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Additional resources</a></ul></ul></ol>					</div>
									</div>
				</div>
			


<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Client / Server worlds Setting</h2>



<p><strong>Netcode for Entities 1.5.0v</strong></p>



<p><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/set-up-client-server-worlds.html" target="_blank" rel="noreferrer noopener">https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/set-up-client-server-worlds.html</a></p>



<p>Netcode for Entities의 네트워킹 모델을 사용하여client 와 server를 설정합니다.</p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 클라이언트 / 서버 World 네트워크 모델</h3>



<p><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/client-server-worlds.html" target="_blank" rel="noreferrer noopener">https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/client-server-worlds.html</a></p>



<p><strong>Netcode for Entities</strong>는 <strong>Client</strong>와 Server의 로직을 각각 <strong>Client world</strong>와 <strong>Server world</strong>로 분리하여 처리합니다.</p>



<p>월드(World)는 Unity의 <strong>ECS(Entity Component System)</strong> 개념으로, <strong>엔티티와 시스템을 시스템 그룹(SystemGroup)으로 구성한 단위</strong>입니다.</p>



<p>기본적인 Client / Server 월드 외에도, 개발 중에 게임을 테스트할 수 있도록 <strong>씬 클라이언트(Thin Client)</strong> 기능도 지원합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 시스템 생성 및 업데이트 구성</h4>



<p>기본적으로, 모든 시스템은 클라이언트/서버 월드의 <code><a href="https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/api/Unity.Entities.SimulationSystemGroup.html" target="_blank" rel="noreferrer noopener"><code>SimulationSystemGroup</code></a></code>에서 생성되고 업데이트됩니다. </p>



<p>하지만 특정 시스템을 <strong>클라이언트에만</strong>, 또는 <strong>서버에만</strong> 작동하게 만들고 싶을 때는 다음 두 가지 방법을 사용할 수 있습니다</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading">1&#x20e3; 특정 시스템 그룹에 할당하기</h5>



<p>시스템이 속할 시스템 그룹을 지정하면, <strong>그 시스템 그룹이 존재하지 않는 월드에서는 자동으로 필터링</strong>됩니다.</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[UpdateInGroup(typeof(GhostInputSystemGroup))]
public class MyInputSystem : SystemBase
{
  ...
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 참고: </p>



<p><code><a href="https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/api/Unity.Entities.PresentationSystemGroup.html" target="_blank" rel="noreferrer noopener"><code>PresentationSystemGroup</code></a></code>에 속한 시스템은 클라이언트 월드에서만 작동합니다. </p>



<p>Server / Thin client worlds에는 이 시스템 그룹이 생성되지 않기 때문입니다.</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading">2&#x20e3; WorldSystemFilter 사용</h5>



<p>시스템이 어떤 월드에서 작동할지 더 세부적으로 설정하고 싶다면 <strong><code>WorldSystemFilter</code> </strong>속성을 사용하세요.</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// WorldSystemFilterFlags 옵션 
// - LocalSimulation: 오프라인 로컬 시뮬레이션 (Netcode 시스템 없음)
// - ServerSimulation: 서버 시뮬레이션
// - ClientSimulation: 클라이언트 시뮬레이션
// - ThinClientSimulation: 씬 클라이언트
// 속성을 지정하지 않으면, 기본적으로 시스템은 상위 그룹의 필터링 규칙을 따릅니다 (WorldSystemFilterFlags.Default)

[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]
public class MySystem : SystemBase
{
  ...
}</pre>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Client / Server worlds with bootstrapping</h4>



<p><strong>Netcode for Entities</strong>를 프로젝트에 추가하면, 기본 <code><a href="https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ClientServerBootstrap.html" target="_blank" rel="noreferrer noopener"><code>ClientServerBootstrap</code></a></code> 클래스가 제공됩니다. </p>



<p>이 클래스는 <strong>게임 시작 시 클라이언트 및 서버 월드를 자동 생성</strong>합니다</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">public virtual bool Initialize(string defaultWorldName)
{
    CreateDefaultClientServerWorlds();
    return true;
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>자동 부트스트래핑은 <strong>에디터에서 Play 모드 진입 시 매우 유용</strong>합니다. </p>



<p>하지만, <strong>실제 게임에서는 메인 메뉴와 같은 전처리 과정이 필요</strong>하므로 <strong>월드 생성을 지연</strong>시키거나 수동 제어할 필요가 있습니다.</p>



<p>예를 들어</p>



<ul class="wp-block-list">
<li>&#8220;클라이언트-호스트 서버 실행&#8221; → <strong>서버</strong>와 <strong>클라이언트</strong> 모두 생성</li>



<li>&#8220;전용 서버에 접속&#8221; → <strong>클라이언트</strong>만 생성</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading">0&#x20e3; Bootstrapping 커스터 마이징</h5>



<p>기본 <code>ClientServerBootstrap</code>을 상속하여 원하는 방식으로 월드 생성을 제어할 수 있습니다</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">public class MyGameSpecificBootstrap : ClientServerBootstrap
{
    public override bool Initialize(string defaultWorldName)
    {
        // Netcode 없이 로컬 시뮬레이션 월드만 생성
        CreateLocalWorld(defaultWorldName);
        return true;
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>버튼 클릭 등의 타이밍에 다음을 호출하여 월드 생성:</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">var clientWorld = ClientServerBootstrap.CreateClientWorld();
var serverWorld = ClientServerBootstrap.CreateServerWorld();

AutomaticThinClientWorldsUtility.NumThinClientsRequested = 10;
AutomaticThinClientWorldsUtility.BootstrapThinClientWorlds();

ClientServerBootstrap.CreateDefaultClientServerWorlds();
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Netcode Sample  <a href="https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/NetcodeSamples/README.md" target="_blank" rel="noreferrer noopener">https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/NetcodeSamples/README.md</a></p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Client / Server 업데이트 주기</h4>



<p>Netcode for Entities를 사용할 때, 서버는 항상 <strong>Fixed Timestep</strong>으로 업데이트됩니다.</p>



<p>이는 클라이언트 예측을 위한 기본적인 결정론 수준을 보장하고(엄격한 결정론은 아니지만), 물리 시스템의 안정성과 프레임 레이트 독립성을 보장하기 위함입니다.</p>



<p>또한 이 패키지는 프레임당 최대 Fixed Step 반복 횟수를 제한하여 서버가 단일 프레임을 시뮬레이션하는 데 몇 초가 걸리는 상태에 빠지지 않도록 합니다.</p>



<p>중요한 점은 서버의 고정 업데이트가 <a href="https://docs.unity3d.com/Manual/class-TimeManager.html"><strong>표준 Unity 업데이트 빈도</strong></a>&nbsp;또 <strong>Unity 물리 시스템의 Fixed Timestep</strong>를 사용하지 않는다는 것입니다. </p>



<p><strong>대신 자체적인 <code>ClientServerTickRate.SimulationTickRate</code> 를 사용합니다. </strong>&#8211; 고정된 틱(tick) 간격</p>



<p>(이것은 <code>Unity.Physics</code>가 사용 중이라면 정수 배수여야 합니다. <code>ClientServerTickRate.PredictedFixedStepSimulationTickRatio</code>를 참조하세요)</p>



<p>그러나 클라이언트는 동적 타임스텝으로 업데이트됩니다. </p>



<p><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/intro-to-prediction.html" target="_blank" rel="noreferrer noopener">예측 코드만 예외</a>로, 이는 항상 서버와 동일한 고정 타임스텝으로 실행되어 두 시뮬레이션 간의 결정론적 관계를 유지하려고 합니다.</p>



<p>전체 틱과 동기화되지 않은 리프레시 레이트에 대한 예측 처리 방법을 이해하려면 <a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/intro-to-prediction.html#partial-ticks" target="_blank" rel="noreferrer noopener">부분 틱</a>을 참조하세요.</p>



<p>설정 예시:</p>



<p><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/api/Unity.NetCode.ClientServerTickRate.html" target="_blank" rel="noreferrer noopener">https://docs.unity3d.com/Packages/com.unity.netcode@1.5/api/Unity.NetCode.ClientServerTickRate.html</a></p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class MyCustomClientServerBootstrap : ClientServerBootstrap
{
   override public void Initialize(string defaultWorld)
   {
       base.Initialise(defaultWorld);
       var customTickRate = new ClientServerTickRate();
       //run at 30hz
       customTickRate.simulationTickRate = 30;
       customTickRate.ResolveDefault();
       foreach(var world in World.All)
       {
           if(world.IsServer())
           {
              // 이 경우 서버에서만 생성되지만 클라이언트 세계에서도 동일한 작업을 수행할 수 있습니다
              var tickRateEntity = world.EntityManager.CreateSingleton(new ClientServerTickRate
              {
                  SimulationTickRate = 30;
              });
           }
       }
   }
}


// SimulationTickRate = 초당 몇 번의 시뮬레이션 틱을 실행할지 설정합니다. 기본값은 초당 60 틱입니다.
// NetworkTickRate = 서버가 클라이언트에게 스냅샷(snapshot)을 전송하는 빈도를 설정합니다. 기본값은 SimulationTickRate와 동일합니다.</pre>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 성능 문제 방지</h5>



<p>서버가 설정된 시뮬레이션 틱 레이트보다 <strong>느린 속도로 업데이트될 경우</strong>, 한 프레임에서 여러 개의 시뮬레이션 틱을 처리하려고 시도합니다.</p>



<p>예를 들어, 서버의 마지막 업데이트가 16ms가 아닌 50ms가 걸렸다면, 서버는 다음 프레임에서 이를 따라잡기 위해 약 <strong>3번의 시뮬레이션 스텝</strong>을 실행합니다 (16ms × 3 ≈ 50ms).</p>



<p>이러한 동작은 <strong>성능 저하를 악화시키는 악순환</strong>을 유발할 수 있습니다:</p>



<p>서버는 더 많은 시뮬레이션 스텝을 처리해야 하므로 점점 더 느려지고, 그 결과 틱 간격을 더 많이 놓치게 됩니다.</p>



<p>위와 같은 상황을 방지하기 위해 <code>ClientServerTickRate</code>에서는 다음과 같은 설정을 제공합니다</p>



<ul class="wp-block-list">
<li><code>MaxSimulationStepsPerFrame</code><br>서버가 한 프레임 내에 수행할 수 있는 <strong>최대 시뮬레이션 스텝 수</strong>를 제한합니다.</li>



<li><code>MaxSimulationStepBatchSize</code><br>여러 틱을 <strong>하나의 배치(batch)</strong> 로 묶어 처리하도록 지시합니다. <br>이때는 <strong>델타 타임(delta time)을 곱한 값</strong>으로 단일 스텝을 실행합니다.<br>예: 2개의 스텝을 실행하는 대신, <strong>1개의 스텝</strong>만 실행하되 <strong>델타 타임을 2배</strong>로 설정하여 처리합니다.</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6ab.png" alt="🚫" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>주의</strong>: <br><code>MaxSimulationStepBatchSize</code> 에 의한 배칭 처리는 특정 조건에서만 작동하며, 자체적인 제한 사항이 있습니다.<br>게임 로직에서 &#8220;<strong>한 시뮬레이션 스텝 = 하나의 틱</strong>&#8220;이라고 가정하지 않도록 하며, <code>TimeData.DeltaTime</code> 값을 <strong>하드코딩하지 마십시오</strong>.<br>배칭이 발생하면 <strong>서버와 클라이언트 간의 시뮬레이션 정밀도가 달라져 예측 오류</strong>가 발생할 수 있습니다.</p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270f.png" alt="✏" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 프레임 속도 유지 방식 설정</h5>



<p>서버가 유휴 상태일 때 <strong>프레임 속도를 어떻게 유지할지</strong>도 설정할 수 있습니다. </p>



<p><code>TargetFrameRateMode</code>는 서버가 틱 레이트를 유지하기 위한 <strong>유휴 시간 소비 방식</strong>을 제어합니다.</p>



<ul class="wp-block-list">
<li><strong><code>BusyWait</code></strong><br>가능한 한 빠른 속도로 계속 실행 (CPU 사용량 높음)</li>



<li><strong><code>Sleep</code></strong><br><code>Application.targetFrameRate</code>에 맞춰 대기하여 CPU 부하를 줄임</li>



<li><strong><code>Auto</code></strong><br>헤드리스(콘솔 없는) 서버에서는 <code>Sleep</code>을 사용하고, 그 외에는 <code>BusyWait</code>을 사용</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 월드 마이그레이션 (World Migration)</h4>



<p>현재 사용 중인 월드를 <strong>파괴(destroy)</strong> 하고, <strong>연결 상태를 유지한 채로 새로운 월드로 전환</strong>하고자 할 경우, <code>DriverMigrationSystem</code>을 사용할 수 있습니다.</p>



<p>이 시스템은 네트워크 전송(transport) 관련 정보를 저장 및 불러올 수 있게 해주며, <strong>매끄러운 월드 전환</strong>을 가능하게 합니다.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">public World MigrateWorld(World sourceWorld)
{
    DriverMigrationSystem migrationSystem = default;
    foreach (var world in World.All)
    {
        if ((migrationSystem = world.GetExistingSystem&lt;DriverMigrationSystem>()) != null)
            break;
    }

    var ticket = migrationSystem.StoreWorld(sourceWorld);
    sourceWorld.Dispose();

    var newWorld = migrationSystem.LoadWorld(ticket);

    // NOTE: LoadWorld는 반드시 새 월드에 필요한 시스템을 추가하기 전에 호출해야 합니다!
    // 이유: LoadWorld는 NetworkStreamReceiveSystem이 올바른 드라이버를 불러오기 위해 필요한 
    // `MigrationTicket` 컴포넌트를 생성하기 때문입니다.

    return ClientServerBootstrap.CreateServerWorld(DefaultWorld, newWorld.Name, newWorld);
}
</pre>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<p>이 기능은 예를 들어 <strong>로비에서 인게임으로 넘어가거나</strong>, <strong>씬을 바꾸면서도 연결을 유지해야 하는 경우</strong>에 매우 유용합니다.</p>



<h4 class="wp-block-heading" id="additional-resources"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2795.png" alt="➕" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Additional resources</h4>



<ul class="wp-block-list">
<li><a href="https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/manual/index.html" target="_blank" rel="noreferrer noopener">Entities overview</a></li>



<li><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/thin-clients.html" target="_blank" rel="noreferrer noopener">Thin clients</a></li>



<li><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/intro-to-prediction.html" target="_blank" rel="noreferrer noopener">Introduction to prediction</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 네트워크 프로토콜 검사</h3>



<p><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/network-protocol-checks.html" target="_blank" rel="noreferrer noopener">https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/network-protocol-checks.html</a></p>



<p>클라이언트가 서버에 연결할 때, <strong>Netcode 프로토콜 버전(NetworkProtocolVersion)</strong> 을 주고받습니다. </p>



<p>이 프로토콜에는 다음과 같은 정보가 포함되어 있습니다:</p>



<ul class="wp-block-list">
<li>Netcode 버전 (netcode version)</li>



<li>게임 버전 (game version)</li>



<li>RPC 컬렉션 (RPC collection)</li>



<li>직렬화된 컴포넌트 컬렉션 (erialized component collections)</li>
</ul>



<p>서로 호환되지 않는 게임 버전 간의 연결을 <strong>사전에 차단</strong>하여 예측할 수 없는 동작을 방지합니다.</p>



<p> <strong>RPC 컬렉션</strong>은 모든 로드된 어셈블리에서 컴파일된 RPC들의 <strong>타입과 멤버</strong>를 기반으로 해시를 계산합니다.</p>



<p><strong>Serialized Component 컬렉션</strong> 역시 Netcode for Entities가 수집한 고스트(Ghost) 컴포넌트를 기반으로 해시를 계산합니다.</p>



<p>이러한 타입 정보와 멤버들을 기반으로 계산된 <strong>해시값</strong>이 프로토콜의 일부로 사용됩니다.</p>



<p>Netcode for Entities는 기본적으로 이 해시값이 <strong>완전히 동일해야</strong> 통신이 가능하도록 설정되어 있습니다.</p>



<p>이렇게 하면 중간에 <strong>예외가 발생하는 것을 방지</strong>하고, <strong>대역폭 최적화</strong>가 가능합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--40);margin-bottom:var(--wp--preset--spacing--40)"/>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 개발 중 발생할 수 있는 문제</h4>



<p>개발 중에는 <strong>호환 가능한 빌드조차도</strong> 이 검사 때문에 <strong>부적합한 버전으로 잘못 판단되는</strong> 경우가 있습니다.</p>



<p>예를 들어:</p>



<ul class="wp-block-list">
<li>독립 실행형 빌드와 Unity Editor에서 실행 중인 월드를 연결하려는 경우</li>



<li>Editor는 테스트용 어셈블리를 포함하고 있는데, 빌드에는 포함되어 있지 않을 경우</li>



<li>이로 인해 해시가 일치하지 않아 연결이 끊어짐</li>
</ul>



<p>이러한 <strong>엄격한 프로토콜 검사</strong>는 개발 중 테스트에 방해가 될 수 있으므로, <strong><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/network-protocol-checks.html#disabling-the-check" target="_blank" rel="noreferrer noopener">비활성화</a>할 수 있습니다.</strong></p>



<p>이 프로토콜 버전 오류가 발생하면 각 피어는 사용자 코드가 읽을 수 있는 를 통해 원격 피어와의 연결을 끊고&nbsp;</p>



<p><code>NetworkStreamDisconnectReason.BadProtocolVersion</code>, 이를 사용하여 플레이어에게 해당 빌드가 대상 원격 피어와 호환되지 않음을 알립니다. </p>



<p>개발 빌드에서는 패키지가 로컬 피어에 로드된 RPC 및 고스트 유형의 전체 목록과 정렬된 목록을 나타내는 오류 로그도 출력합니다. </p>



<p>유형 불일치 문제를 해결하려면 이러한 로그를 원격 피어에서 발생한 로그와 상호 참조하세요.</p>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>프로토콜 검사</strong> 해제</h5>



<p>검사를 비활성화하려면, 다음과 같이 <code>RpcCollection.DynamicAssemblyList</code>를 <code>true</code>로 설정합니다:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[BurstCompile] // 선택 사항
[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation | WorldSystemFilterFlags.ServerSimulation | WorldSystemFilterFlags.ThinClientSimulation)]
[UpdateInGroup(typeof(InitializationSystemGroup))]
[CreateAfter(typeof(RpcSystem))]
public partial struct SetRpcSystemDynamicAssemblyListSystem : ISystem
{
    public void OnCreate(ref SystemState state)
    {
        SystemAPI.GetSingletonRW&lt;RpcCollection>().ValueRW.DynamicAssemblyList = true;
        state.Enabled = false;
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6ab.png" alt="🚫" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>주의</strong>: </p>



<p>이 설정은 <code>RpcSystem.OnUpdate</code>가 실행되기 전에 적용되어야 하며,</p>



<p><code>RpcSystem.OnCreate</code> 이후에 설정되어야 합니다.</p>



<p><strong>클라이언트와 서버 모두 이 플래그 값을 동일하게 설정해야</strong> 연결이 가능합니다. (값이 다르면 프로토콜 해석 방식이 달라지기 때문)</p>



<p>이 기능을 활성화하면 다음과 같은 단점이 있습니다:</p>



<ul class="wp-block-list">
<li>각 RPC마다 <strong>6바이트의 오버헤드</strong>가 발생합니다 (ushort 인덱스 대신 해시값 전체를 전송)</li>



<li>게임 도중, 클라이언트가 <strong>알 수 없는 RPC나 고스트 타입을 수신</strong>하게 되면<br>→ 런타임 오류 발생 후 <strong>즉시 연결이 끊어짐</strong><br>→ 즉, 연결 시점이 아닌 게임 중간에 강제 종료될 수 있습니다</li>
</ul>



<p>따라서 이 설정은 <strong>개발 중 테스트 목적</strong>으로 사용하는 것이 좋으며, <strong>출시용 빌드에서는 권장되지 않습니다.</strong></p>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2795.png" alt="➕" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Additional resources</h4>



<ul class="wp-block-list">
<li><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/api/Unity.NetCode.NetworkProtocolVersion.html" target="_blank" rel="noreferrer noopener">NetworkProtocolVersion API</a></li>
</ul>



<p></p>
<p>The post <a href="https://lycos7560.com/unity/unity-netcode-for-entities-client-server-worlds/39993/">Unity Netcode for Entities &#8211; Client / Server worlds</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://lycos7560.com/unity/unity-netcode-for-entities-client-server-worlds/39993/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>IInputComponentData [Netcode for Entities]</title>
		<link>https://lycos7560.com/unity/iinputcomponentdata-netcode-for-entities/39970/</link>
					<comments>https://lycos7560.com/unity/iinputcomponentdata-netcode-for-entities/39970/#respond</comments>
		
		<dc:creator><![CDATA[lycos7560]]></dc:creator>
		<pubDate>Sun, 27 Apr 2025 06:33:37 +0000</pubDate>
				<category><![CDATA[Unity]]></category>
		<category><![CDATA[client]]></category>
		<category><![CDATA[Client / Server worlds]]></category>
		<category><![CDATA[compress]]></category>
		<category><![CDATA[connect]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[dtls]]></category>
		<category><![CDATA[ECS]]></category>
		<category><![CDATA[Entities]]></category>
		<category><![CDATA[Entity]]></category>
		<category><![CDATA[IComponentData]]></category>
		<category><![CDATA[IInputComponentData]]></category>
		<category><![CDATA[IP]]></category>
		<category><![CDATA[multiplayer]]></category>
		<category><![CDATA[Netcode]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[NFE]]></category>
		<category><![CDATA[online]]></category>
		<category><![CDATA[Quantization]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[study]]></category>
		<category><![CDATA[TCP]]></category>
		<category><![CDATA[UDP]]></category>
		<category><![CDATA[WSS]]></category>
		<category><![CDATA[공부]]></category>
		<category><![CDATA[기초]]></category>
		<category><![CDATA[양자]]></category>
		<category><![CDATA[양자화]]></category>
		<category><![CDATA[유니티]]></category>
		<guid isPermaLink="false">https://lycos7560.com/?p=39970</guid>

					<description><![CDATA[<p>🔍 IInputComponentData https://docs.unity3d.com/Packages/com.unity.netcode@1.5/api/Unity.NetCode.IInputComponentData.html Netcode for Entities (NFE)에서 클라이언트의 입력을 서버로 전송하기 위해 특별히 설계된 인터페이스 IInputComponentData의 핵심 역할 1️⃣ 입력 데이터의 네트워크 동기화 2️⃣ 예측(Prediction) 시스템 지원 3️⃣ 입력 버퍼링 ✍🏻예시 코드 ❓[GhostField(Quantization = 100)] 양자화를 사용하는 이유 Netcode for Entities (NFE)에서&#160;네트워크 대역폭을 최적화하기 위해 사용되는 핵심 기능 1️⃣ 데이터 압축으로 대역폭 절감 2️⃣ 네트워크 [&#8230;]</p>
<p>The post <a href="https://lycos7560.com/unity/iinputcomponentdata-netcode-for-entities/39970/">IInputComponentData [Netcode for Entities]</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></description>
										<content:encoded><![CDATA[				<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-ab9c0ba8      "
					data-scroll= "1"
					data-offset= "30"
					style=""
				>
				<div class="uagb-toc__wrap">
						<div class="uagb-toc__title">
							목차						</div>
																						<div class="uagb-toc__list-wrap ">
						<ol class="uagb-toc__list"><li class="uagb-toc__list"><a href="#iinputcomponentdata" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50d.png" alt="🔍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> IInputComponentData</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#iinputcomponentdata의-핵심-역할" class="uagb-toc-link__trigger">IInputComponentData의 핵심 역할</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-입력-데이터의-네트워크-동기화" class="uagb-toc-link__trigger">1&#x20e3; 입력 데이터의 네트워크 동기화</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#2-예측prediction-시스템-지원" class="uagb-toc-link__trigger">2&#x20e3; 예측(Prediction) 시스템 지원</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#3-입력-버퍼링" class="uagb-toc-link__trigger">3&#x20e3; 입력 버퍼링</a></li></ul><li class="uagb-toc__list"><a href="#예시-코드" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270d-1f3fb.png" alt="✍🏻" class="wp-smiley" style="height: 1em; max-height: 1em;" />예시 코드</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#ghostfieldquantization-100-양자화를-사용하는-이유" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2753.png" alt="❓" class="wp-smiley" style="height: 1em; max-height: 1em;" />[GhostField(Quantization = 100)] 양자화를 사용하는 이유</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-데이터-압축으로-대역폭-절감" class="uagb-toc-link__trigger">1&#x20e3; 데이터 압축으로 대역폭 절감</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#2-네트워크-지연-감소" class="uagb-toc-link__trigger">2&#x20e3; 네트워크 지연 감소</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#3-작동-원리" class="uagb-toc-link__trigger">3&#x20e3; 작동 원리</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#4-간단-적용-예시" class="uagb-toc-link__trigger">4&#x20e3; 간단 적용 예시</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#5-최적화-가이드" class="uagb-toc-link__trigger">5&#x20e3; 최적화 가이드</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#6-주의사항" class="uagb-toc-link__trigger">6&#x20e3; 주의사항</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#7-성능비교" class="uagb-toc-link__trigger">7&#x20e3; 성능비교</a></li></ul></li></ul><li class="uagb-toc__list"><a href="#iinputcomponentdata-와-icomponentdata의-차이점" class="uagb-toc-link__trigger">IInputComponentData 와 IComponentData의 차이점</a></ul></ol>					</div>
									</div>
				</div>
			


<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50d.png" alt="🔍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>IInputComponentData</code></h2>



<p><a href="https://docs.unity3d.com/Packages/com.unity.netcode@1.5/api/Unity.NetCode.IInputComponentData.html" target="_blank" rel="noreferrer noopener">https://docs.unity3d.com/Packages/com.unity.netcode@1.5/api/Unity.NetCode.IInputComponentData.html</a></p>



<p><strong>Netcode for Entities (NFE)</strong>에서 클라이언트의 입력을 서버로 전송하기 위해 특별히 설계된 인터페이스</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><strong><code>IInputComponentData</code>의 핵심 역할</strong></h3>



<h4 class="wp-block-heading"><strong>1&#x20e3; 입력 데이터의 네트워크 동기화</strong></h4>



<ul class="wp-block-list">
<li><strong>클라이언트 → 서버</strong>로의 입력 전송을 최적화합니다.</li>



<li>NFE는 이 인터페이스가 붙은 컴포넌트를 자동으로 직렬화/역직렬화합니다.</li>
</ul>



<h4 class="wp-block-heading"><strong>2&#x20e3; 예측(Prediction) 시스템 지원</strong></h4>



<ul class="wp-block-list">
<li><strong>클라이언트 측 예측</strong>과&nbsp;<strong>서버 측 보정</strong>을 가능하게 합니다.</li>



<li><code>GhostPredictionSystemGroup</code>에서 특별 처리됩니다.</li>
</ul>



<h4 class="wp-block-heading"><strong>3&#x20e3; 입력 버퍼링</strong></h4>



<ul class="wp-block-list">
<li>틱(tick) 기반으로 입력을 저장해&nbsp;<strong>네트워크 지연 보정</strong>에 사용됩니다.</li>
</ul>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270d-1f3fb.png" alt="✍🏻" class="wp-smiley" style="height: 1em; max-height: 1em;" /><strong>예시 코드</strong></h3>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using Unity.Entities;
using Unity.NetCode;

// 반드시 IInputComponentData를 상속해야 함
public struct NetcodePlayerInput : IInputComponentData
{
    // 필드에 [GhostField] 속성을 추가해 직렬화 옵션 지정
    [GhostField(Quantization = 100)] // 값 범위: -1.0 ~ 1.0 → -100 ~ 100으로 압축
    public float MoveX; // 좌우 이동 입력 (-1: 왼쪽, 1: 오른쪽)

    [GhostField]
    public float MoveY; // 전후 이동 입력

    [GhostField]
    public InputEvent Jump; // 점프 입력 (버튼 상태)

    // 현재 틱 정보 (NFE가 자동으로 주입)
    public uint Tick { get; set; }
}</pre>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2753.png" alt="❓" class="wp-smiley" style="height: 1em; max-height: 1em;" />[GhostField(Quantization = 100)] 양자화를 사용하는 이유</h4>



<p>Netcode for Entities (NFE)에서&nbsp;<strong>네트워크 대역폭을 최적화</strong>하기 위해 사용되는 핵심 기능</p>



<h5 class="wp-block-heading"><strong><strong>1&#x20e3;</strong> 데이터 압축으로 대역폭 절감</strong></h5>



<ul class="wp-block-list">
<li><strong>원본 데이터</strong>:&nbsp;<code>float</code>&nbsp;(32비트)</li>



<li><strong>양자화 후</strong>:&nbsp;<code>short</code>&nbsp;(16비트) 등 작은 타입으로 변환</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[GhostField(Quantization = 100)] 
public float MoveX; // -1.0 ~ 1.0 → -100 ~ 100 정수로 압축
// 1.75f → 175 (전송) : 수신 측에서 1.75f로 복원</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><strong><strong>2&#x20e3;</strong> 네트워크 지연 감소</strong></h5>



<p>작은 데이터 패킷으로 통신하여&nbsp;<strong>전송 시간 단축</strong>하여 <strong>실시간 반응성 향상</strong> (지연 시간 감소)</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><strong><strong>3&#x20e3;</strong> <strong><strong>작동 원리</strong></strong></strong></h5>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>원본 값</th><th>양자화 계수</th><th>송신 값</th><th>복원 값</th><th>오차</th></tr></thead><tbody><tr><td>0.73f</td><td>100</td><td>73</td><td>0.73f</td><td>0%</td></tr><tr><td>1.28f</td><td>100</td><td>128</td><td>1.28f</td><td>0%</td></tr><tr><td>0.123f</td><td>100</td><td>12</td><td>0.12f</td><td>2.4%</td></tr></tbody></table></figure>



<ul class="wp-block-list">
<li><strong>적정 범위</strong>:&nbsp;<code>-1.0 ~ 1.0</code>&nbsp;(조이스틱 입력 등)
<ul class="wp-block-list">
<li><code>Quantization = 100</code>&nbsp;→&nbsp;<code>-100 ~ +100</code>&nbsp;(총 201단계)</li>



<li><strong>필요 비트</strong>:&nbsp;<code>⌈log₂(201)⌉ = 8비트</code>&nbsp;(1바이트)</li>
</ul>
</li>



<li><strong>정밀도 vs 효율 트레이드오프</strong>:
<ul class="wp-block-list">
<li><strong>100</strong>: 0.01 단위 정밀도 (대부분의 게임 입력에 충분)</li>



<li><strong>1000</strong>: 0.001 단위 (고정밀 필요 시) → 대역폭 2배 소모</li>
</ul>
</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><strong>4&#x20e3; <strong><strong>간단 적용 예시</strong></strong></strong></h5>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 캐릭터 이동
[GhostField(Quantization = 100)]
public float Horizontal; // 좌우 이동 (-1.0 ~ 1.0)

[GhostField(Quantization = 100)]
public float Vertical;   // 전후 이동

// 캐릭터 회전
[GhostField(Quantization = 32767)] // short.MaxValue
public float RotationY; // 0 ~ 360도 → -32767 ~ 32767
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><strong> </strong>5&#x20e3; 최적화 가이드</h5>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th><strong>값 범위</strong></th><th><strong>권장 양자화 계수</strong></th><th><strong>비트 사용량</strong></th></tr></thead><tbody><tr><td>-1.0 ~ 1.0</td><td>100</td><td>8비트</td></tr><tr><td>-10.0 ~ 10.0</td><td>10</td><td>8비트</td></tr><tr><td>0 ~ 360 (각도)</td><td>32767</td><td>16비트</td></tr><tr><td>고정밀 물리 파라미터</td><td>10000+</td><td>16~32비트</td></tr></tbody></table></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><strong>6&#x20e3; 주의사항</strong></h5>



<ul class="wp-block-list">
<li><strong>오버플로우 방지</strong><br><code>Quantization</code>&nbsp;값을 너무 크게 설정하면 정수 변환 시 오버플로우 발생 가능:</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 위험 예시 (float.MaxValue → 양자화 시 오류)
[GhostField(Quantization = 1000000)] 
public float DangerValue;</pre>



<ul class="wp-block-list">
<li><strong><strong>정밀도 한계</strong></strong><br><code>0.005f</code>&nbsp;같은 미세한 값은&nbsp;<code>Quantization=100</code>에서&nbsp;<strong>반올림 오차</strong>&nbsp;발생:</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">0.005f * 100 = 0.5f → 반올림 → 1 → 복원 시 0.01f (100% 오차)</pre>



<ul class="wp-block-list">
<li><strong><strong>에디터 디버깅</strong></strong><br><code>NetworkProtocol</code>&nbsp;로그에서 실제 전송 크기 확인:</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// Unity 콘솔에 패킷 크기 출력
Debug.Log($"패킷 크기: {System.Runtime.InteropServices.Marshal.SizeOf(packet)}바이트");</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><strong>7&#x20e3; </strong>성능비교</h5>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 양자화 미적용 (32비트 float)
[GhostField] 
public float Uncompressed; // 4바이트

// 양자화 적용 (8비트 압축)
[GhostField(Quantization = 100)] 
public float Compressed; // 1바이트

절감 효과: 75% 대역폭 감소 (4배 효율)
초당 60프레임 기준:
미적용: 60fps * 4B = 240B/s
적용: 60fps * 1B = 60B/s</pre>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><strong><code>IInputComponentData</code></strong> 와 <code>IComponentData</code>의 차이점</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>특징</th><th><code>IInputComponentData</code></th><th><code>IComponentData</code></th></tr></thead><tbody><tr><td><strong>자동 직렬화</strong></td><td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b55.png" alt="⭕" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 네트워크 전송 최적화</td><td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 직접 구현 필요</td></tr><tr><td><strong>예측 지원</strong></td><td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b55.png" alt="⭕" class="wp-smiley" style="height: 1em; max-height: 1em;" />&nbsp;<code>PredictedGhost</code>와 연동</td><td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 별도 시스템 필요</td></tr><tr><td><strong>틱 동기화</strong></td><td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b55.png" alt="⭕" class="wp-smiley" style="height: 1em; max-height: 1em;" />&nbsp;<code>Tick</code>&nbsp;프로퍼티 자동 관리</td><td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 수동 처리</td></tr><tr><td><strong>버퍼링</strong></td><td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b55.png" alt="⭕" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 입력 히스토리 유지</td><td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 직접 구현</td></tr></tbody></table></figure>



<p></p>
<p>The post <a href="https://lycos7560.com/unity/iinputcomponentdata-netcode-for-entities/39970/">IInputComponentData [Netcode for Entities]</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://lycos7560.com/unity/iinputcomponentdata-netcode-for-entities/39970/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Unity Serialization (직렬화)</title>
		<link>https://lycos7560.com/unity/unity-serialization-%ec%a7%81%eb%a0%ac%ed%99%94/39882/</link>
					<comments>https://lycos7560.com/unity/unity-serialization-%ec%a7%81%eb%a0%ac%ed%99%94/39882/#respond</comments>
		
		<dc:creator><![CDATA[lycos7560]]></dc:creator>
		<pubDate>Tue, 25 Feb 2025 09:24:30 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Byte Stream]]></category>
		<category><![CDATA[Configuration Files]]></category>
		<category><![CDATA[Data Format]]></category>
		<category><![CDATA[Data Storage]]></category>
		<category><![CDATA[Data Structure]]></category>
		<category><![CDATA[data transfer]]></category>
		<category><![CDATA[Developer Tools]]></category>
		<category><![CDATA[Dictionary]]></category>
		<category><![CDATA[file saving]]></category>
		<category><![CDATA[Game Data]]></category>
		<category><![CDATA[Game Development]]></category>
		<category><![CDATA[Game State Saving]]></category>
		<category><![CDATA[Inspector]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[JsonUtility]]></category>
		<category><![CDATA[List]]></category>
		<category><![CDATA[Load System]]></category>
		<category><![CDATA[Memory Management]]></category>
		<category><![CDATA[Newtonsoft.Json]]></category>
		<category><![CDATA[Object Conversion]]></category>
		<category><![CDATA[parsing]]></category>
		<category><![CDATA[PlayerPrefs]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Readability]]></category>
		<category><![CDATA[Runtime]]></category>
		<category><![CDATA[Save System]]></category>
		<category><![CDATA[Scene Management]]></category>
		<category><![CDATA[ScriptableObject]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[Serialization]]></category>
		<category><![CDATA[Serialization Rules]]></category>
		<category><![CDATA[SerializeField]]></category>
		<category><![CDATA[study]]></category>
		<category><![CDATA[System.Serializable]]></category>
		<category><![CDATA[Unity Editor]]></category>
		<category><![CDATA[Variable Types]]></category>
		<category><![CDATA[WebSockets]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[YAML]]></category>
		<category><![CDATA[가독성]]></category>
		<category><![CDATA[개발자도구]]></category>
		<category><![CDATA[객체변환]]></category>
		<category><![CDATA[게임개발]]></category>
		<category><![CDATA[게임데이터]]></category>
		<category><![CDATA[게임상태저장]]></category>
		<category><![CDATA[공부]]></category>
		<category><![CDATA[데이터구조]]></category>
		<category><![CDATA[데이터저장]]></category>
		<category><![CDATA[데이터전송]]></category>
		<category><![CDATA[데이터포맷]]></category>
		<category><![CDATA[런타임]]></category>
		<category><![CDATA[로드시스템]]></category>
		<category><![CDATA[메모리관리]]></category>
		<category><![CDATA[바이트스트림]]></category>
		<category><![CDATA[변수타입]]></category>
		<category><![CDATA[설정파일]]></category>
		<category><![CDATA[스크립팅]]></category>
		<category><![CDATA[씬관리]]></category>
		<category><![CDATA[웹소켓]]></category>
		<category><![CDATA[유니티에디터]]></category>
		<category><![CDATA[직렬화]]></category>
		<category><![CDATA[직렬화규칙]]></category>
		<category><![CDATA[파싱]]></category>
		<category><![CDATA[파일저장]]></category>
		<category><![CDATA[프로그래밍]]></category>
		<guid isPermaLink="false">https://lycos7560.com/?p=39882</guid>

					<description><![CDATA[<p>🔥 Serialization (직렬화) 개요 Serialization이란 객체 데이터를 바이트 스트림으로 변환하여 저장하거나 전송할 수 있도록 하는 과정 주 목적은 필요할 때 다시 개체로 만들 수 있도록 개체의 상태를 저장하는 것 반대로 Deserialization은 저장된 바이트 데이터를 다시 객체로 변환하는 과정입니다. 🔥 JSON, XML, YAML 일반적으로 많이 사용하는 데이터 직렬화 포맷들 1️⃣ JSON (JavaScript Object Notation) ✔️ 특징 [&#8230;]</p>
<p>The post <a href="https://lycos7560.com/unity/unity-serialization-%ec%a7%81%eb%a0%ac%ed%99%94/39882/">Unity Serialization (직렬화)</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></description>
										<content:encoded><![CDATA[				<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-571189ff      "
					data-scroll= "1"
					data-offset= "30"
					style=""
				>
				<div class="uagb-toc__wrap">
						<div class="uagb-toc__title">
							목차						</div>
																						<div class="uagb-toc__list-wrap ">
						<ol class="uagb-toc__list"><li class="uagb-toc__list"><a href="#serialization-직렬화-개요" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Serialization (직렬화) 개요</a><li class="uagb-toc__list"><a href="#json-xml-yaml" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> JSON, XML, YAML</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-json-javascript-object-notation" class="uagb-toc-link__trigger">1&#x20e3; JSON (JavaScript Object Notation)</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#2-xml-extensible-markup-language" class="uagb-toc-link__trigger">2&#x20e3; XML (eXtensible Markup Language)</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#3-yaml-yaml-aint-markup-language" class="uagb-toc-link__trigger">3&#x20e3; YAML (YAML Ain&#039;t Markup Language)</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#비교-정리" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50e.png" alt="🔎" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 비교 정리</a></li></ul></li><li class="uagb-toc__list"><a href="#unity에서의-스크립트-직렬화-serialization-in-unity" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" />Unity에서의 스크립트 직렬화 (Serialization in Unity)</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-unity에서-직렬화가-중요한-이유" class="uagb-toc-link__trigger">1&#x20e3; Unity에서 직렬화가 중요한 이유</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#2-unity에서-직렬화-가능한-타입" class="uagb-toc-link__trigger">2&#x20e3; Unity에서 직렬화 가능한 타입</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#3-unity-직렬화-적용-방법" class="uagb-toc-link__trigger">3&#x20e3; Unity 직렬화 적용 방법</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#4-unity-직렬화와-json-활용" class="uagb-toc-link__trigger">4&#x20e3; Unity 직렬화와 JSON 활용</a></ul></ul></ol>					</div>
									</div>
				</div>
			


<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Serialization (직렬화) 개요</strong></h2>



<p><strong>Serialization</strong>이란<strong> 객체 데이터</strong>를 <strong>바이트 스트림</strong>으로 변환하여 <strong>저장</strong>하거나 <strong>전송</strong>할 수 있도록 하는 과정</p>



<p>주 목적은 필요할 때 다시 개체로 만들 수 있도록 개체의 상태를 저장하는 것</p>



<p>반대로 <strong>Deserialization</strong>은 저장된 바이트 데이터를 다시 객체로 변환하는 과정입니다.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="262" height="199" src="https://lycos7560.com/wp-content/uploads/2025/02/image-179.png" alt="" class="wp-image-39884"/><figcaption class="wp-element-caption"><a href="https://learn.microsoft.com/ko-kr/dotnet/visual-basic/programming-guide/concepts/serialization/" target="_blank" rel="noreferrer noopener">https://learn.microsoft.com/ko-kr/dotnet/visual-basic/programming-guide/concepts/serialization/</a></figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading"><strong><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></strong> JSON, XML, YAML</h2>



<p>일반적으로 많이 사용하는 데이터 직렬화 포맷들</p>



<hr class="wp-block-separator has-alpha-channel-opacity" style="margin-top:var(--wp--preset--spacing--30);margin-bottom:var(--wp--preset--spacing--30)"/>



<h3 class="wp-block-heading">1&#x20e3; JSON (JavaScript Object Notation)</h3>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 특징</h4>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 가벼운 텍스트 기반 포맷<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 사람이 읽고 쓰기 쉬우며, 기계가 빠르게 처리 가능<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 대부분의 프로그래밍 언어에서 지원 (C#, Python, JavaScript 등)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 키-값 쌍의 구조 (Dictionary, Object와 유사)</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 예제</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "name": "John",
  "age": 30,
  "skills": ["C#", "Unity", "Python"],
  "isDeveloper": true
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 장점</h4>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 가볍고 속도가 빠름<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 대부분의 언어에서 지원<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> API 및 데이터 전송에 적합 (REST API, WebSockets 등)</p>



<h4 class="wp-block-heading"><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 단점</strong></h4>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 주석 지원이 안됨<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> XML이나 YAML보다 덜 유연함</p>



<hr class="wp-block-separator has-alpha-channel-opacity" style="margin-top:var(--wp--preset--spacing--40);margin-bottom:var(--wp--preset--spacing--40)"/>



<h3 class="wp-block-heading">2&#x20e3; XML (eXtensible Markup Language)</h3>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 특징</h4>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 데이터 구조를 계층적으로 표현 (HTML과 유사)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 사람이 읽을 수 있지만, JSON보다 길이가 김<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 다양한 도메인에서 사용 (문서 저장, 설정 파일, 웹 서비스 등)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> &lt;태그&gt;를 이용한 구조화된 데이터 표현</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 예제</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;Person>
    &lt;Name>John&lt;/Name>
    &lt;Age>30&lt;/Age>
    &lt;Skills>
        &lt;Skill>C#&lt;/Skill>
        &lt;Skill>Unity&lt;/Skill>
        &lt;Skill>Python&lt;/Skill>
    &lt;/Skills>
    &lt;IsDeveloper>true&lt;/IsDeveloper>
&lt;/Person>
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 장점</h4>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 데이터 구조가 명확함<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 주석 사용 가능 (&lt;!&#8211; 주석 &#8211;&gt;)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 다양한 데이터 타입을 표현하기 적합</p>



<h4 class="wp-block-heading"><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 단점</strong></h4>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> JSON보다 크기가 크고, 가독성이 떨어짐<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 파싱 속도가 느림</p>



<hr class="wp-block-separator has-alpha-channel-opacity" style="margin-top:var(--wp--preset--spacing--40);margin-bottom:var(--wp--preset--spacing--40)"/>



<h3 class="wp-block-heading">3&#x20e3; YAML (YAML Ain&#8217;t Markup Language)</h3>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 특징</h4>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> JSON과 유사하지만 더 간결한 문법을 가짐<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 들여쓰기를 이용한 계층 구조 (Python과 유사)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 설정 파일에서 많이 사용 (Docker, Kubernetes, Unity Config 등)</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 예제</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="yaml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">name: John
age: 30
skills:
  - C#
  - Unity
  - Python
isDeveloper: true
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 장점</h4>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 사람이 읽기 쉬운 직관적인 문법<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> JSON보다 간결하여 가독성이 좋음<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 주석 (#) 사용 가능</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 단점</strong></h4>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 들여쓰기 실수로 인한 오류 발생 가능<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 파싱 속도가 JSON보다 느림</p>



<figure class="wp-block-image size-full"><img decoding="async" width="727" height="481" src="https://lycos7560.com/wp-content/uploads/2025/02/image-180.jpg" alt="" class="wp-image-39885" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-180.jpg 727w, https://lycos7560.com/wp-content/uploads/2025/02/image-180-300x198.jpg 300w" sizes="(max-width: 727px) 100vw, 727px" /><figcaption class="wp-element-caption">Unity의 YAML<br><a href="https://unity.com/kr/blog/engine-platform/understanding-unitys-serialization-language-yaml" target="_blank" rel="noreferrer noopener">https://unity.com/kr/blog/engine-platform/understanding-unitys-serialization-language-yaml</a></figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity" style="margin-top:var(--wp--preset--spacing--40);margin-bottom:var(--wp--preset--spacing--40)"/>



<h3 class="wp-block-heading"><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50e.png" alt="🔎" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 비교 정리</strong></h3>



<p>Unity에서는 JSON (JsonUtility, Newtonsoft.Json)이 가장 많이 사용되며, YAML은 Unity의 설정 파일 (.yml)에서 많이 활용됩니다.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>형식</th><th>문법</th><th>가독성</th><th>속도</th><th>사용 사례</th></tr></thead><tbody><tr><td><strong>JSON</strong></td><td><code>{ "key": "value" }</code></td><td>좋음</td><td>빠름 <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td>API, 데이터 저장</td></tr><tr><td><strong>XML</strong></td><td><code>&lt;tag&gt;value&lt;/tag&gt;</code></td><td>중간</td><td>느림 <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td>문서 저장, 설정 파일</td></tr><tr><td><strong>YAML</strong></td><td><code>key: value</code> (들여쓰기)</td><td>매우 좋음 <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td>중간</td><td>설정 파일, DevOps</td></tr></tbody></table></figure>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="1620" height="714" src="https://lycos7560.com/wp-content/uploads/2025/02/image-180.png" alt="" class="wp-image-39886" style="width:771px;height:auto" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-180.png 1620w, https://lycos7560.com/wp-content/uploads/2025/02/image-180-300x132.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-180-768x338.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-180-1536x677.png 1536w" sizes="(max-width: 1620px) 100vw, 1620px" /></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading"><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" />Unity에서의 스크립트 직렬화 (Serialization in Unity)</strong></h2>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default" style="margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50)"/>



<h3 class="wp-block-heading">1&#x20e3; <strong>Unity에서 직렬화가 중요한 이유</strong></h3>



<p>Unity는 <strong>Inspector 창에서 데이터를 유지</strong>하거나 <strong>저장 시스템(예: PlayerPrefs, JSON, Binary 파일 등)에 데이터를 저장</strong>하기 위해 직렬화를 활용합니다.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>씬(Scene) 저장 및 로드</strong>: Inspector에 입력한 값이 유지됨<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>ScriptableObject:</strong> 게임 데이터 관리<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Save/Load 시스템</strong>: JSON 또는 Binary 직렬화를 활용하여 파일 저장</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default" style="margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50)"/>



<h3 class="wp-block-heading">2&#x20e3; <strong>Unity에서 직렬화 가능한 타입</strong></h3>



<p><a href="https://docs.unity3d.com/6000.0/Documentation/Manual/script-serialization-rules.html" target="_blank" rel="noreferrer noopener">https://docs.unity3d.com/6000.0/Documentation/Manual/script-serialization-rules.html</a></p>



<p>Unity는 <strong>특정 데이터 타입만 직렬화할 수 있도록 제한</strong>하고 있습니다.</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b55.png" alt="⭕" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 직렬화 가능한 타입 (Serializable)</h4>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>기본 데이터 타입</strong>: <code>int</code>, <code>float</code>, <code>bool</code>, <code>string</code> 등<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Unity 기본 타입</strong>: <strong>배열 &amp; 리스트</strong>: <code>int[]</code>, <code>List&lt;float&gt;</code> 등 (단, <code>public</code> 또는 <code>[SerializeField]</code> 필요)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>사용자 정의 클래스</strong> (<code>[System.Serializable]</code> 필요)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>ScriptableObject</strong></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong> 직렬화 불가능한 타입 (Non-Serializable)</h4>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>딕셔너리(Dictionary)</strong><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>다차원 배열 (<code>int[,]</code>)</strong><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong><strong>속성(Property) (getter/setter)</strong></strong><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong><strong>Static 변수 (<code>static</code>)</strong></strong><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong><strong>추상 클래스 &amp; 인터페이스</strong></strong><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong><strong>델리게이트(Delegate), 이벤트(Event)</strong></strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default" style="margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50)"/>



<h3 class="wp-block-heading">3&#x20e3; <strong>Unity 직렬화 적용 방법</strong></h3>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> [SerializeField]</h4>



<p><code>private</code> 변수도 Inspector에서 보이도록 만들고, 직렬화 가능하게 합니다.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using UnityEngine;

public class Player : MonoBehaviour
{
    [SerializeField] private int health = 100;  // 직렬화됨 (Inspector에서 수정 가능)
    private int score = 0;  // 직렬화되지 않음 (Inspector에서 보이지 않음)
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> [SerializeField]를 사용하면 <code>private</code> 변수도 직렬화됨<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 하지만 <code>static</code>, <code>const</code>, <code>readonly</code> 변수는 직렬화되지 않음</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> [System.Serializable]</h4>



<p>사용자 정의 클래스를 직렬화하려면 <code>[System.Serializable]</code>을 붙여야 합니다.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using UnityEngine;

[System.Serializable]  
public class Weapon
{
    public string name;
    public int damage;
}

public class Player : MonoBehaviour
{
    public Weapon myWeapon;  // Weapon 클래스가 직렬화되므로 Inspector에서 수정 가능
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 클래스를 <code>System.Serializable</code>로 만들면 Unity Inspector에서 확인 가능<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 하지만 <code>Dictionary</code>, <code>Properties</code>, <code>Static 변수</code> 등은 여전히 직렬화되지 않음</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ScriptableObject</h4>



<p>게임 데이터를 저장 및 관리하는 특수한 직렬화 객체</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using UnityEngine;

[CreateAssetMenu(fileName = "New Weapon", menuName = "Weapon")]
public class WeaponData : ScriptableObject
{
    public string weaponName;
    public int damage;
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 씬(Scene)과 독립적으로 데이터 관리 가능<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 메모리 효율적 관리 가능 (오브젝트 풀링, 설정 저장 등)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 런타임에서 수정된 값은 저장되지 않음 (Play 모드가 끝나면 초기화됨)</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default" style="margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50)"/>



<h3 class="wp-block-heading">4&#x20e3; <strong>Unity 직렬화와 JSON 활용</strong></h3>



<p>Unity에서 JSON 직렬화를 활용하면 <strong>데이터 저장 &amp; 로드</strong>가 가능해집니다.</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> JsonUtility (빠르지만 제한적)</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using UnityEngine;

[System.Serializable]
public class PlayerData
{
    public string name;
    public int level;
}

public class SaveLoadSystem : MonoBehaviour
{
    void Start()
    {
        PlayerData player = new PlayerData { name = "John", level = 10 };
        string json = JsonUtility.ToJson(player);
        Debug.Log(json);  // {"name":"John","level":10}

        PlayerData loadedPlayer = JsonUtility.FromJson&lt;PlayerData>(json);
        Debug.Log(loadedPlayer.name);  // John
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 빠름 &amp; Unity 기본 지원<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Dictionary, List&lt;T&gt; 같은 복잡한 자료형 지원 X</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Newtonsoft.Json (더 강력한 JSON 직렬화)</h4>



<p><code>Newtonsoft.Json</code> 라이브러리를 사용하면 <strong>Dictionary, List, Interface 등도 직렬화 가능</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using UnityEngine;
using Newtonsoft.Json;
using System.Collections.Generic;

public class PlayerData
{
    public string name;
    public int level;
    public Dictionary&lt;string, int> inventory = new Dictionary&lt;string, int>();
}

public class SaveLoadSystem : MonoBehaviour
{
    void Start()
    {
        PlayerData player = new PlayerData { name = "John", level = 10 };
        player.inventory.Add("Sword", 1);
        player.inventory.Add("Potion", 5);

        string json = JsonConvert.SerializeObject(player, Formatting.Indented);
        Debug.Log(json);

        PlayerData loadedPlayer = JsonConvert.DeserializeObject&lt;PlayerData>(json);
        Debug.Log(loadedPlayer.inventory["Sword"]);  // 1
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Dictionary, List&lt;T&gt; 등 복잡한 자료형 지원<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> JsonUtility보다 속도가 느림<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 추가 라이브러리 설치 필요 (<code>Newtonsoft.Json.dll</code>)</p>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="[유니티 TIPS] 데이터 시리얼라이제이션 완전 정복하기" width="1778" height="1000" src="https://www.youtube.com/embed/kEu_AQ_Es-8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div><figcaption class="wp-element-caption">공부 참고 영상</figcaption></figure>



<p></p>
<p>The post <a href="https://lycos7560.com/unity/unity-serialization-%ec%a7%81%eb%a0%ac%ed%99%94/39882/">Unity Serialization (직렬화)</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://lycos7560.com/unity/unity-serialization-%ec%a7%81%eb%a0%ac%ed%99%94/39882/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>URP VFX Learning Templates (2)</title>
		<link>https://lycos7560.com/unity/urp-vfx-learning-templates-2/39699/</link>
					<comments>https://lycos7560.com/unity/urp-vfx-learning-templates-2/39699/#respond</comments>
		
		<dc:creator><![CDATA[lycos7560]]></dc:creator>
		<pubDate>Sun, 23 Feb 2025 00:40:02 +0000</pubDate>
				<category><![CDATA[Unity]]></category>
		<category><![CDATA[Alpha Blending]]></category>
		<category><![CDATA[Compute Shader]]></category>
		<category><![CDATA[Flipbook Animation]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Motion Vectors]]></category>
		<category><![CDATA[Noise Texture]]></category>
		<category><![CDATA[Particle System]]></category>
		<category><![CDATA[Real-time FX]]></category>
		<category><![CDATA[Rendering Tricks]]></category>
		<category><![CDATA[Templates]]></category>
		<category><![CDATA[TUTORIAL]]></category>
		<category><![CDATA[Unity Docs]]></category>
		<category><![CDATA[Unity Shader]]></category>
		<category><![CDATA[Unity VFX Graph]]></category>
		<category><![CDATA[URP]]></category>
		<category><![CDATA[URP (Universal Render Pipeline)]]></category>
		<category><![CDATA[VFX]]></category>
		<category><![CDATA[VFX (Visual Effects)]]></category>
		<category><![CDATA[VFX Techniques]]></category>
		<guid isPermaLink="false">https://lycos7560.com/?p=39699</guid>

					<description><![CDATA[<p>URP_VFX_Learning_Templates (2) 11. TexIndex Attribute VFX 아티스트들은 스프라이트 시트(Sprite Sheet) 를 자주 사용합니다. 이 VFX 예제는 출력(Output) 에서 UV 옵션 을 사용하여 스프라이트 시트 를 활용하는 방법을 보여줍니다. 또한 Flipbook 설정 을 구성하는 방법과 texIndex 속성 과의 관계를 설명합니다. Covered Aspects: 12. Flipbook Mode 이 VFX는 Output(출력)의 UV 모드를 Flipbook으로 설정하여 스프라이트 시트를 사용하는 방법을 [&#8230;]</p>
<p>The post <a href="https://lycos7560.com/unity/urp-vfx-learning-templates-2/39699/">URP VFX Learning Templates (2)</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">
<blockquote class="wp-embedded-content" data-secret="f27cY38Nml"><a href="https://lycos7560.com/unity/urp-vfx-learning-templates-1/39596/">URP VFX Learning Templates (1)</a></blockquote><iframe loading="lazy" class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;URP VFX Learning Templates (1)&#8221; &#8212; 어제와 내일의 나 그 사이의 이야기" src="https://lycos7560.com/unity/urp-vfx-learning-templates-1/39596/embed/#?secret=j2C2b3DaWr#?secret=f27cY38Nml" data-secret="f27cY38Nml" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</div></figure>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>


				<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-303fb734      "
					data-scroll= "1"
					data-offset= "30"
					style=""
				>
				<div class="uagb-toc__wrap">
						<div class="uagb-toc__title">
							목차						</div>
																						<div class="uagb-toc__list-wrap ">
						<ol class="uagb-toc__list"><li class="uagb-toc__list"><a href="#urp-vfx-learning-templates-2" class="uagb-toc-link__trigger">URP_VFX_Learning_Templates (2)</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#11-texindex-attribute" class="uagb-toc-link__trigger">11. TexIndex Attribute</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#12-flipbook-mode" class="uagb-toc-link__trigger">12. Flipbook Mode</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#13-flipbook-blending" class="uagb-toc-link__trigger">13. Flipbook Blending</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#14-texindex-advanced" class="uagb-toc-link__trigger">14. TexIndex Advanced</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#15-pivot-attribute" class="uagb-toc-link__trigger">15. Pivot Attribute</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#16-pivot-advanced" class="uagb-toc-link__trigger">16. Pivot Advanced</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#17-sample-mesh" class="uagb-toc-link__trigger">17. Sample Mesh</a></ul></ol>					</div>
									</div>
				</div>
			


<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Unity 6 - 6000.0.32f1
Visual Effect Graph - 17.0.3</pre>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h1 class="wp-block-heading">URP_VFX_Learning_Templates (2)</h1>



<h2 class="wp-block-heading">11. TexIndex Attribute</h2>



<p>VFX 아티스트들은 <strong>스프라이트 시트(Sprite Sheet)</strong> 를 자주 사용합니다.</p>



<p>이 VFX 예제는 <strong>출력(Output)</strong> 에서 <strong>UV 옵션</strong> 을 사용하여 <strong>스프라이트 시트</strong> 를 활용하는 방법을 보여줍니다. </p>



<p>또한 <strong>Flipbook 설정</strong> 을 구성하는 방법과 <strong>texIndex 속성</strong> 과의 관계를 설명합니다.</p>



<h3 class="wp-block-heading"><strong><strong>Covered Aspects:</strong></strong></h3>



<ul class="wp-block-list">
<li>TexIndex Attribute</li>



<li>UVs Mode</li>



<li>Flipbook</li>
</ul>



<figure class="wp-block-video"><video height="1056" style="aspect-ratio: 1704 / 1056;" width="1704" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_07_35_03_551.mp4"></video><figcaption class="wp-element-caption">TexIndex Attribute Video (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1439" height="943" src="https://lycos7560.com/wp-content/uploads/2025/02/image-78.png" alt="" class="wp-image-39713" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-78.png 1439w, https://lycos7560.com/wp-content/uploads/2025/02/image-78-300x197.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-78-768x503.png 768w" sizes="(max-width: 1439px) 100vw, 1439px" /><figcaption class="wp-element-caption">TexIndex Attribute Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1762" height="1789" src="https://lycos7560.com/wp-content/uploads/2025/02/image-74-1.jpg" alt="" class="wp-image-39700" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-74-1.jpg 1762w, https://lycos7560.com/wp-content/uploads/2025/02/image-74-1-295x300.jpg 295w, https://lycos7560.com/wp-content/uploads/2025/02/image-74-1-768x780.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-74-1-1513x1536.jpg 1513w" sizes="(max-width: 1762px) 100vw, 1762px" /><figcaption class="wp-element-caption">Sprite Debug Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1271" height="1780" src="https://lycos7560.com/wp-content/uploads/2025/02/image-74.png" alt="" class="wp-image-39701" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-74.png 1271w, https://lycos7560.com/wp-content/uploads/2025/02/image-74-214x300.png 214w, https://lycos7560.com/wp-content/uploads/2025/02/image-74-768x1076.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-74-1097x1536.png 1097w" sizes="(max-width: 1271px) 100vw, 1271px" /><figcaption class="wp-element-caption">Leaf Fliebook Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1387" height="1088" src="https://lycos7560.com/wp-content/uploads/2025/02/image-77-1.jpg" alt="" class="wp-image-39708" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-77-1.jpg 1387w, https://lycos7560.com/wp-content/uploads/2025/02/image-77-1-300x235.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-77-1-768x602.jpg 768w" sizes="(max-width: 1387px) 100vw, 1387px" /><figcaption class="wp-element-caption">SpriteSheet Debug (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1910" height="921" src="https://lycos7560.com/wp-content/uploads/2025/02/image-75.png" alt="" class="wp-image-39703" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-75.png 1910w, https://lycos7560.com/wp-content/uploads/2025/02/image-75-300x145.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-75-768x370.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-75-1536x741.png 1536w" sizes="(max-width: 1910px) 100vw, 1910px" /><figcaption class="wp-element-caption">SpriteSheet Debug (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1714" height="942" src="https://lycos7560.com/wp-content/uploads/2025/02/image-76.jpg" alt="" class="wp-image-39704" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-76.jpg 1714w, https://lycos7560.com/wp-content/uploads/2025/02/image-76-300x165.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-76-768x422.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-76-1536x844.jpg 1536w" sizes="(max-width: 1714px) 100vw, 1714px" /><figcaption class="wp-element-caption">SpriteSheet Debug (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1879" height="949" src="https://lycos7560.com/wp-content/uploads/2025/02/image-76.png" alt="" class="wp-image-39705" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-76.png 1879w, https://lycos7560.com/wp-content/uploads/2025/02/image-76-300x152.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-76-768x388.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-76-1536x776.png 1536w" sizes="(max-width: 1879px) 100vw, 1879px" /><figcaption class="wp-element-caption">Leaf Flipbook (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1697" height="1008" src="https://lycos7560.com/wp-content/uploads/2025/02/image-77.jpg" alt="" class="wp-image-39706" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-77.jpg 1697w, https://lycos7560.com/wp-content/uploads/2025/02/image-77-300x178.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-77-768x456.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-77-1536x912.jpg 1536w" sizes="(max-width: 1697px) 100vw, 1697px" /><figcaption class="wp-element-caption">Leaf Flipbook (2)</figcaption></figure>



<figure class="wp-block-video"><video height="1228" style="aspect-ratio: 2168 / 1228;" width="2168" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_07_58_26_612.mp4"></video><figcaption class="wp-element-caption">TexIndex Attribute Video (2)</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">12. Flipbook Mode</h2>



<p>이 VFX는 <strong>Output(출력)의 UV 모드를 Flipbook으로 설정하여 스프라이트 시트를 사용하는 방법</strong>을 보여줍니다.</p>



<p>또한 <strong>Flipbook Blend Frames 사용법과 Flipbook Player Block의 기본적인 활용 방법</strong>을 설명합니다.</p>



<p><strong>Flipbook Blend Frames</strong> 설정을 사용하면 프레임 간 보간(Interpolation)이 적용되어 <strong>부드러운 애니메이션 효과</strong>를 얻을 수 있습니다.</p>



<h3 class="wp-block-heading"><strong><strong>Covered Aspects:</strong></strong></h3>



<ul class="wp-block-list">
<li>Flipbook Player</li>



<li>UVs Mode</li>



<li>TexIndex Attribute</li>
</ul>



<figure class="wp-block-video"><video height="1224" style="aspect-ratio: 2344 / 1224;" width="2344" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_08_13_45_776.mp4"></video><figcaption class="wp-element-caption">Flipbook Mode Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1595" height="1006" src="https://lycos7560.com/wp-content/uploads/2025/02/image-79.jpg" alt="" class="wp-image-39714" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-79.jpg 1595w, https://lycos7560.com/wp-content/uploads/2025/02/image-79-300x189.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-79-768x484.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-79-1536x969.jpg 1536w" sizes="(max-width: 1595px) 100vw, 1595px" /><figcaption class="wp-element-caption">CandleMesh Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="955" height="1011" src="https://lycos7560.com/wp-content/uploads/2025/02/image-77.png" alt="" class="wp-image-39712" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-77.png 955w, https://lycos7560.com/wp-content/uploads/2025/02/image-77-283x300.png 283w, https://lycos7560.com/wp-content/uploads/2025/02/image-77-768x813.png 768w" sizes="(max-width: 955px) 100vw, 955px" /><figcaption class="wp-element-caption">CandleMesh Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1394" height="1019" src="https://lycos7560.com/wp-content/uploads/2025/02/image-79.png" alt="" class="wp-image-39715" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-79.png 1394w, https://lycos7560.com/wp-content/uploads/2025/02/image-79-300x219.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-79-768x561.png 768w" sizes="(max-width: 1394px) 100vw, 1394px" /><figcaption class="wp-element-caption">CandleMesh (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1843" height="1045" src="https://lycos7560.com/wp-content/uploads/2025/02/image-80-1.jpg" alt="" class="wp-image-39717" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-80-1.jpg 1843w, https://lycos7560.com/wp-content/uploads/2025/02/image-80-1-300x170.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-80-1-768x435.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-80-1-1536x871.jpg 1536w" sizes="(max-width: 1843px) 100vw, 1843px" /><figcaption class="wp-element-caption">CandleMesh (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="684" height="542" src="https://lycos7560.com/wp-content/uploads/2025/02/image-85.png" alt="" class="wp-image-39730" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-85.png 684w, https://lycos7560.com/wp-content/uploads/2025/02/image-85-300x238.png 300w" sizes="(max-width: 684px) 100vw, 684px" /></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1833" height="997" src="https://lycos7560.com/wp-content/uploads/2025/02/image-80.png" alt="" class="wp-image-39718" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-80.png 1833w, https://lycos7560.com/wp-content/uploads/2025/02/image-80-300x163.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-80-768x418.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-80-1536x835.png 1536w" sizes="(max-width: 1833px) 100vw, 1833px" /><figcaption class="wp-element-caption">SG Candle Shader Graph</figcaption></figure>



<div class="wp-block-file"><a id="wp-block-file--media-5df68b37-34df-4a04-8ebb-a6b2f97bb390" href="https://lycos7560.com/wp-content/uploads/2025/02/SG_Candle.unitypackage">SG_Candle</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/SG_Candle.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-5df68b37-34df-4a04-8ebb-a6b2f97bb390">다운로드</a></div>



<figure class="wp-block-image size-full"><img decoding="async" width="765" height="984" src="https://lycos7560.com/wp-content/uploads/2025/02/image-81.png" alt="" class="wp-image-39720" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-81.png 765w, https://lycos7560.com/wp-content/uploads/2025/02/image-81-233x300.png 233w" sizes="(max-width: 765px) 100vw, 765px" /><figcaption class="wp-element-caption">Flipbook Flame Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1847" height="998" src="https://lycos7560.com/wp-content/uploads/2025/02/image-82.jpg" alt="" class="wp-image-39721" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-82.jpg 1847w, https://lycos7560.com/wp-content/uploads/2025/02/image-82-300x162.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-82-768x415.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-82-1536x830.jpg 1536w" sizes="(max-width: 1847px) 100vw, 1847px" /><figcaption class="wp-element-caption">Flipbook Flame (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1885" height="1065" src="https://lycos7560.com/wp-content/uploads/2025/02/image-82.png" alt="" class="wp-image-39722" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-82.png 1885w, https://lycos7560.com/wp-content/uploads/2025/02/image-82-300x169.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-82-768x434.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-82-1536x868.png 1536w" sizes="(max-width: 1885px) 100vw, 1885px" /><figcaption class="wp-element-caption">Flipbook Flame (2)</figcaption></figure>



<figure class="wp-block-video"><video height="920" style="aspect-ratio: 1816 / 920;" width="1816" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_08_52_55_798.mp4"></video><figcaption class="wp-element-caption">Flipbook Flame Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="693" height="542" src="https://lycos7560.com/wp-content/uploads/2025/02/image-83.png" alt="" class="wp-image-39724" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-83.png 693w, https://lycos7560.com/wp-content/uploads/2025/02/image-83-300x235.png 300w" sizes="(max-width: 693px) 100vw, 693px" /></figure>



<div class="wp-block-file"><a id="wp-block-file--media-8e29395e-ab0b-42c2-bf45-20a8391e377c" href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Flipbook_CandleFlame.unitypackage">TX_Flipbook_CandleFlame</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Flipbook_CandleFlame.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-8e29395e-ab0b-42c2-bf45-20a8391e377c">다운로드</a></div>



<figure class="wp-block-image size-full"><img decoding="async" width="613" height="973" src="https://lycos7560.com/wp-content/uploads/2025/02/image-84.png" alt="" class="wp-image-39726" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-84.png 613w, https://lycos7560.com/wp-content/uploads/2025/02/image-84-189x300.png 189w" sizes="(max-width: 613px) 100vw, 613px" /><figcaption class="wp-element-caption">FlipBook Mode Debug Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1654" height="991" src="https://lycos7560.com/wp-content/uploads/2025/02/image-86.png" alt="" class="wp-image-39728" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-86.png 1654w, https://lycos7560.com/wp-content/uploads/2025/02/image-86-300x180.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-86-768x460.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-86-1536x920.png 1536w" sizes="(max-width: 1654px) 100vw, 1654px" /><figcaption class="wp-element-caption">FlipBook Mode Debug</figcaption></figure>



<div class="wp-block-file"><a id="wp-block-file--media-4b4e556a-d996-4461-84ba-44b59b05f52e" href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Flipbook_example.unitypackage">TX_Flipbook_example</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Flipbook_example.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-4b4e556a-d996-4461-84ba-44b59b05f52e">다운로드</a></div>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">13. Flipbook Blending</h2>



<p>이 VFX는 <strong>일반적인 프레임 블렌딩(Frame Blending)과 모션 벡터(Motion Vectors)를 이용한 프레임 블렌딩</strong>의 차이를 보여줍니다.</p>



<p>모션 벡터 블렌딩(Motion Vector Blending)은 <strong>프레임 간 픽셀 이동 정보를 포함한 텍스처를 활용하여 프레임 간 부드러운 전환을 구현</strong>합니다.</p>



<p>이 방식은 <strong>플립북의 프레임 수를 줄이거나, 슬로우 모션(Slow Motion) 애니메이션을 구현할 때 유용</strong>합니다.</p>



<h3 class="wp-block-heading"><strong><strong>Covered Aspects:</strong></strong></h3>



<ul class="wp-block-list">
<li>Flipbook Player</li>



<li>UVs Mode</li>



<li>TexIndex Attribute</li>
</ul>



<figure class="wp-block-video"><video height="1196" style="aspect-ratio: 2232 / 1196;" width="2232" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_09_16_43_921.mp4"></video><figcaption class="wp-element-caption">Flipbook Blending Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1139" height="1061" src="https://lycos7560.com/wp-content/uploads/2025/02/image-87.png" alt="" class="wp-image-39732" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-87.png 1139w, https://lycos7560.com/wp-content/uploads/2025/02/image-87-300x279.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-87-768x715.png 768w" sizes="(max-width: 1139px) 100vw, 1139px" /><figcaption class="wp-element-caption">Flipbook Blending Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1490" height="1045" src="https://lycos7560.com/wp-content/uploads/2025/02/image-88.png" alt="" class="wp-image-39733" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-88.png 1490w, https://lycos7560.com/wp-content/uploads/2025/02/image-88-300x210.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-88-768x539.png 768w" sizes="(max-width: 1490px) 100vw, 1490px" /><figcaption class="wp-element-caption">Flipbook Blending (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1790" height="1039" src="https://lycos7560.com/wp-content/uploads/2025/02/image-89.jpg" alt="" class="wp-image-39734" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-89.jpg 1790w, https://lycos7560.com/wp-content/uploads/2025/02/image-89-300x174.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-89-768x446.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-89-1536x892.jpg 1536w" sizes="(max-width: 1790px) 100vw, 1790px" /><figcaption class="wp-element-caption">Flipbook Blending (2)</figcaption></figure>



<div class="wp-block-file"><a id="wp-block-file--media-4b503e0c-56b3-4777-858e-1c35a4a134ff" href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Flipbook_Smoke.unitypackage">TX_Flipbook_Smoke</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Flipbook_Smoke.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-4b503e0c-56b3-4777-858e-1c35a4a134ff">다운로드</a></div>



<figure class="wp-block-video"><video height="1360" style="aspect-ratio: 2536 / 1360;" width="2536" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_09_31_46_844.mp4"></video></figure>



<p>일반적인 Blend Frame은 단순한 알파 블렌딩(Alpha Blending) 방식으로, 프레임 수가 부족할 경우 끊김 현상이 발생할 수 있음.</p>



<p>Flipbook Player를 사용하면 자동으로 <code>TexIndex</code>가 증가하며 애니메이션이 진행됨.</p>



<p>Motion Vector Blending을 사용하면 픽셀 이동 정보를 활용하여 더욱 부드러운 전환을 구현할 수 있음.</p>



<ul class="wp-block-list">
<li>이 방법은 플립북 애니메이션의 프레임 수를 줄이면서도 부드러운 모션을 유지하는 데 유용함.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">14. <strong>TexIndex Advanced</strong></h2>



<p>이 고급 VFX는 <strong>texIndex 속성</strong>을 창의적으로 활용하는 여러 시스템으로 구성되어 있습니다.</p>



<p>시간(Time), 노이즈(Noise), 심지어 파티클의 위치(Position)까지 사용하여 </p>



<p><strong>texIndex 속성</strong>을 제어하며, 이를 통해 생동감 있는 VFX를 만듭니다.</p>



<h3 class="wp-block-heading"><strong><strong>Covered Aspects:</strong></strong></h3>



<ul class="wp-block-list">
<li>Flipbook UVs</li>



<li>TexIndex Attribute</li>



<li>Flipbook Player</li>
</ul>



<figure class="wp-block-image size-full"><img decoding="async" width="1781" height="589" src="https://lycos7560.com/wp-content/uploads/2025/02/image-118.jpg" alt="" class="wp-image-39787" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-118.jpg 1781w, https://lycos7560.com/wp-content/uploads/2025/02/image-118-300x99.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-118-768x254.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-118-1536x508.jpg 1536w" sizes="(max-width: 1781px) 100vw, 1781px" /><figcaption class="wp-element-caption">TexIndex Advanced Graph Entire</figcaption></figure>



<figure class="wp-block-video"><video height="1172" style="aspect-ratio: 2320 / 1172;" width="2320" controls src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_17_52_30_504.mp4"></video><figcaption class="wp-element-caption">TexIndex Advanced Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="957" height="1179" src="https://lycos7560.com/wp-content/uploads/2025/02/image-89.png" alt="" class="wp-image-39739" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-89.png 957w, https://lycos7560.com/wp-content/uploads/2025/02/image-89-244x300.png 244w, https://lycos7560.com/wp-content/uploads/2025/02/image-89-768x946.png 768w" sizes="(max-width: 957px) 100vw, 957px" /><figcaption class="wp-element-caption">Brush Strokes Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1892" height="706" src="https://lycos7560.com/wp-content/uploads/2025/02/image-90.png" alt="" class="wp-image-39742" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-90.png 1892w, https://lycos7560.com/wp-content/uploads/2025/02/image-90-300x112.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-90-768x287.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-90-1536x573.png 1536w" sizes="(max-width: 1892px) 100vw, 1892px" /><figcaption class="wp-element-caption">Brush Strokes (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1710" height="1061" src="https://lycos7560.com/wp-content/uploads/2025/02/image-91.png" alt="" class="wp-image-39743" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-91.png 1710w, https://lycos7560.com/wp-content/uploads/2025/02/image-91-300x186.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-91-768x477.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-91-1536x953.png 1536w" sizes="(max-width: 1710px) 100vw, 1710px" /><figcaption class="wp-element-caption">Brush Strokes (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1886" height="273" src="https://lycos7560.com/wp-content/uploads/2025/02/image-93.png" alt="" class="wp-image-39745" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-93.png 1886w, https://lycos7560.com/wp-content/uploads/2025/02/image-93-300x43.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-93-768x111.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-93-1536x222.png 1536w" sizes="(max-width: 1886px) 100vw, 1886px" /><figcaption class="wp-element-caption">Brush Strokes (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1534" height="979" src="https://lycos7560.com/wp-content/uploads/2025/02/image-92.png" alt="" class="wp-image-39744" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-92.png 1534w, https://lycos7560.com/wp-content/uploads/2025/02/image-92-300x191.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-92-768x490.png 768w" sizes="(max-width: 1534px) 100vw, 1534px" /><figcaption class="wp-element-caption">Brush Strokes (4)</figcaption></figure>



<div class="wp-block-file"><a id="wp-block-file--media-99b47eea-ac51-4bd0-a047-0892965818a9" href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Brush.unitypackage">TX_Brush</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Brush.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-99b47eea-ac51-4bd0-a047-0892965818a9">다운로드</a></div>



<figure class="wp-block-video"><video height="1232" style="aspect-ratio: 1944 / 1232;" width="1944" controls src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_15_38_29_761.mp4"></video><figcaption class="wp-element-caption">Brush Strokes Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="773" height="1059" src="https://lycos7560.com/wp-content/uploads/2025/02/image-94.png" alt="" class="wp-image-39747" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-94.png 773w, https://lycos7560.com/wp-content/uploads/2025/02/image-94-219x300.png 219w, https://lycos7560.com/wp-content/uploads/2025/02/image-94-768x1052.png 768w" sizes="(max-width: 773px) 100vw, 773px" /><figcaption class="wp-element-caption">Background Pattern Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1650" height="709" src="https://lycos7560.com/wp-content/uploads/2025/02/image-95.png" alt="" class="wp-image-39748" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-95.png 1650w, https://lycos7560.com/wp-content/uploads/2025/02/image-95-300x129.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-95-768x330.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-95-1536x660.png 1536w" sizes="(max-width: 1650px) 100vw, 1650px" /><figcaption class="wp-element-caption">Background Pattern (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1622" height="991" src="https://lycos7560.com/wp-content/uploads/2025/02/image-96.png" alt="" class="wp-image-39749" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-96.png 1622w, https://lycos7560.com/wp-content/uploads/2025/02/image-96-300x183.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-96-768x469.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-96-1536x938.png 1536w" sizes="(max-width: 1622px) 100vw, 1622px" /><figcaption class="wp-element-caption">Background Pattern (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="1283" src="https://lycos7560.com/wp-content/uploads/2025/02/image-97.jpg" alt="" class="wp-image-39750" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-97.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-97-300x200.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-97-768x513.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-97-1536x1026.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption">Background Pattern (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="874" height="443" src="https://lycos7560.com/wp-content/uploads/2025/02/image-97.png" alt="" class="wp-image-39753" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-97.png 874w, https://lycos7560.com/wp-content/uploads/2025/02/image-97-300x152.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-97-768x389.png 768w" sizes="(max-width: 874px) 100vw, 874px" /><figcaption class="wp-element-caption">TX_Flipbook_Cross / TX_UnityLogo_Pack</figcaption></figure>



<div class="wp-block-file"><a id="wp-block-file--media-ce705eb8-08bf-44f0-a9e7-25222dbae62f" href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Flipbook_CrossTX_UnityLogo_Pack.unitypackage">TX_Flipbook_Cross&amp;TX_UnityLogo_Pack</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Flipbook_CrossTX_UnityLogo_Pack.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-ce705eb8-08bf-44f0-a9e7-25222dbae62f">다운로드</a></div>



<figure class="wp-block-video"><video height="1192" style="aspect-ratio: 2344 / 1192;" width="2344" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_16_29_35_748.mp4"></video><figcaption class="wp-element-caption">Background Pattern Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="802" height="1066" src="https://lycos7560.com/wp-content/uploads/2025/02/image-102.png" alt="" class="wp-image-39763" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-102.png 802w, https://lycos7560.com/wp-content/uploads/2025/02/image-102-226x300.png 226w, https://lycos7560.com/wp-content/uploads/2025/02/image-102-768x1021.png 768w" sizes="(max-width: 802px) 100vw, 802px" /><figcaption class="wp-element-caption">Unity Font Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1538" height="1030" src="https://lycos7560.com/wp-content/uploads/2025/02/image-98.png" alt="" class="wp-image-39757" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-98.png 1538w, https://lycos7560.com/wp-content/uploads/2025/02/image-98-300x201.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-98-768x514.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-98-1536x1029.png 1536w" sizes="(max-width: 1538px) 100vw, 1538px" /><figcaption class="wp-element-caption">Unity Font (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1685" height="1071" src="https://lycos7560.com/wp-content/uploads/2025/02/image-99.png" alt="" class="wp-image-39758" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-99.png 1685w, https://lycos7560.com/wp-content/uploads/2025/02/image-99-300x191.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-99-768x488.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-99-1536x976.png 1536w" sizes="(max-width: 1685px) 100vw, 1685px" /><figcaption class="wp-element-caption">Unity Font (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1736" height="698" src="https://lycos7560.com/wp-content/uploads/2025/02/image-100.png" alt="" class="wp-image-39759" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-100.png 1736w, https://lycos7560.com/wp-content/uploads/2025/02/image-100-300x121.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-100-768x309.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-100-1536x618.png 1536w" sizes="(max-width: 1736px) 100vw, 1736px" /><figcaption class="wp-element-caption">Unity Font (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1066" height="444" src="https://lycos7560.com/wp-content/uploads/2025/02/image-101.png" alt="" class="wp-image-39761" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-101.png 1066w, https://lycos7560.com/wp-content/uploads/2025/02/image-101-300x125.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-101-768x320.png 768w" sizes="(max-width: 1066px) 100vw, 1066px" /><figcaption class="wp-element-caption">TX_Flipbook_Unity</figcaption></figure>



<div class="wp-block-file"><a id="wp-block-file--media-bfe388c7-2813-44c0-b804-a8ea95c651be" href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Flipbook_Unity_Text.unitypackage">TX_Flipbook_Unity_Text</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Flipbook_Unity_Text.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-bfe388c7-2813-44c0-b804-a8ea95c651be">다운로드</a></div>



<figure class="wp-block-video"><video height="1192" style="aspect-ratio: 2344 / 1192;" width="2344" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_16_48_06_307.mp4"></video><figcaption class="wp-element-caption">Unity Font Viedo</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="956" height="1002" src="https://lycos7560.com/wp-content/uploads/2025/02/image-103.png" alt="" class="wp-image-39764" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-103.png 956w, https://lycos7560.com/wp-content/uploads/2025/02/image-103-286x300.png 286w, https://lycos7560.com/wp-content/uploads/2025/02/image-103-768x805.png 768w" sizes="(max-width: 956px) 100vw, 956px" /><figcaption class="wp-element-caption">Cubes Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="853" height="1068" src="https://lycos7560.com/wp-content/uploads/2025/02/image-104.png" alt="" class="wp-image-39765" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-104.png 853w, https://lycos7560.com/wp-content/uploads/2025/02/image-104-240x300.png 240w, https://lycos7560.com/wp-content/uploads/2025/02/image-104-768x962.png 768w" sizes="(max-width: 853px) 100vw, 853px" /><figcaption class="wp-element-caption">Cubes (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1782" height="915" src="https://lycos7560.com/wp-content/uploads/2025/02/image-105.png" alt="" class="wp-image-39766" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-105.png 1782w, https://lycos7560.com/wp-content/uploads/2025/02/image-105-300x154.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-105-768x394.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-105-1536x789.png 1536w" sizes="(max-width: 1782px) 100vw, 1782px" /><figcaption class="wp-element-caption">Cubes (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="2517" height="748" src="https://lycos7560.com/wp-content/uploads/2025/02/image-106.png" alt="" class="wp-image-39767" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-106.png 2517w, https://lycos7560.com/wp-content/uploads/2025/02/image-106-300x89.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-106-768x228.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-106-1536x456.png 1536w, https://lycos7560.com/wp-content/uploads/2025/02/image-106-2048x609.png 2048w" sizes="(max-width: 2517px) 100vw, 2517px" /><figcaption class="wp-element-caption">Cubes (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="531" height="463" src="https://lycos7560.com/wp-content/uploads/2025/02/image-107.png" alt="" class="wp-image-39768" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-107.png 531w, https://lycos7560.com/wp-content/uploads/2025/02/image-107-300x262.png 300w" sizes="(max-width: 531px) 100vw, 531px" /><figcaption class="wp-element-caption">ST_Unity_Cube</figcaption></figure>



<div class="wp-block-file"><a id="wp-block-file--media-7172feb2-4cdd-4a20-b97c-7c1830fcb96c" href="https://lycos7560.com/wp-content/uploads/2025/02/ST_Unity_Cube.unitypackage">ST_Unity_Cube</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/ST_Unity_Cube.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-7172feb2-4cdd-4a20-b97c-7c1830fcb96c">다운로드</a></div>



<figure class="wp-block-image size-full"><img decoding="async" width="1692" height="1073" src="https://lycos7560.com/wp-content/uploads/2025/02/image-108.png" alt="" class="wp-image-39770" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-108.png 1692w, https://lycos7560.com/wp-content/uploads/2025/02/image-108-300x190.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-108-768x487.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-108-1536x974.png 1536w" sizes="(max-width: 1692px) 100vw, 1692px" /><figcaption class="wp-element-caption">SG_Unity_Sketch</figcaption></figure>



<div class="wp-block-file"><a id="wp-block-file--media-0ca3e3fb-502c-42d4-9555-ff36d271c883" href="https://lycos7560.com/wp-content/uploads/2025/02/SG_Unity_Sketch.unitypackage">SG_Unity_Sketch</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/SG_Unity_Sketch.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-0ca3e3fb-502c-42d4-9555-ff36d271c883">다운로드</a></div>



<figure class="wp-block-video"><video height="1172" style="aspect-ratio: 2320 / 1172;" width="2320" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_17_13_12_773.mp4"></video><figcaption class="wp-element-caption">Cubes Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="814" height="1074" src="https://lycos7560.com/wp-content/uploads/2025/02/image-109.png" alt="" class="wp-image-39773" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-109.png 814w, https://lycos7560.com/wp-content/uploads/2025/02/image-109-227x300.png 227w, https://lycos7560.com/wp-content/uploads/2025/02/image-109-768x1013.png 768w" sizes="(max-width: 814px) 100vw, 814px" /><figcaption class="wp-element-caption">Lightning Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1155" height="1013" src="https://lycos7560.com/wp-content/uploads/2025/02/image-110.png" alt="" class="wp-image-39774" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-110.png 1155w, https://lycos7560.com/wp-content/uploads/2025/02/image-110-300x263.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-110-768x674.png 768w" sizes="(max-width: 1155px) 100vw, 1155px" /><figcaption class="wp-element-caption">Lightning (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1552" height="1070" src="https://lycos7560.com/wp-content/uploads/2025/02/image-111.png" alt="" class="wp-image-39775" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-111.png 1552w, https://lycos7560.com/wp-content/uploads/2025/02/image-111-300x207.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-111-768x529.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-111-1536x1059.png 1536w" sizes="(max-width: 1552px) 100vw, 1552px" /><figcaption class="wp-element-caption">Lightning (2)</figcaption></figure>



<div class="wp-block-file"><a id="wp-block-file--media-d1dd35b8-2d8b-43b6-a530-f86ce11dc694" href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Lighting.unitypackage">TX_Lighting</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/TX_Lighting.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-d1dd35b8-2d8b-43b6-a530-f86ce11dc694">다운로드</a></div>



<figure class="wp-block-video"><video height="1172" style="aspect-ratio: 2320 / 1172;" width="2320" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_17_23_47_199.mp4"></video><figcaption class="wp-element-caption">Lightning Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="952" height="1026" src="https://lycos7560.com/wp-content/uploads/2025/02/image-112.png" alt="" class="wp-image-39778" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-112.png 952w, https://lycos7560.com/wp-content/uploads/2025/02/image-112-278x300.png 278w, https://lycos7560.com/wp-content/uploads/2025/02/image-112-768x828.png 768w" sizes="(max-width: 952px) 100vw, 952px" /><figcaption class="wp-element-caption">I Dot Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1254" height="1058" src="https://lycos7560.com/wp-content/uploads/2025/02/image-113.png" alt="" class="wp-image-39779" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-113.png 1254w, https://lycos7560.com/wp-content/uploads/2025/02/image-113-300x253.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-113-768x648.png 768w" sizes="(max-width: 1254px) 100vw, 1254px" /><figcaption class="wp-element-caption">I Dot (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1478" height="624" src="https://lycos7560.com/wp-content/uploads/2025/02/image-114.png" alt="" class="wp-image-39780" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-114.png 1478w, https://lycos7560.com/wp-content/uploads/2025/02/image-114-300x127.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-114-768x324.png 768w" sizes="(max-width: 1478px) 100vw, 1478px" /><figcaption class="wp-element-caption">I Dot (2)</figcaption></figure>



<figure class="wp-block-video"><video height="1172" style="aspect-ratio: 2320 / 1172;" width="2320" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_17_32_30_64.mp4"></video><figcaption class="wp-element-caption">I Dot Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="527" height="971" src="https://lycos7560.com/wp-content/uploads/2025/02/image-115.png" alt="" class="wp-image-39782" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-115.png 527w, https://lycos7560.com/wp-content/uploads/2025/02/image-115-163x300.png 163w" sizes="(max-width: 527px) 100vw, 527px" /><figcaption class="wp-element-caption">Floating Shapes Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="938" height="1039" src="https://lycos7560.com/wp-content/uploads/2025/02/image-116.jpg" alt="" class="wp-image-39783" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-116.jpg 938w, https://lycos7560.com/wp-content/uploads/2025/02/image-116-271x300.jpg 271w, https://lycos7560.com/wp-content/uploads/2025/02/image-116-768x851.jpg 768w" sizes="(max-width: 938px) 100vw, 938px" /><figcaption class="wp-element-caption">Floating Shapes (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1611" height="927" src="https://lycos7560.com/wp-content/uploads/2025/02/image-116.png" alt="" class="wp-image-39784" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-116.png 1611w, https://lycos7560.com/wp-content/uploads/2025/02/image-116-300x173.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-116-768x442.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-116-1536x884.png 1536w" sizes="(max-width: 1611px) 100vw, 1611px" /><figcaption class="wp-element-caption">Floating Shapes (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1609" height="918" src="https://lycos7560.com/wp-content/uploads/2025/02/image-117.png" alt="" class="wp-image-39785" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-117.png 1609w, https://lycos7560.com/wp-content/uploads/2025/02/image-117-300x171.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-117-768x438.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-117-1536x876.png 1536w" sizes="(max-width: 1609px) 100vw, 1609px" /><figcaption class="wp-element-caption">Floating Shapes (3)</figcaption></figure>



<figure class="wp-block-video"><video height="1172" style="aspect-ratio: 2320 / 1172;" width="2320" controls src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_17_45_58_212.mp4"></video></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">15. <strong>Pivot Attribute</strong></h2>



<p><strong>피벗 속성(Pivot Attribute)</strong> 은 <strong>출력 렌더(output render)</strong> 가 <strong>파티클 위치를 기준으로 어디에서 생성되는지</strong> 를 제어합니다.</p>



<p>기본적으로 <strong>피벗은 파티클의 중심(Position)에 위치</strong>하지만, <strong>X, Y, Z 축을 따라 이동(offset)</strong> 시킬 수 있습니다.</p>



<p>피벗을 오프셋하면 <strong>스케일(크기) 조정 및 회전(rotation) 시 보다 매력적인 움직임을 만들 수 있습니다</strong>.</p>



<h3 class="wp-block-heading"><strong><strong>Covered Aspects:</strong></strong></h3>



<ul class="wp-block-list">
<li>Pivot Attribute</li>



<li>Angle Attribute</li>
</ul>



<figure class="wp-block-video"><video height="1172" style="aspect-ratio: 2320 / 1172;" width="2320" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_18_15_21_603.mp4"></video></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="840" height="1302" src="https://lycos7560.com/wp-content/uploads/2025/02/image-118.png" alt="" class="wp-image-39790" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-118.png 840w, https://lycos7560.com/wp-content/uploads/2025/02/image-118-194x300.png 194w, https://lycos7560.com/wp-content/uploads/2025/02/image-118-768x1190.png 768w" sizes="(max-width: 840px) 100vw, 840px" /><figcaption class="wp-element-caption">Pivot Attribute Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1684" height="1159" src="https://lycos7560.com/wp-content/uploads/2025/02/image-119.png" alt="" class="wp-image-39792" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-119.png 1684w, https://lycos7560.com/wp-content/uploads/2025/02/image-119-300x206.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-119-768x529.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-119-1536x1057.png 1536w" sizes="(max-width: 1684px) 100vw, 1684px" /><figcaption class="wp-element-caption">Pivot Attribute (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1595" height="1291" src="https://lycos7560.com/wp-content/uploads/2025/02/image-120.png" alt="" class="wp-image-39793" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-120.png 1595w, https://lycos7560.com/wp-content/uploads/2025/02/image-120-300x243.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-120-768x622.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-120-1536x1243.png 1536w" sizes="(max-width: 1595px) 100vw, 1595px" /><figcaption class="wp-element-caption">Pivot Attribute (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1340" height="406" src="https://lycos7560.com/wp-content/uploads/2025/02/image-121.png" alt="" class="wp-image-39794" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-121.png 1340w, https://lycos7560.com/wp-content/uploads/2025/02/image-121-300x91.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-121-768x233.png 768w" sizes="(max-width: 1340px) 100vw, 1340px" /></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="883" height="410" src="https://lycos7560.com/wp-content/uploads/2025/02/image-122.png" alt="" class="wp-image-39795" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-122.png 883w, https://lycos7560.com/wp-content/uploads/2025/02/image-122-300x139.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-122-768x357.png 768w" sizes="(max-width: 883px) 100vw, 883px" /></figure>



<div class="wp-block-file"><a id="wp-block-file--media-1f95656c-d925-4b94-b321-88cbace793da" href="https://lycos7560.com/wp-content/uploads/2025/02/Pivot-Leaf.unitypackage">Pivot Leaf</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/Pivot-Leaf.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-1f95656c-d925-4b94-b321-88cbace793da">다운로드</a></div>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">16. <strong>Pivot Advanced</strong></h2>



<p>파티클의 <strong>피벗(Pivot)</strong> 을 제어하는 것은 <strong>자연스럽고 흥미로운 움직임을 구현하는 핵심 요소</strong>입니다.</p>



<p>이 VFX에서는 <strong>피벗을 조작하여 꽃잎, 잎사귀, 가시 등이 자연스럽게 배치 및 애니메이션되는 과정</strong>을 보여줍니다.</p>



<p>또한, <strong>Shader Graph와 VFX Graph의 연동을 통해 셰이더를 제어하는 방법</strong>도 시연합니다.</p>



<h3 class="wp-block-heading"><strong><strong>Covered Aspects:</strong></strong></h3>



<ul class="wp-block-list">
<li>Pivot Attribute</li>



<li>Shader Graph integration</li>



<li>Activation Port</li>
</ul>



<figure class="wp-block-video"><video height="1176" style="aspect-ratio: 2336 / 1176;" width="2336" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_24_11_02_22_851.mp4"></video></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1528" height="1014" src="https://lycos7560.com/wp-content/uploads/2025/02/image-125.jpg" alt="" class="wp-image-39805" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-125.jpg 1528w, https://lycos7560.com/wp-content/uploads/2025/02/image-125-300x199.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-125-768x510.jpg 768w" sizes="(max-width: 1528px) 100vw, 1528px" /><figcaption class="wp-element-caption">Pivot Advanced Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1249" height="1920" src="https://lycos7560.com/wp-content/uploads/2025/02/image-123.jpg" alt="" class="wp-image-39802" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-123.jpg 1249w, https://lycos7560.com/wp-content/uploads/2025/02/image-123-195x300.jpg 195w, https://lycos7560.com/wp-content/uploads/2025/02/image-123-768x1181.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-123-999x1536.jpg 999w" sizes="(max-width: 1249px) 100vw, 1249px" /><figcaption class="wp-element-caption">Flower Blossom Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1741" height="1032" src="https://lycos7560.com/wp-content/uploads/2025/02/image-125.png" alt="" class="wp-image-39807" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-125.png 1741w, https://lycos7560.com/wp-content/uploads/2025/02/image-125-300x178.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-125-768x455.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-125-1536x910.png 1536w" sizes="(max-width: 1741px) 100vw, 1741px" /><figcaption class="wp-element-caption">Flower Blossom (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1243" height="986" src="https://lycos7560.com/wp-content/uploads/2025/02/image-126.png" alt="" class="wp-image-39810" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-126.png 1243w, https://lycos7560.com/wp-content/uploads/2025/02/image-126-300x238.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-126-768x609.png 768w" sizes="(max-width: 1243px) 100vw, 1243px" /><figcaption class="wp-element-caption">Flower Blossom (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1106" height="673" src="https://lycos7560.com/wp-content/uploads/2025/02/image-126.jpg" alt="" class="wp-image-39808" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-126.jpg 1106w, https://lycos7560.com/wp-content/uploads/2025/02/image-126-300x183.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-126-768x467.jpg 768w" sizes="(max-width: 1106px) 100vw, 1106px" /><figcaption class="wp-element-caption">Flower Blossom (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1507" height="1024" src="https://lycos7560.com/wp-content/uploads/2025/02/image-127.png" alt="" class="wp-image-39811" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-127.png 1507w, https://lycos7560.com/wp-content/uploads/2025/02/image-127-300x204.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-127-768x522.png 768w" sizes="(max-width: 1507px) 100vw, 1507px" /><figcaption class="wp-element-caption">Flower Blossom (4)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1174" height="1063" src="https://lycos7560.com/wp-content/uploads/2025/02/image-128.png" alt="" class="wp-image-39812" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-128.png 1174w, https://lycos7560.com/wp-content/uploads/2025/02/image-128-300x272.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-128-768x695.png 768w" sizes="(max-width: 1174px) 100vw, 1174px" /><figcaption class="wp-element-caption">SG_PetalBend</figcaption></figure>



<div class="wp-block-file"><a id="wp-block-file--media-92470543-5aa6-4761-8b34-400c76614df8" href="https://lycos7560.com/wp-content/uploads/2025/02/SG_PetalBend.unitypackage">SG_PetalBend</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/SG_PetalBend.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-92470543-5aa6-4761-8b34-400c76614df8">다운로드</a></div>



<figure class="wp-block-image size-full"><img decoding="async" width="1727" height="1536" src="https://lycos7560.com/wp-content/uploads/2025/02/image-123.png" alt="" class="wp-image-39803" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-123.png 1727w, https://lycos7560.com/wp-content/uploads/2025/02/image-123-300x267.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-123-768x683.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-123-1536x1366.png 1536w" sizes="(max-width: 1727px) 100vw, 1727px" /><figcaption class="wp-element-caption">Green Leaf Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="954" height="1044" src="https://lycos7560.com/wp-content/uploads/2025/02/image-129.png" alt="" class="wp-image-39814" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-129.png 954w, https://lycos7560.com/wp-content/uploads/2025/02/image-129-274x300.png 274w, https://lycos7560.com/wp-content/uploads/2025/02/image-129-768x840.png 768w" sizes="(max-width: 954px) 100vw, 954px" /><figcaption class="wp-element-caption">Green Leaf (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="2254" height="1039" src="https://lycos7560.com/wp-content/uploads/2025/02/image-130.png" alt="" class="wp-image-39815" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-130.png 2254w, https://lycos7560.com/wp-content/uploads/2025/02/image-130-300x138.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-130-768x354.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-130-1536x708.png 1536w, https://lycos7560.com/wp-content/uploads/2025/02/image-130-2048x944.png 2048w" sizes="(max-width: 2254px) 100vw, 2254px" /><figcaption class="wp-element-caption">Green Leaf (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="855" height="1573" src="https://lycos7560.com/wp-content/uploads/2025/02/image-124.png" alt="" class="wp-image-39804" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-124.png 855w, https://lycos7560.com/wp-content/uploads/2025/02/image-124-163x300.png 163w, https://lycos7560.com/wp-content/uploads/2025/02/image-124-768x1413.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-124-835x1536.png 835w" sizes="(max-width: 855px) 100vw, 855px" /><figcaption class="wp-element-caption">Spines Graph</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="965" height="1067" src="https://lycos7560.com/wp-content/uploads/2025/02/image-131.png" alt="" class="wp-image-39816" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-131.png 965w, https://lycos7560.com/wp-content/uploads/2025/02/image-131-271x300.png 271w, https://lycos7560.com/wp-content/uploads/2025/02/image-131-768x849.png 768w" sizes="(max-width: 965px) 100vw, 965px" /><figcaption class="wp-element-caption">Spines (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="607" height="689" src="https://lycos7560.com/wp-content/uploads/2025/02/image-132.png" alt="" class="wp-image-39817" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-132.png 607w, https://lycos7560.com/wp-content/uploads/2025/02/image-132-264x300.png 264w" sizes="(max-width: 607px) 100vw, 607px" /><figcaption class="wp-element-caption">Spines (2)</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">17. <strong>Sample Mesh</strong></h2>



<p>이 VFX는 <strong>메시 샘플링(Sample Mesh)</strong> 을 활용하여 <strong>파티클을 메시 표면에 생성</strong> 하고, 메시의 <strong>버텍스 색상(Vertex Color)</strong> 을 <strong>상속</strong> 하는 방법을 보여줍니다.</p>



<p>또한, 메시의 버텍스 색상에 <strong>앰비언트 오클루전(Ambient Occlusion, AO)</strong> 값을 미리 베이크(Bake) 해두었으며, 이를 이용해 <strong>파티클의 색상을 설정</strong> 합니다.</p>



<h3 class="wp-block-heading"><strong><strong>Covered Aspects:</strong></strong></h3>



<ul class="wp-block-list">
<li>Mesh Sampling</li>



<li>Sample Mesh Operator</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-video"><video height="1120" style="aspect-ratio: 1984 / 1120;" width="1984" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_03_05_01_58_06_887.mp4"></video><figcaption class="wp-element-caption">Sample Mesh Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1436" height="1920" src="https://lycos7560.com/wp-content/uploads/2025/02/image-181.jpg" alt="" class="wp-image-39896" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-181.jpg 1436w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-224x300.jpg 224w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-768x1027.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-1149x1536.jpg 1149w" sizes="(max-width: 1436px) 100vw, 1436px" /><figcaption class="wp-element-caption">Sample Mesh Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="1042" src="https://lycos7560.com/wp-content/uploads/2025/02/image-181-1.jpg" alt="" class="wp-image-39897" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-181-1.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-1-300x163.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-1-768x417.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-1-1536x834.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption">Sample Mesh (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1198" height="868" src="https://lycos7560.com/wp-content/uploads/2025/02/image-182-1.jpg" alt="" class="wp-image-39904" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-182-1.jpg 1198w, https://lycos7560.com/wp-content/uploads/2025/02/image-182-1-300x217.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-182-1-768x556.jpg 768w" sizes="(max-width: 1198px) 100vw, 1198px" /><figcaption class="wp-element-caption">Sample Mesh Plane</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="1045" src="https://lycos7560.com/wp-content/uploads/2025/02/image-181-2.jpg" alt="" class="wp-image-39898" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-181-2.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-2-300x163.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-2-768x418.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-2-1536x836.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption">Sample Mesh (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1859" height="498" src="https://lycos7560.com/wp-content/uploads/2025/02/image-181.png" alt="" class="wp-image-39899" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-181.png 1859w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-300x80.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-768x206.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-181-1536x411.png 1536w" sizes="(max-width: 1859px) 100vw, 1859px" /><figcaption class="wp-element-caption">Lion Mesh</figcaption></figure>



<div class="wp-block-file"><a id="wp-block-file--media-1e450586-94e2-4d98-9d7a-0cf1b5b87dc3" href="https://lycos7560.com/wp-content/uploads/2025/02/Lion.unitypackage">Lion</a><a href="https://lycos7560.com/wp-content/uploads/2025/02/Lion.unitypackage" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-1e450586-94e2-4d98-9d7a-0cf1b5b87dc3">다운로드</a></div>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="1763" src="https://lycos7560.com/wp-content/uploads/2025/02/image-182.jpg" alt="" class="wp-image-39902" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-182.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-182-300x275.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-182-768x705.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-182-1536x1410.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption">Sample Mesh (3)</figcaption></figure>



<p></p>



<p></p>



<p></p>



<p></p>



<p></p>



<p></p>



<p></p>



<p></p>



<p></p>



<p></p>



<p></p>
<p>The post <a href="https://lycos7560.com/unity/urp-vfx-learning-templates-2/39699/">URP VFX Learning Templates (2)</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://lycos7560.com/unity/urp-vfx-learning-templates-2/39699/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_07_35_03_551.mp4" length="7021778" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_07_58_26_612.mp4" length="11089805" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_08_13_45_776.mp4" length="7364224" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_08_52_55_798.mp4" length="12897827" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_09_16_43_921.mp4" length="21185407" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_09_31_46_844.mp4" length="4690749" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_15_38_29_761.mp4" length="15542810" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_17_52_30_504.mp4" length="229371564" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_16_29_35_748.mp4" length="44215272" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_16_48_06_307.mp4" length="27463485" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_17_13_12_773.mp4" length="71870864" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_17_23_47_199.mp4" length="36961851" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_17_32_30_64.mp4" length="9428918" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_17_45_58_212.mp4" length="18471538" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_23_18_15_21_603.mp4" length="12531473" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_24_11_02_22_851.mp4" length="27680510" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_03_05_01_58_06_887.mp4" length="14078818" type="video/mp4" />

			</item>
		<item>
		<title>ECS의 World와 SubScene의 관계</title>
		<link>https://lycos7560.com/unity/ecs%ec%9d%98-world%ec%99%80-subscene%ec%9d%98-%ea%b4%80%ea%b3%84/39668/</link>
					<comments>https://lycos7560.com/unity/ecs%ec%9d%98-world%ec%99%80-subscene%ec%9d%98-%ea%b4%80%ea%b3%84/39668/#respond</comments>
		
		<dc:creator><![CDATA[lycos7560]]></dc:creator>
		<pubDate>Wed, 19 Feb 2025 04:52:42 +0000</pubDate>
				<category><![CDATA[Unity]]></category>
		<category><![CDATA[Archetype]]></category>
		<category><![CDATA[Archetypes]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[Component]]></category>
		<category><![CDATA[ComponentBased]]></category>
		<category><![CDATA[ComponentData]]></category>
		<category><![CDATA[Container]]></category>
		<category><![CDATA[DataContainer]]></category>
		<category><![CDATA[DataManagement]]></category>
		<category><![CDATA[DataOriented]]></category>
		<category><![CDATA[DataStructure]]></category>
		<category><![CDATA[DOTS]]></category>
		<category><![CDATA[ECS]]></category>
		<category><![CDATA[Entity]]></category>
		<category><![CDATA[EntityManager]]></category>
		<category><![CDATA[EntityQuery]]></category>
		<category><![CDATA[EntityState]]></category>
		<category><![CDATA[EntitySystem]]></category>
		<category><![CDATA[GameEngine]]></category>
		<category><![CDATA[GameObject]]></category>
		<category><![CDATA[Query]]></category>
		<category><![CDATA[QuerySystem]]></category>
		<category><![CDATA[Scene]]></category>
		<category><![CDATA[SceneManagement]]></category>
		<category><![CDATA[SceneSystem]]></category>
		<category><![CDATA[StateManagement]]></category>
		<category><![CDATA[study]]></category>
		<category><![CDATA[SubScene]]></category>
		<category><![CDATA[System]]></category>
		<category><![CDATA[SystemBase]]></category>
		<category><![CDATA[World]]></category>
		<category><![CDATA[WorldState]]></category>
		<category><![CDATA[WorldSystem]]></category>
		<category><![CDATA[공부]]></category>
		<guid isPermaLink="false">https://lycos7560.com/?p=39668</guid>

					<description><![CDATA[<p>⭐ 개념 정리 ✅ World ECS에서 World는 Entity와 System 등을 관리하는 Container 역할 World는 특정 씬(Scene)에 종속되지 않고, 모든 ECS 데이터를 포함하여 관리한다. World가 관리하는 핵심 구성 요소 4가지 ✅ SubScene SubScene은 씬(Scene) 내부에서 특정 ECS 데이터(Entity)를 포함하는 컨테이너 역할을 한다. SubScene이 로드되면, 그 안의 GameObject들이 자동으로 Entity로 변환(Entity Conversion)되어 World에 등록 ➡️ SubScene의 로드 [&#8230;]</p>
<p>The post <a href="https://lycos7560.com/unity/ecs%ec%9d%98-world%ec%99%80-subscene%ec%9d%98-%ea%b4%80%ea%b3%84/39668/">ECS의 World와 SubScene의 관계</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></description>
										<content:encoded><![CDATA[				<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-4370eae9      "
					data-scroll= "1"
					data-offset= "30"
					style=""
				>
				<div class="uagb-toc__wrap">
						<div class="uagb-toc__title">
							ECS의 World와 SubScene의 관계						</div>
																						<div class="uagb-toc__list-wrap ">
						<ol class="uagb-toc__list"><li class="uagb-toc__list"><a href="#개념-정리" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b50.png" alt="⭐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 개념 정리</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#world" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> World</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#subscene" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> SubScene</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#subscene의-로드-과정" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> SubScene의 로드 과정</a></li></ul><li class="uagb-toc__list"><a href="#world와-subscene의-관계" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> World와 SubScene의 관계</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#world는-subscene을-포함하는-상위-컨테이너인가" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2753.png" alt="❓" class="wp-smiley" style="height: 1em; max-height: 1em;" /> World는 SubScene을 포함하는 상위 컨테이너인가?</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#서로-다른-world에서-같은-subscene을-공유할-수-있을까" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2753.png" alt="❓" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 서로 다른 World에서 같은 SubScene을 공유할 수 있을까?</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#서로-다른-world에서-같은-subscene을-공유하는-방법" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 서로 다른 World에서 같은 SubScene을 공유하는 방법</a></li></ul><li class="uagb-toc__list"><a href="#subscene-내의-entity들이-서로-다른-world에-포함될-수-있을까" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2753.png" alt="❓" class="wp-smiley" style="height: 1em; max-height: 1em;" />SubScene 내의 Entity들이 서로 다른 World에 포함될 수 있을까?</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#일반적인-subscene의-world-포함-방식" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 일반적인 SubScene의 World 포함 방식</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#특정-entity만-다른-world에-포함시키는-방법" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 특정 Entity만 다른 World에 포함시키는 방법</a></ul></ul></ol>					</div>
									</div>
				</div>
			


<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b50.png" alt="⭐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 개념 정리</h2>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> World</h3>



<p><code><strong>ECS</strong></code>에서<code> <strong>World</strong></code>는 <code><strong>Entity</strong></code>와 <code><strong>System</strong></code> 등을 관리하는 Container 역할</p>



<p><code><strong>World</strong></code>는 <strong>특정 씬(Scene)에 종속되지 않고</strong>, 모든 ECS 데이터를 포함하여 관리한다.</p>



<p><code><strong>World</strong></code>가 관리하는 핵심 구성 요소 4가지</p>



<ul class="wp-block-list">
<li><strong><code>EntityManager</code></strong> → <code><strong>Entity</strong></code>와 <strong><code>Component</code></strong>관리</li>



<li><strong><code>Systems</code></strong> → ECS 시스템 실행 및 업데이트</li>



<li><strong><code>Archetypes</code></strong> → <code><strong>Entity</strong></code> 구조 저장 및 관리</li>



<li><strong><code>Queries</code></strong> → 특정 조건을 만족하는 <code><strong>Entity</strong></code> 검색</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> SubScene</h3>



<p><code><strong>SubScene</strong></code>은 씬(Scene) 내부에서 특정 ECS 데이터(<code><strong>Entity</strong></code>)를 포함하는 컨테이너 역할을 한다.</p>



<p><code><strong>SubScene</strong></code>이 로드되면, 그 안의 GameObject들이 자동으로 <code><strong>Entity</strong></code>로 변환(Entity Conversion)되어 <code><code><strong>World</strong></code></code>에 등록</p>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> SubScene의 로드 과정</h4>



<ol class="wp-block-list">
<li> <strong><code><strong>SubScene</strong></code></strong> <strong>로드</strong> → <code><strong>SceneSystem</strong></code>이 <code><strong>SubScene</strong></code>을 <code><code><strong>World</strong></code></code>에 추가</li>



<li>GameObject <strong>→ <code><strong>Entity</strong></code> </strong>변환</li>



<li>EntityManager가 모든 <strong><code>Entity</code> </strong>관리</li>



<li>ECS 시스템이 해당 <strong><code>Entity</code> </strong>를 처리</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> World와 SubScene의 관계</h3>



<p><code><code><strong>World</strong></code></code>는 <strong><code><strong>MainScene</strong></code></strong>과 <strong><code><strong>SubScene</strong></code></strong>을 구분하지 않고, 모든 ECS 데이터를 포함하여 관리</p>



<p><strong><code><strong>SubScene</strong></code></strong>이 로드되면 해당 오브젝트들이 ECS <strong><code>Entity</code></strong>로 변환되어 <code><code><code><code><code><strong>World</strong></code></code></code></code></code>에 등록됨</p>



<p><strong><code><code>World</code></code> </strong>자체는 <strong>씬(Scene)</strong>을 직접적으로 관리하지 않지만, <strong><code><code>World</code></code></strong>가 관리하는 <code><strong>SceneSystem</strong></code>을 사용해 <strong><code><strong>SubScene</strong></code></strong>을 동적으로 로드/언로드할 수는 있음</p>



<p><strong>즉, <code><code>World</code></code> 는 씬(Scene) 개념과 독립적이지만, <code>SubScene</code>과는 밀접한 관계를 가짐</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2753.png" alt="❓" class="wp-smiley" style="height: 1em; max-height: 1em;" /> World는 SubScene을 포함하는 상위 컨테이너인가?</h3>



<p>Yes, 하지만 직접적인 포함 관계는 아님</p>



<p><strong><code><code>World</code></code></strong>는 <strong>ECS 데이터를 관리하는 컨테이너</strong>이므로, <strong><code><strong>SubScene</strong></code></strong>에서 생성된 ECS 데이터(<code><strong>Entity</strong></code>, <code><strong>Component</strong></code>, <code><strong>System </strong></code>등)는 <strong>결국 <strong><code><code>World</code></code></strong>에 포함됨</strong>.</p>



<p>하지만, <strong>Unity의 <strong><code><strong>SubScene</strong></code></strong>자체가 World의 일부는 아니다</strong>. (<strong><code><strong>SubScene</strong></code></strong>은 <strong><strong>씬(Scene)</strong>의 일부</strong>, World는 <strong>ECS의 컨테이너</strong>)</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2753.png" alt="❓" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 서로 다른 World에서 같은 SubScene을 공유할 수 있을까?</h3>



<p>일반적으로 Unity ECS에서는 <strong><strong><strong><code>SubScene</code></strong></strong>은 하나의 <strong><code><strong>World</strong></code></strong>에 속하는 것이 원칙</strong></p>



<p>특정한 방식으로 <strong>다른 <code><strong>World</strong></code>에서 동일한 <strong><code>SubScene</code></strong>을 공유하는 것</strong>도 가능할 수 있음</p>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 서로 다른 World에서 같은 SubScene을 공유하는 방법</h4>



<h5 class="wp-block-heading">1. 각 World에서 같은 SubScene을 개별적으로 로드</h5>



<ul class="wp-block-list">
<li>각 <code><strong>World</strong></code>가 동일한 <strong><code>SubScene</code></strong>을 독립적으로 로드하여 각각의 ECS 데이터를 가질 수 있음</li>



<li>서로 다른 <code><strong>World</strong></code>에 있지만, 동일한 형태의 ECS 데이터가 생성</li>
</ul>



<h5 class="wp-block-heading">2. Persistent Scene을 활용해 한 World에서 로드한 데이터를 다른 World가 참조</h5>



<ul class="wp-block-list">
<li>한 <code><strong>World</strong></code>에서 <strong><code>SubScene</code></strong>을 로드하고, 다른 <code><strong>World</strong></code>는 해당 데이터를 복사하거나 참조하도록 설계</li>



<li>예를 들어, 멀티플레이어 게임에서 서버 <code><strong>World</strong></code>와 클라이언트 <code><strong>World</strong></code>가 동일한 맵 데이터(<strong><code>SubScene</code></strong>)를 참조하는 방식</li>



<li>하지만, Unity ECS가 기본적으로 제공하는 기능은 아니므로 별도의 데이터 동기화 로직이 필요함.</li>
</ul>



<h5 class="wp-block-heading">3. Bake 시점에 SubScene의 ECS 데이터를 여러 World로 복사</h5>



<ul class="wp-block-list">
<li><strong><code>SubScene</code></strong>이 변환될 때(<code><strong>Bake</strong></code>), ECS 데이터를 특정 World가 아니라 <strong>여러 <code><strong>World</strong></code>에 분산해서 배치하는 방식</strong>도 가능</li>



<li><code><strong>EntityManager.CopyEntitiesFrom()</strong></code> 등을 사용하여 <strong><strong><code>SubScene</code></strong>의 데이터를 한 <strong><code><code>World</code></code></strong>에서 다른 <strong><code><code>World</code></code></strong>로 복사 가능</strong>.</li>



<li>Unity ECS가 기본적으로 지원하는 기능이 아니므로, 수동으로 구현해야 할 수도 있음.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2753.png" alt="❓" class="wp-smiley" style="height: 1em; max-height: 1em;" />SubScene 내의 Entity들이 서로 다른 World에 포함될 수 있을까?</h3>



<p>Yes, 하지만 Unity ECS에서 기본적으로 지원하는 방식은 아님</p>



<p>특정한 방법을 사용하면 일부 <code><strong>Entity</strong></code>를 다른 <code><strong>World</strong></code>로 이동시키는 것은 가능함</p>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 일반적인 SubScene의 World 포함 방식</h4>



<p>기본적으로 <strong><code>SubScene</code></strong>이 로드되면, 그 안의 모든 GameObject가 동일한 <code><strong>World</strong></code>로 변환(<strong><code>Bake</code></strong>)됨</p>



<p>즉, <strong>SubScene </strong>내의 모든 <code><strong>Entity</strong></code>들은 한 개의 <code><strong>World</strong></code>에 속하는 것이 원칙</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 예제: 일반적인 <strong><code>SubScene</code></strong> 로드 과정</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">SceneSystem.LoadSceneAsync(world, subSceneEntity, loadParameters);</pre>



<p>특정 <strong><code><strong>World</strong></code></strong>에서 <strong><code>SubScene</code></strong>을 로드함 → <strong><code>SubScene</code></strong> 내부의 <code><strong>Entity</strong></code>들이 해당 <code><strong>World</strong></code>에 포함됨</p>



<p>결과적으로 <strong><code>SubScene</code></strong>의 모든 <code><strong>Entity</strong></code>들은 동일한 <code><strong>World</strong></code>에 속하게 됨</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 특정 Entity만 다른 World에 포함시키는 방법</h4>



<p>하지만, 특정한 방식으로 <strong><code>SubScene</code></strong> 내부의 <code><strong>Entity</strong></code>를 다른 World로 이동시키는 것도 가능</p>



<h5 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" />방법 1: 특정 Entity를 다른 World로 복사하기</h5>



<p><strong><code>SubScene</code></strong>이 로드된 후, 특정 <code><strong>Entity</strong></code>를 <strong>다른 <code><strong>World</strong></code>로 복사</strong>하는 방식</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 현재 World에서 Entity 가져오기
EntityManager entityManager = sourceWorld.EntityManager;
EntityQuery query = entityManager.CreateEntityQuery(ComponentType.ReadOnly&lt;MyComponent>());

// 대상 World로 Entity 복사
EntityManager destinationManager = targetWorld.EntityManager;
NativeArray&lt;Entity> entities = query.ToEntityArray(Allocator.Temp);
foreach (var entity in entities)
{
    Entity newEntity = destinationManager.Instantiate(entity);
}
entities.Dispose();
</pre>



<ul class="wp-block-list">
<li>원본 <code><strong>Entity</strong></code>를 삭제하지 않으면 동일한 <code><strong>Entity</strong></code>가 두 개의 <strong><code><strong>World</strong></code></strong>에 존재할 수도 있음! → 원본을 삭제할지 여부를 잘 결정해야 함</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" />방법 2: SubScene을 특정 World에서 로드한 후 일부 Entity만 다른 World에서 활용</h5>



<ul class="wp-block-list">
<li><strong><code>SubScene</code></strong>을 <strong><code>World A</code>에서 로드</strong></li>



<li>특정 <code><strong>Entity</strong></code>를 <code><strong>World</strong></code><strong><code> B</code></strong>에서 참조할 수 있도록 설계</li>



<li><strong><code>EntityCommandBuffer</code> </strong>또는 <code><strong>CopyEntitiesFrom</strong></code>을 활용하여 데이터 이동 가능</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">targetWorld.EntityManager.CopyEntitiesFrom(sourceWorld.EntityManager, query);
</pre>



<ul class="wp-block-list">
<li>하지만, 시스템(System)과 동작 방식이 달라질 수 있으므로 주의해야 함</li>
</ul>



<p></p>
<p>The post <a href="https://lycos7560.com/unity/ecs%ec%9d%98-world%ec%99%80-subscene%ec%9d%98-%ea%b4%80%ea%b3%84/39668/">ECS의 World와 SubScene의 관계</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://lycos7560.com/unity/ecs%ec%9d%98-world%ec%99%80-subscene%ec%9d%98-%ea%b4%80%ea%b3%84/39668/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>URP VFX Learning Templates (1)</title>
		<link>https://lycos7560.com/unity/urp-vfx-learning-templates-1/39596/</link>
					<comments>https://lycos7560.com/unity/urp-vfx-learning-templates-1/39596/#comments</comments>
		
		<dc:creator><![CDATA[lycos7560]]></dc:creator>
		<pubDate>Tue, 18 Feb 2025 04:12:05 +0000</pubDate>
				<category><![CDATA[Unity]]></category>
		<category><![CDATA[Alpha Blending]]></category>
		<category><![CDATA[Compute Shader]]></category>
		<category><![CDATA[Flipbook Animation]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Motion Vectors]]></category>
		<category><![CDATA[Noise Texture]]></category>
		<category><![CDATA[Particle System]]></category>
		<category><![CDATA[Real-time FX]]></category>
		<category><![CDATA[Rendering Tricks]]></category>
		<category><![CDATA[Templates]]></category>
		<category><![CDATA[TUTORIAL]]></category>
		<category><![CDATA[Unity Docs]]></category>
		<category><![CDATA[Unity Shader]]></category>
		<category><![CDATA[Unity VFX Graph]]></category>
		<category><![CDATA[URP]]></category>
		<category><![CDATA[URP (Universal Render Pipeline)]]></category>
		<category><![CDATA[VFX]]></category>
		<category><![CDATA[VFX (Visual Effects)]]></category>
		<category><![CDATA[VFX Techniques]]></category>
		<guid isPermaLink="false">https://lycos7560.com/?p=39596</guid>

					<description><![CDATA[<p>URP_VFX_Learning_Templates https://docs.unity3d.com/Packages/com.unity.visualeffectgraph@17.0/manual/index.html 1. Context&#38;Flow 컨텍스트 및 데이터 흐름 VFX Graph에서 데이터 흐름이 어떻게 구성되는지 설명하고, 자주 사용되는 컨텍스트 블록을 개요로 제공 Covered Aspects: 2. Spawn Context 이 VFX는 스폰 컨텍스트(Spawn Context) 와 관련된 정보를 제공하기 위한 것입니다. 스폰 컨텍스트란 무엇이며, Inspector에서 어떤 옵션을 설정할 수 있는지, 그리고 추가적으로 다음과 같은 정보를 포함합니다: Covered Aspects: • [&#8230;]</p>
<p>The post <a href="https://lycos7560.com/unity/urp-vfx-learning-templates-1/39596/">URP VFX Learning Templates (1)</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></description>
										<content:encoded><![CDATA[				<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-303fb734      "
					data-scroll= "1"
					data-offset= "30"
					style=""
				>
				<div class="uagb-toc__wrap">
						<div class="uagb-toc__title">
							목차						</div>
																						<div class="uagb-toc__list-wrap ">
						<ol class="uagb-toc__list"><li class="uagb-toc__list"><a href="#urp-vfx-learning-templates" class="uagb-toc-link__trigger">URP_VFX_Learning_Templates</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-contextflow" class="uagb-toc-link__trigger">1. Context&amp;Flow</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#2-spawn-context" class="uagb-toc-link__trigger">2. Spawn Context</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#3-capacity-count" class="uagb-toc-link__trigger">3. Capacity Count</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#4-multiple-outputs" class="uagb-toc-link__trigger">4. Multiple Outputs</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#5-bounds" class="uagb-toc-link__trigger">5. Bounds</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#6-orient-face-camera" class="uagb-toc-link__trigger">6. Orient Face Camera</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#7-orient-fixed-axis" class="uagb-toc-link__trigger">7. Orient Fixed Axis</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#8-orient-advanced" class="uagb-toc-link__trigger">8. Orient Advanced</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#9-rotation-angle" class="uagb-toc-link__trigger">9. Rotation &amp; Angle</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#10-falling-coins" class="uagb-toc-link__trigger">10. Falling Coins</a></ul></ol>					</div>
									</div>
				</div>
			


<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Unity 6 - 6000.0.32f1
Visual Effect Graph - 17.0.3</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h1 class="wp-block-heading">URP_VFX_Learning_Templates</h1>



<p><a href="https://docs.unity3d.com/Packages/com.unity.visualeffectgraph@17.0/manual/index.html" target="_blank" rel="noreferrer noopener">https://docs.unity3d.com/Packages/com.unity.visualeffectgraph@17.0/manual/index.html</a></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">1. Context&amp;Flow</h2>



<p><strong>컨텍스트 및 데이터 흐름</strong></p>



<p>VFX Graph에서 <strong>데이터 흐름</strong>이 어떻게 구성되는지 설명하고, 자주 사용되는 <strong>컨텍스트 블록</strong>을 개요로 제공</p>



<h3 class="wp-block-heading"><strong><strong>Covered Aspects:</strong></strong></h3>



<ul class="wp-block-list">
<li>Data Flow (데이터 흐름)</li>



<li>Context Block (컨텍스트 블록)</li>
</ul>



<figure class="wp-block-video"><video height="932" style="aspect-ratio: 2048 / 932;" width="2048" controls src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_16_18_09_41_580.mp4"></video><figcaption class="wp-element-caption">Context&amp;Flow Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="919" height="1920" src="https://lycos7560.com/wp-content/uploads/2025/02/image-36.jpg" alt="" class="wp-image-39610" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-36.jpg 919w, https://lycos7560.com/wp-content/uploads/2025/02/image-36-144x300.jpg 144w, https://lycos7560.com/wp-content/uploads/2025/02/image-36-768x1605.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-36-735x1536.jpg 735w" sizes="(max-width: 919px) 100vw, 919px" /><figcaption class="wp-element-caption">Context&amp;Flow Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1421" height="839" src="https://lycos7560.com/wp-content/uploads/2025/02/image-36.png" alt="" class="wp-image-39611" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-36.png 1421w, https://lycos7560.com/wp-content/uploads/2025/02/image-36-300x177.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-36-768x453.png 768w" sizes="(max-width: 1421px) 100vw, 1421px" /><figcaption class="wp-element-caption">Context&amp;Flow (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1406" height="948" src="https://lycos7560.com/wp-content/uploads/2025/02/image-37.png" alt="" class="wp-image-39612" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-37.png 1406w, https://lycos7560.com/wp-content/uploads/2025/02/image-37-300x202.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-37-768x518.png 768w" sizes="(max-width: 1406px) 100vw, 1406px" /><figcaption class="wp-element-caption">Context&amp;Flow (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1351" height="499" src="https://lycos7560.com/wp-content/uploads/2025/02/image-38.png" alt="" class="wp-image-39613" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-38.png 1351w, https://lycos7560.com/wp-content/uploads/2025/02/image-38-300x111.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-38-768x284.png 768w" sizes="(max-width: 1351px) 100vw, 1351px" /><figcaption class="wp-element-caption">Context&amp;Flow (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1273" height="963" src="https://lycos7560.com/wp-content/uploads/2025/02/image-39.png" alt="" class="wp-image-39614" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-39.png 1273w, https://lycos7560.com/wp-content/uploads/2025/02/image-39-300x227.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-39-768x581.png 768w" sizes="(max-width: 1273px) 100vw, 1273px" /><figcaption class="wp-element-caption">Context&amp;Flow (4)</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">2. Spawn Context</h2>



<p>이 VFX는 <strong>스폰 컨텍스트(Spawn Context)</strong> 와 관련된 정보를 제공하기 위한 것입니다.</p>



<p><strong>스폰 컨텍스트란 무엇이며</strong>, Inspector에서 어떤 옵션을 설정할 수 있는지, 그리고 추가적으로 다음과 같은 정보를 포함합니다:</p>



<ul class="wp-block-list">
<li>스폰 이벤트 속성(Spawn Event Attributes)이란 무엇인가?</li>



<li>스폰 이벤트 속성을 어떻게 설정하는가?</li>



<li>스폰 상태 연산자(Spawn State Operator)란 무엇인가?</li>
</ul>



<h3 class="wp-block-heading"><strong><strong>Covered Aspects:</strong></strong></h3>



<p>• Spawn Context<br>• Spawn Event Attributes<br>• Spawn State</p>



<figure class="wp-block-video"><video height="912" style="aspect-ratio: 1632 / 912;" width="1632" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_17_06_12_55_147.mp4"></video><figcaption class="wp-element-caption">Spawn Context Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1275" height="1920" src="https://lycos7560.com/wp-content/uploads/2025/02/image-33.jpg" alt="" class="wp-image-39604" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-33.jpg 1275w, https://lycos7560.com/wp-content/uploads/2025/02/image-33-199x300.jpg 199w, https://lycos7560.com/wp-content/uploads/2025/02/image-33-768x1157.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-33-1020x1536.jpg 1020w" sizes="(max-width: 1275px) 100vw, 1275px" /><figcaption class="wp-element-caption">Spawn Context Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1533" height="794" src="https://lycos7560.com/wp-content/uploads/2025/02/image-33.png" alt="" class="wp-image-39605" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-33.png 1533w, https://lycos7560.com/wp-content/uploads/2025/02/image-33-300x155.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-33-768x398.png 768w" sizes="(max-width: 1533px) 100vw, 1533px" /><figcaption class="wp-element-caption">Spawn Context (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1544" height="770" src="https://lycos7560.com/wp-content/uploads/2025/02/image-34.png" alt="" class="wp-image-39606" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-34.png 1544w, https://lycos7560.com/wp-content/uploads/2025/02/image-34-300x150.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-34-768x383.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-34-1536x766.png 1536w" sizes="(max-width: 1544px) 100vw, 1544px" /><figcaption class="wp-element-caption">Spawn Context (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1387" height="743" src="https://lycos7560.com/wp-content/uploads/2025/02/image-35.png" alt="" class="wp-image-39608" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-35.png 1387w, https://lycos7560.com/wp-content/uploads/2025/02/image-35-300x161.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-35-768x411.png 768w" sizes="(max-width: 1387px) 100vw, 1387px" /><figcaption class="wp-element-caption">Spawn Context (3)</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">3. <strong>Capacity Count</strong></h2>



<p>Capacity Count는 시스템의 <strong>파티클 메모리 할당(Memory allocation)</strong>에 사용됩니다. </p>



<p>이 값을 증가시키면 할당되는 메모리 양도 증가합니다.</p>



<p>이 용량은 <strong>최대 활성 입자 수(Max active particles)</strong> 로 볼 수 있습니다.</p>



<p>최대 살아있는 파티클 수에 최대한 가깝게 이 값을 설정하는 것이 좋은 방법입니다.</p>



<p>이 VFX는 <strong>Capacity가 무엇인지</strong>, 그리고 <strong>VFX Control을 사용하여 Capacity를 설정하는 방법</strong>을 설명합니다.</p>



<h3 class="wp-block-heading"><strong>Covered Aspects:</strong></h3>



<p>• <strong>Capacity</strong><br>• <strong>Memory allocation</strong><br>• <strong>VFX Control</strong></p>



<figure class="wp-block-video"><video height="912" style="aspect-ratio: 1632 / 912;" width="1632" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_17_05_30_00_46.mp4"></video><figcaption class="wp-element-caption">Capacity Count Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1348" height="1920" src="https://lycos7560.com/wp-content/uploads/2025/02/image-31.jpg" alt="" class="wp-image-39597" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-31.jpg 1348w, https://lycos7560.com/wp-content/uploads/2025/02/image-31-211x300.jpg 211w, https://lycos7560.com/wp-content/uploads/2025/02/image-31-768x1094.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-31-1078x1536.jpg 1078w" sizes="(max-width: 1348px) 100vw, 1348px" /><figcaption class="wp-element-caption">Capacity Count Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1359" height="1012" src="https://lycos7560.com/wp-content/uploads/2025/02/image-31.png" alt="" class="wp-image-39600" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-31.png 1359w, https://lycos7560.com/wp-content/uploads/2025/02/image-31-300x223.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-31-768x572.png 768w" sizes="(max-width: 1359px) 100vw, 1359px" /><figcaption class="wp-element-caption">Capacity Count (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1549" height="899" src="https://lycos7560.com/wp-content/uploads/2025/02/image-32.png" alt="" class="wp-image-39601" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-32.png 1549w, https://lycos7560.com/wp-content/uploads/2025/02/image-32-300x174.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-32-768x446.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-32-1536x891.png 1536w" sizes="(max-width: 1549px) 100vw, 1549px" /><figcaption class="wp-element-caption">Capacity Count (2)</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">4. Multiple Outputs</h2>



<ul class="wp-block-list">
<li><strong>출력(Context)에서 파티클을 렌더링하는 방식</strong>을 정의.</li>



<li>하나의 파티클 시스템에서 <strong>여러 개의 출력(Renderer)을 추가</strong>하여 다양한 표현 가능.</li>



<li>예: <strong>빌보드 쿼드, 메시, 포인트, 데칼 등</strong>을 활용해 입자를 여러 방식으로 렌더링 가능.</li>
</ul>



<h3 class="wp-block-heading"><strong>Covered Aspects:</strong></h3>



<ul class="wp-block-list">
<li><strong>Composition Mode (속성 조합 모드)</strong></li>



<li><strong>Output Context (출력 컨텍스트)</strong></li>
</ul>



<figure class="wp-block-video"><video height="1176" style="aspect-ratio: 2520 / 1176;" width="2520" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_17_08_00_48_775.mp4"></video><figcaption class="wp-element-caption">Multiple Outputs Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1322" height="2028" src="https://lycos7560.com/wp-content/uploads/2025/02/image-40.png" alt="" class="wp-image-39615" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-40.png 1322w, https://lycos7560.com/wp-content/uploads/2025/02/image-40-196x300.png 196w, https://lycos7560.com/wp-content/uploads/2025/02/image-40-768x1178.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-40-1001x1536.png 1001w" sizes="(max-width: 1322px) 100vw, 1322px" /><figcaption class="wp-element-caption">Multiple Outputs Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1484" height="969" src="https://lycos7560.com/wp-content/uploads/2025/02/image-41.png" alt="" class="wp-image-39617" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-41.png 1484w, https://lycos7560.com/wp-content/uploads/2025/02/image-41-300x196.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-41-768x501.png 768w" sizes="(max-width: 1484px) 100vw, 1484px" /><figcaption class="wp-element-caption">Multiple Outputs (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1275" height="1044" src="https://lycos7560.com/wp-content/uploads/2025/02/image-42.png" alt="" class="wp-image-39618" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-42.png 1275w, https://lycos7560.com/wp-content/uploads/2025/02/image-42-300x246.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-42-768x629.png 768w" sizes="(max-width: 1275px) 100vw, 1275px" /><figcaption class="wp-element-caption">Multiple Outputs (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="988" src="https://lycos7560.com/wp-content/uploads/2025/02/image-43.jpg" alt="" class="wp-image-39619" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-43.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-43-300x154.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-43-768x395.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-43-1536x790.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption">Multiple Outputs (3)</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">5. Bounds</h2>



<ul class="wp-block-list">
<li>Bounds(바운딩 박스)는 VFX가 <strong>카메라의 프러스텀(FOV) 안에 있을 때만 렌더링</strong>되도록 함.</li>



<li>바운드는 <strong>수동(Manual), 기록(Recorded), 자동(Automatic)으로 설정 가능</strong>.</li>



<li>컬링(Culling)을 활용하여 <strong>불필요한 연산을 줄여 성능 최적화</strong> 가능.</li>
</ul>



<figure class="wp-block-image size-full"><img decoding="async" width="268" height="254" src="https://lycos7560.com/wp-content/uploads/2025/02/image-43.png" alt="" class="wp-image-39621"/></figure>



<h3 class="wp-block-heading"><strong>Covered Aspects:</strong></h3>



<ul class="wp-block-list">
<li><strong><strong>Bounds (바운드, 바운딩 박스 설정)</strong></strong></li>



<li><strong><strong>Culling (컬링, 최적화 기법)</strong></strong></li>
</ul>



<figure class="wp-block-video"><video height="932" style="aspect-ratio: 2336 / 932;" width="2336" controls src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_17_20_23_53_961.mp4"></video><figcaption class="wp-element-caption">Bounds Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1404" height="1920" src="https://lycos7560.com/wp-content/uploads/2025/02/image-44.jpg" alt="" class="wp-image-39623" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-44.jpg 1404w, https://lycos7560.com/wp-content/uploads/2025/02/image-44-219x300.jpg 219w, https://lycos7560.com/wp-content/uploads/2025/02/image-44-768x1050.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-44-1123x1536.jpg 1123w" sizes="(max-width: 1404px) 100vw, 1404px" /><figcaption class="wp-element-caption">Bounds Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1196" height="1046" src="https://lycos7560.com/wp-content/uploads/2025/02/image-44.png" alt="" class="wp-image-39624" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-44.png 1196w, https://lycos7560.com/wp-content/uploads/2025/02/image-44-300x262.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-44-768x672.png 768w" sizes="(max-width: 1196px) 100vw, 1196px" /><figcaption class="wp-element-caption">Bounds (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1397" height="1279" src="https://lycos7560.com/wp-content/uploads/2025/02/image-46.png" alt="" class="wp-image-39628" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-46.png 1397w, https://lycos7560.com/wp-content/uploads/2025/02/image-46-300x275.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-46-768x703.png 768w" sizes="(max-width: 1397px) 100vw, 1397px" /><figcaption class="wp-element-caption">Bounds (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1564" height="757" src="https://lycos7560.com/wp-content/uploads/2025/02/image-45.png" alt="" class="wp-image-39626" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-45.png 1564w, https://lycos7560.com/wp-content/uploads/2025/02/image-45-300x145.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-45-768x372.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-45-1536x743.png 1536w" sizes="(max-width: 1564px) 100vw, 1564px" /><figcaption class="wp-element-caption">Bounds (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1453" height="921" src="https://lycos7560.com/wp-content/uploads/2025/02/image-47.png" alt="" class="wp-image-39630" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-47.png 1453w, https://lycos7560.com/wp-content/uploads/2025/02/image-47-300x190.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-47-768x487.png 768w" sizes="(max-width: 1453px) 100vw, 1453px" /><figcaption class="wp-element-caption">Bounds (4)</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">6. Orient Face Camera</h2>



<p>출력이 <strong>쿼드(Quad), 메시(Mesh), 스트립(Strip)</strong> 등으로 설정된 경우, 우리는 종종 파티클의 기하학적 형태(Geometry)가 어떻게 배치되는지 제어해야 합니다.</p>



<p>파티클이 <strong>카메라를 바라보아야 할까요?</strong> 파티클의 <strong>전방(Forward) 방향과 위쪽(Up) 방향은 무엇일까요?</strong></p>



<p><code>Orient</code> 블록을 사용하면 다양한 모드를 통해 <strong>파티클의 방향을 쉽게 제어</strong>할 수 있습니다.</p>



<p>해당 예제는 <strong>&#8220;Face Camera Position&#8221;</strong> 모드를 사용하여 <strong>입자가 항상 카메라의 위치를 바라보도록 설정</strong>하였습니다.</p>



<h3 class="wp-block-heading"><strong>Covered Aspects:</strong></h3>



<ul class="wp-block-list">
<li><strong><strong>Orient (정렬)</strong></strong></li>



<li><strong><strong>AxisX, AxisY, AxisZ (축 설정)</strong></strong></li>
</ul>



<figure class="wp-block-video"><video height="932" style="aspect-ratio: 2280 / 932;" width="2280" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_17_20_59_44_317.mp4"></video><figcaption class="wp-element-caption">Orient Face Camera Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1361" height="1920" src="https://lycos7560.com/wp-content/uploads/2025/02/image-48.jpg" alt="" class="wp-image-39633" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-48.jpg 1361w, https://lycos7560.com/wp-content/uploads/2025/02/image-48-213x300.jpg 213w, https://lycos7560.com/wp-content/uploads/2025/02/image-48-768x1083.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-48-1089x1536.jpg 1089w" sizes="(max-width: 1361px) 100vw, 1361px" /><figcaption class="wp-element-caption"> Orient Face Camera Graph Entire &#8211; Eye Face Camera</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="882" height="1403" src="https://lycos7560.com/wp-content/uploads/2025/02/image-48.png" alt="" class="wp-image-39634" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-48.png 882w, https://lycos7560.com/wp-content/uploads/2025/02/image-48-189x300.png 189w, https://lycos7560.com/wp-content/uploads/2025/02/image-48-768x1222.png 768w" sizes="(max-width: 882px) 100vw, 882px" /><figcaption class="wp-element-caption"> Orient Face Camera Graph Entire &#8211; Body</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="896" src="https://lycos7560.com/wp-content/uploads/2025/02/image-49.jpg" alt="" class="wp-image-39635" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-49.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-49-300x140.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-49-768x358.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-49-1536x717.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption"> Orient Face Camera &#8211; Eye Face Camera (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1200" height="635" src="https://lycos7560.com/wp-content/uploads/2025/02/image-49.png" alt="" class="wp-image-39636" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-49.png 1200w, https://lycos7560.com/wp-content/uploads/2025/02/image-49-300x159.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-49-768x406.png 768w" sizes="(max-width: 1200px) 100vw, 1200px" /><figcaption class="wp-element-caption"> Orient Face Camera &#8211; Eye Face Camera (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="1179" src="https://lycos7560.com/wp-content/uploads/2025/02/image-50.jpg" alt="" class="wp-image-39637" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-50.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-50-300x184.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-50-768x472.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-50-1536x943.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption"> Orient Face Camera &#8211; Eye Face Camera (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1298" height="937" src="https://lycos7560.com/wp-content/uploads/2025/02/image-50.png" alt="" class="wp-image-39638" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-50.png 1298w, https://lycos7560.com/wp-content/uploads/2025/02/image-50-300x217.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-50-768x554.png 768w" sizes="(max-width: 1298px) 100vw, 1298px" /><figcaption class="wp-element-caption">Orient Face Camera &#8211; Eye Face Camera (4)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="1172" src="https://lycos7560.com/wp-content/uploads/2025/02/image-51.jpg" alt="" class="wp-image-39639" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-51.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-51-300x183.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-51-768x469.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-51-1536x938.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption">Orient Face Camera &#8211; Body</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">7. Orient Fixed Axis</h2>



<p>파티클의 <strong>출력(Quads, Meshes, Strips)</strong> 방식과 관계없이, 우리는 종종 파티클이 배치될 방향을 제어하고 싶습니다.</p>



<p>파티클가 <strong>카메라를 향해야 할까요?</strong></p>



<p>파티클의 <strong>전방(Forward) 방향과 상향(Up-Axis)은 무엇인가요?</strong></p>



<p>이때 <strong>Orient(정렬) 블록</strong>을 사용하면 쉽게 파티클의 방향을 설정할 수 있습니다.</p>



<p>이 예제에서는 <strong>&#8220;Fixed Axis(고정 축)&#8221; 모드</strong>를 사용하는 방법을 설명합니다.</p>



<h3 class="wp-block-heading"><strong>Covered Aspects:</strong></h3>



<ul class="wp-block-list">
<li><strong>Orient</strong></li>



<li><strong>AxisX AxisY AxisZ</strong></li>



<li><strong>Custom Attribute</strong></li>
</ul>



<figure class="wp-block-video"><video height="932" style="aspect-ratio: 2344 / 932;" width="2344" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_18_14_14_59_202.mp4"></video></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1307" height="1920" src="https://lycos7560.com/wp-content/uploads/2025/02/image-51-1.jpg" alt="" class="wp-image-39643" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-51-1.jpg 1307w, https://lycos7560.com/wp-content/uploads/2025/02/image-51-1-204x300.jpg 204w, https://lycos7560.com/wp-content/uploads/2025/02/image-51-1-768x1128.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-51-1-1046x1536.jpg 1046w" sizes="(max-width: 1307px) 100vw, 1307px" /><figcaption class="wp-element-caption">Orient Fixed Axis Graph Entire &#8211; Feathers</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1254" height="1920" src="https://lycos7560.com/wp-content/uploads/2025/02/image-51-2.jpg" alt="" class="wp-image-39644" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-51-2.jpg 1254w, https://lycos7560.com/wp-content/uploads/2025/02/image-51-2-196x300.jpg 196w, https://lycos7560.com/wp-content/uploads/2025/02/image-51-2-768x1176.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-51-2-1003x1536.jpg 1003w" sizes="(max-width: 1254px) 100vw, 1254px" /><figcaption class="wp-element-caption">Orient Fixed Axis Graph Entire &#8211; Eyes</figcaption></figure>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:50%">
<figure class="wp-block-image size-full"><img decoding="async" width="493" height="939" src="https://lycos7560.com/wp-content/uploads/2025/02/image-51.png" alt="" class="wp-image-39645" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-51.png 493w, https://lycos7560.com/wp-content/uploads/2025/02/image-51-158x300.png 158w" sizes="(max-width: 493px) 100vw, 493px" /><figcaption class="wp-element-caption">Orient Fixed Axis Graph Entire &#8211; Body</figcaption></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:50%">
<figure class="wp-block-image size-full"><img decoding="async" width="557" height="1023" src="https://lycos7560.com/wp-content/uploads/2025/02/image-52.png" alt="" class="wp-image-39646" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-52.png 557w, https://lycos7560.com/wp-content/uploads/2025/02/image-52-163x300.png 163w" sizes="(max-width: 557px) 100vw, 557px" /></figure>
</div>
</div>



<figure class="wp-block-image size-full"><img decoding="async" width="1765" height="1065" src="https://lycos7560.com/wp-content/uploads/2025/02/image-53.png" alt="" class="wp-image-39647" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-53.png 1765w, https://lycos7560.com/wp-content/uploads/2025/02/image-53-300x181.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-53-768x463.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-53-1536x927.png 1536w" sizes="(max-width: 1765px) 100vw, 1765px" /><figcaption class="wp-element-caption">Orient Fixed Axis &#8211; Feathers (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1888" height="1060" src="https://lycos7560.com/wp-content/uploads/2025/02/image-54.png" alt="" class="wp-image-39649" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-54.png 1888w, https://lycos7560.com/wp-content/uploads/2025/02/image-54-300x168.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-54-768x431.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-54-1536x862.png 1536w" sizes="(max-width: 1888px) 100vw, 1888px" /><figcaption class="wp-element-caption">Orient Fixed Axis &#8211; Feathers (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1892" height="952" src="https://lycos7560.com/wp-content/uploads/2025/02/image-55.png" alt="" class="wp-image-39652" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-55.png 1892w, https://lycos7560.com/wp-content/uploads/2025/02/image-55-300x151.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-55-768x386.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-55-1536x773.png 1536w" sizes="(max-width: 1892px) 100vw, 1892px" /><figcaption class="wp-element-caption">Orient Fixed Axis &#8211; Feathers (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1552" height="814" src="https://lycos7560.com/wp-content/uploads/2025/02/image-56.png" alt="" class="wp-image-39653" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-56.png 1552w, https://lycos7560.com/wp-content/uploads/2025/02/image-56-300x157.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-56-768x403.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-56-1536x806.png 1536w" sizes="(max-width: 1552px) 100vw, 1552px" /><figcaption class="wp-element-caption">Orient Fixed Axis &#8211; Eyes (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1640" height="493" src="https://lycos7560.com/wp-content/uploads/2025/02/image-57.png" alt="" class="wp-image-39654" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-57.png 1640w, https://lycos7560.com/wp-content/uploads/2025/02/image-57-300x90.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-57-768x231.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-57-1536x462.png 1536w" sizes="(max-width: 1640px) 100vw, 1640px" /><figcaption class="wp-element-caption">Orient Fixed Axis &#8211; Eyes (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1749" height="930" src="https://lycos7560.com/wp-content/uploads/2025/02/image-58.png" alt="" class="wp-image-39655" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-58.png 1749w, https://lycos7560.com/wp-content/uploads/2025/02/image-58-300x160.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-58-768x408.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-58-1536x817.png 1536w" sizes="(max-width: 1749px) 100vw, 1749px" /><figcaption class="wp-element-caption">Orient Fixed Axis &#8211; Eyes (3)</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">8. Orient Advanced</h2>



<p><strong>파티클의 출력(Quads, Meshes, Strips) 방식과 관계없이</strong>, 우리는 파티클의 <strong>지오메트리 방향을 제어</strong>하고 싶을 때가 많습니다.</p>



<p><strong>파티클이 카메라를 향해야 할까요?</strong></p>



<p><strong>파티클의 전방(Forward) 방향과 상향(Up-Axis)은 무엇인가요?</strong></p>



<p><strong>Orient(정렬) 블록</strong>을 사용하면 쉽게 파티클의 방향을 설정할 수 있으며, 다양한 모드를 제공합니다.</p>



<p>이번에는 <strong>&#8220;Advanced Mode(고급 모드)&#8221;</strong> 를 사용하는 방법을 설명합니다.</p>



<h3 class="wp-block-heading"><strong>Covered Aspects:</strong></h3>



<ul class="wp-block-list">
<li><strong>Orient</strong></li>



<li><strong>AxisX AxisY AxisZ</strong></li>
</ul>



<figure class="wp-block-video"><video height="1164" style="aspect-ratio: 2344 / 1164;" width="2344" controls src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_18_15_53_46_971.mp4"></video></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1689" height="1870" src="https://lycos7560.com/wp-content/uploads/2025/02/image-59.jpg" alt="" class="wp-image-39659" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-59.jpg 1689w, https://lycos7560.com/wp-content/uploads/2025/02/image-59-271x300.jpg 271w, https://lycos7560.com/wp-content/uploads/2025/02/image-59-768x850.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-59-1387x1536.jpg 1387w" sizes="(max-width: 1689px) 100vw, 1689px" /><figcaption class="wp-element-caption">Orient Advanced Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1886" height="1017" src="https://lycos7560.com/wp-content/uploads/2025/02/image-59.png" alt="" class="wp-image-39661" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-59.png 1886w, https://lycos7560.com/wp-content/uploads/2025/02/image-59-300x162.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-59-768x414.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-59-1536x828.png 1536w" sizes="(max-width: 1886px) 100vw, 1886px" /><figcaption class="wp-element-caption">Orient Advanced (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1376" height="731" src="https://lycos7560.com/wp-content/uploads/2025/02/image-60.png" alt="" class="wp-image-39662" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-60.png 1376w, https://lycos7560.com/wp-content/uploads/2025/02/image-60-300x159.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-60-768x408.png 768w" sizes="(max-width: 1376px) 100vw, 1376px" /><figcaption class="wp-element-caption">Orient Advanced (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1898" height="795" src="https://lycos7560.com/wp-content/uploads/2025/02/image-61.png" alt="" class="wp-image-39663" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-61.png 1898w, https://lycos7560.com/wp-content/uploads/2025/02/image-61-300x126.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-61-768x322.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-61-1536x643.png 1536w" sizes="(max-width: 1898px) 100vw, 1898px" /><figcaption class="wp-element-caption">Orient Advanced (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1012" height="531" src="https://lycos7560.com/wp-content/uploads/2025/02/image-62.png" alt="" class="wp-image-39664" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-62.png 1012w, https://lycos7560.com/wp-content/uploads/2025/02/image-62-300x157.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-62-768x403.png 768w" sizes="(max-width: 1012px) 100vw, 1012px" /><figcaption class="wp-element-caption">Orient Advanced (4)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1316" height="873" src="https://lycos7560.com/wp-content/uploads/2025/02/image-63.png" alt="" class="wp-image-39665" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-63.png 1316w, https://lycos7560.com/wp-content/uploads/2025/02/image-63-300x199.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-63-768x509.png 768w" sizes="(max-width: 1316px) 100vw, 1316px" /><figcaption class="wp-element-caption">Orient Advanced (5)</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">9. Rotation &amp; Angle</h2>



<p>VFX Graph에서 파티클의 회전은 Angle 속성을 조정하여 컨트롤할 수 있습니다.</p>



<p>하지만 보다 현실적인 회전 효과를 구현하려면 Angular Velocity(각속도)를 활용하는 것이 좋습니다.</p>



<p>이 속성은 일반적을 <strong>Initialize Context</strong>에서 설정되며, <strong>Update Context</strong>에서 이를 통합하여 회전을 업데이트합니다.</p>



<h3 class="wp-block-heading"><strong>Covered Aspects:</strong></h3>



<ul class="wp-block-list">
<li><strong>Rotation</strong></li>



<li><strong>Angle attribute</strong></li>



<li><strong>Pivot attribute</strong></li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-video"><video height="964" style="aspect-ratio: 2480 / 964;" width="2480" controls src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_20_12_59_44_165.mp4"></video><figcaption class="wp-element-caption">Rotation &amp; Angle Video</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1728" height="1920" src="https://lycos7560.com/wp-content/uploads/2025/02/image-64.jpg" alt="" class="wp-image-39674" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-64.jpg 1728w, https://lycos7560.com/wp-content/uploads/2025/02/image-64-270x300.jpg 270w, https://lycos7560.com/wp-content/uploads/2025/02/image-64-768x853.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-64-1382x1536.jpg 1382w" sizes="(max-width: 1728px) 100vw, 1728px" /><figcaption class="wp-element-caption">Rotation &amp; Angle Graph Entire</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1673" height="1235" src="https://lycos7560.com/wp-content/uploads/2025/02/image-64.png" alt="" class="wp-image-39675" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-64.png 1673w, https://lycos7560.com/wp-content/uploads/2025/02/image-64-300x221.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-64-768x567.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-64-1536x1134.png 1536w" sizes="(max-width: 1673px) 100vw, 1673px" /><figcaption class="wp-element-caption">Rotation &amp; Angle (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1448" height="1232" src="https://lycos7560.com/wp-content/uploads/2025/02/image-65.png" alt="" class="wp-image-39676" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-65.png 1448w, https://lycos7560.com/wp-content/uploads/2025/02/image-65-300x255.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-65-768x653.png 768w" sizes="(max-width: 1448px) 100vw, 1448px" /><figcaption class="wp-element-caption">Rotation &amp; Angle (2)</figcaption></figure>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h2 class="wp-block-heading">10. Falling Coins</h2>



<p>해당 내용은 <strong>Unity VFX Graph에서 파티클의 회전 및 물리적 움직임</strong>을 설정하는 방법을 설명합니다.</p>



<p>파티클의 <strong>각속도(Angular Velocity)</strong>, <strong>충돌</strong>, <strong>위치 변화(Position Offset)</strong>, <strong>랜덤한 회전 효과</strong> 등을 적용하는 방식에 대해 다룹니다.</p>



<h3 class="wp-block-heading"><strong>Covered Aspects:</strong></h3>



<ul class="wp-block-list">
<li><strong>Angular Velocity</strong></li>



<li><strong>Angle</strong></li>



<li><strong>Update Rotation</strong></li>
</ul>



<figure class="wp-block-video"><video height="1100" style="aspect-ratio: 1944 / 1100;" width="1944" controls muted src="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_20_15_03_36_8-1.mp4"></video></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1249" height="1920" src="https://lycos7560.com/wp-content/uploads/2025/02/image-66.jpg" alt="" class="wp-image-39680" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-66.jpg 1249w, https://lycos7560.com/wp-content/uploads/2025/02/image-66-195x300.jpg 195w, https://lycos7560.com/wp-content/uploads/2025/02/image-66-768x1181.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-66-999x1536.jpg 999w" sizes="(max-width: 1249px) 100vw, 1249px" /><figcaption class="wp-element-caption">Falling Coins Graph Entire (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1015" height="2051" src="https://lycos7560.com/wp-content/uploads/2025/02/image-66.png" alt="" class="wp-image-39681" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-66.png 1015w, https://lycos7560.com/wp-content/uploads/2025/02/image-66-148x300.png 148w, https://lycos7560.com/wp-content/uploads/2025/02/image-66-768x1552.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-66-760x1536.png 760w, https://lycos7560.com/wp-content/uploads/2025/02/image-66-1014x2048.png 1014w" sizes="(max-width: 1015px) 100vw, 1015px" /><figcaption class="wp-element-caption">Falling Coins Graph Entire (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="1536" src="https://lycos7560.com/wp-content/uploads/2025/02/image-67.jpg" alt="" class="wp-image-39682" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-67.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-67-300x240.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-67-768x614.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-67-1536x1229.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption">Falling Coins Graph Entire (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="481" height="1223" src="https://lycos7560.com/wp-content/uploads/2025/02/image-67.png" alt="" class="wp-image-39683" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-67.png 481w, https://lycos7560.com/wp-content/uploads/2025/02/image-67-118x300.png 118w" sizes="(max-width: 481px) 100vw, 481px" /><figcaption class="wp-element-caption">Falling Coins Graph Entire (4)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="1245" src="https://lycos7560.com/wp-content/uploads/2025/02/image-68.jpg" alt="" class="wp-image-39684" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-68.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-68-300x195.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-68-768x498.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-68-1536x996.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption">Falling Coins &#8211; Falling Coins (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="1174" src="https://lycos7560.com/wp-content/uploads/2025/02/image-68-1.jpg" alt="" class="wp-image-39685" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-68-1.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-68-1-300x183.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-68-1-768x470.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-68-1-1536x939.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption">Falling Coins &#8211; Falling Coins (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1055" height="1083" src="https://lycos7560.com/wp-content/uploads/2025/02/image-68.png" alt="" class="wp-image-39687" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-68.png 1055w, https://lycos7560.com/wp-content/uploads/2025/02/image-68-292x300.png 292w, https://lycos7560.com/wp-content/uploads/2025/02/image-68-768x788.png 768w" sizes="(max-width: 1055px) 100vw, 1055px" /><figcaption class="wp-element-caption">Falling Coins &#8211; Falling Coins (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1406" height="1026" src="https://lycos7560.com/wp-content/uploads/2025/02/image-70.png" alt="" class="wp-image-39690" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-70.png 1406w, https://lycos7560.com/wp-content/uploads/2025/02/image-70-300x219.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-70-768x560.png 768w" sizes="(max-width: 1406px) 100vw, 1406px" /><figcaption class="wp-element-caption">Falling Coins &#8211; Sliding Coins (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="789" src="https://lycos7560.com/wp-content/uploads/2025/02/image-69.png" alt="" class="wp-image-39691" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-69.png 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-69-300x123.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-69-768x316.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-69-1536x631.png 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption">Falling Coins &#8211; Sliding Coins (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1013" height="952" src="https://lycos7560.com/wp-content/uploads/2025/02/image-71.png" alt="" class="wp-image-39692" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-71.png 1013w, https://lycos7560.com/wp-content/uploads/2025/02/image-71-300x282.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-71-768x722.png 768w" sizes="(max-width: 1013px) 100vw, 1013px" /><figcaption class="wp-element-caption">Falling Coins &#8211; Sliding Coins (3)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="2231" height="1145" src="https://lycos7560.com/wp-content/uploads/2025/02/image-72.png" alt="" class="wp-image-39693" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-72.png 2231w, https://lycos7560.com/wp-content/uploads/2025/02/image-72-300x154.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-72-768x394.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-72-1536x788.png 1536w, https://lycos7560.com/wp-content/uploads/2025/02/image-72-2048x1051.png 2048w" sizes="(max-width: 2231px) 100vw, 2231px" /><figcaption class="wp-element-caption">Falling Coins &#8211; Coin&#8217;s Pile (1)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1640" height="1297" src="https://lycos7560.com/wp-content/uploads/2025/02/image-73.png" alt="" class="wp-image-39694" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-73.png 1640w, https://lycos7560.com/wp-content/uploads/2025/02/image-73-300x237.png 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-73-768x607.png 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-73-1536x1215.png 1536w" sizes="(max-width: 1640px) 100vw, 1640px" /><figcaption class="wp-element-caption">Falling Coins &#8211; Coin&#8217;s Pile (2)</figcaption></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="1920" height="1007" src="https://lycos7560.com/wp-content/uploads/2025/02/image-74.jpg" alt="" class="wp-image-39695" srcset="https://lycos7560.com/wp-content/uploads/2025/02/image-74.jpg 1920w, https://lycos7560.com/wp-content/uploads/2025/02/image-74-300x157.jpg 300w, https://lycos7560.com/wp-content/uploads/2025/02/image-74-768x403.jpg 768w, https://lycos7560.com/wp-content/uploads/2025/02/image-74-1536x806.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /><figcaption class="wp-element-caption">Falling Coins &#8211; Coin&#8217;s Pile (3)</figcaption></figure>



<p></p>
<p>The post <a href="https://lycos7560.com/unity/urp-vfx-learning-templates-1/39596/">URP VFX Learning Templates (1)</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://lycos7560.com/unity/urp-vfx-learning-templates-1/39596/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_16_18_09_41_580.mp4" length="3880093" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_17_06_12_55_147.mp4" length="3623393" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_17_05_30_00_46.mp4" length="6376492" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_17_08_00_48_775.mp4" length="8397352" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_17_20_23_53_961.mp4" length="13346588" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_17_20_59_44_317.mp4" length="61298828" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_18_14_14_59_202.mp4" length="13314322" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_18_15_53_46_971.mp4" length="30019818" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_20_12_59_44_165.mp4" length="15609420" type="video/mp4" />
<enclosure url="https://lycos7560.com/wp-content/uploads/2025/02/녹화_2025_02_20_15_03_36_8-1.mp4" length="14246069" type="video/mp4" />

			</item>
		<item>
		<title>C#의 CancellationToken, CancellationTokenSource</title>
		<link>https://lycos7560.com/c/c%ec%9d%98-cancellationtoken-cancellationtokensource/39889/</link>
					<comments>https://lycos7560.com/c/c%ec%9d%98-cancellationtoken-cancellationtokensource/39889/#respond</comments>
		
		<dc:creator><![CDATA[lycos7560]]></dc:creator>
		<pubDate>Sun, 16 Feb 2025 08:07:57 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[async]]></category>
		<category><![CDATA[AsynchronousProgramming]]></category>
		<category><![CDATA[Await]]></category>
		<category><![CDATA[BestPractice]]></category>
		<category><![CDATA[Cancel]]></category>
		<category><![CDATA[CancelAfter]]></category>
		<category><![CDATA[CancellationToken]]></category>
		<category><![CDATA[CancellationTokenSource]]></category>
		<category><![CDATA[CodeOptimization]]></category>
		<category><![CDATA[Concurrency]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[CSharpProgramming]]></category>
		<category><![CDATA[DataProcessing]]></category>
		<category><![CDATA[Delay]]></category>
		<category><![CDATA[Dispose]]></category>
		<category><![CDATA[ExceptionHandling]]></category>
		<category><![CDATA[Filestream]]></category>
		<category><![CDATA[GetAsync]]></category>
		<category><![CDATA[HighPerformance]]></category>
		<category><![CDATA[HttpClient]]></category>
		<category><![CDATA[LinkedCancellation]]></category>
		<category><![CDATA[LinkedTokenSource]]></category>
		<category><![CDATA[LoopCancellation]]></category>
		<category><![CDATA[MaxDegreeOfParallelism]]></category>
		<category><![CDATA[MemoryLeak]]></category>
		<category><![CDATA[Multithreading]]></category>
		<category><![CDATA[OperationCanceledException]]></category>
		<category><![CDATA[ParallelForEach]]></category>
		<category><![CDATA[ParallelOptions]]></category>
		<category><![CDATA[ParallelProcessing]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Register]]></category>
		<category><![CDATA[ResourceCleanup]]></category>
		<category><![CDATA[ResourceManagement]]></category>
		<category><![CDATA[SafeThreading]]></category>
		<category><![CDATA[SoftwareDevelopment]]></category>
		<category><![CDATA[study]]></category>
		<category><![CDATA[Task]]></category>
		<category><![CDATA[TaskCanceledException]]></category>
		<category><![CDATA[TaskManagement]]></category>
		<category><![CDATA[TaskRun]]></category>
		<category><![CDATA[thread]]></category>
		<category><![CDATA[ThreadSafety]]></category>
		<category><![CDATA[ThreadSleep]]></category>
		<category><![CDATA[Timeout]]></category>
		<category><![CDATA[Token]]></category>
		<category><![CDATA[TokenSource]]></category>
		<category><![CDATA[TryCatch]]></category>
		<category><![CDATA[Using]]></category>
		<category><![CDATA[공부]]></category>
		<category><![CDATA[기초]]></category>
		<category><![CDATA[비동기처리]]></category>
		<category><![CDATA[코루틴]]></category>
		<guid isPermaLink="false">https://lycos7560.com/?p=39889</guid>

					<description><![CDATA[<p>🔥 CancellationToken, CancellationTokenSource https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.cancellationtokensource?view=net-9.0 ✅ 개념 정리 CancellationToken과 CancellationTokenSource는 C#에서 비동기 작업(Task)이나 스레드를 안전하게 취소할 수 있도록 제공되는 기능합니다. 이를 활용하면 비동기 작업을 중단하거나, 긴 루프를 중지할 수 있도록 관리할 수 있습니다. 🔹 CancellationTokenSource 🔹 CancellationToken 역할 설명 CancellationTokenSource 취소 요청을 보내는 쪽 (발신자) 역할을 합니다. Cancel(), CancelAfter(), Dispose() 등을 호출 할 수 있습니다. CancellationToken [&#8230;]</p>
<p>The post <a href="https://lycos7560.com/c/c%ec%9d%98-cancellationtoken-cancellationtokensource/39889/">C#의 CancellationToken, CancellationTokenSource</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></description>
										<content:encoded><![CDATA[				<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-735cef37      "
					data-scroll= "1"
					data-offset= "30"
					style=""
				>
				<div class="uagb-toc__wrap">
						<div class="uagb-toc__title">
							목차						</div>
																						<div class="uagb-toc__list-wrap ">
						<ol class="uagb-toc__list"><li class="uagb-toc__list"><a href="#cancellationtoken-cancellationtokensource" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancellationToken, CancellationTokenSource</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#개념-정리" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 개념 정리</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#cancellationtokensource" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancellationTokenSource</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#cancellationtoken" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancellationToken</a></li></ul><li class="uagb-toc__list"><a href="#기본적인-사용법" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 기본적인 사용법</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#cancellationtoken-사용-예제" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancellationToken 사용 예제</a></li></ul><li class="uagb-toc__list"><a href="#알아두면-유용한-기능" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 알아두면 유용한 기능</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#throwifcancellationrequested" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ThrowIfCancellationRequested()</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#taskrun에서-cancellationtoken" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Task.Run()에서 CancellationToken</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#register를-활용한-callback-함수" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Register()를 활용한 CallBack 함수</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#async와-cancellationtoken을-활용한-httpclient-요청-취소" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> async와 CancellationToken을 활용한 HttpClient 요청 취소</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#cancelafter를-활용한-자동-취소" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancelAfter()를 활용한 자동 취소</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#linkedtokensource를-사용하여-여러-토큰을-결합" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> LinkedTokenSource를 사용하여 여러 토큰을 결합</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#parallelforeach에서-cancellationtoken-적용" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Parallel.ForEach()에서 CancellationToken 적용</a></li></ul><li class="uagb-toc__list"><a href="#주의-사항" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 주의 사항</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#리소스-정리의-중요성" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 리소스 정리의 중요성</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#cancellationtoken-확인-빈도" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" />  CancellationToken 확인 빈도</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#cancellationtokensourcedispose-중요성" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancellationTokenSource.Dispose() 중요성</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#공식-문서-사용-예제" class="uagb-toc-link__trigger"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 공식 문서 사용 예제</a></ul></ul></ol>					</div>
									</div>
				</div>
			


<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancellationToken, CancellationTokenSource</h2>



<p><a href="https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.cancellationtokensource?view=net-9.0" target="_blank" rel="noreferrer noopener">https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.cancellationtokensource?view=net-9.0</a></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 개념 정리</h3>



<p><code><strong>CancellationToken</strong></code>과 <code><strong>CancellationTokenSource</strong></code>는 C#에서 <strong>비동기 작업(Task)</strong>이나 <strong>스레드를 안전하게 취소</strong>할 수 있도록 제공되는 기능합니다.</p>



<p>이를 활용하면 <strong>비동기 작업을 중단</strong>하거나,<strong> 긴 루프를 중지</strong>할 수 있도록 <strong>관리</strong>할 수 있습니다.</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancellationTokenSource</h4>



<ul class="wp-block-list">
<li>취소 요청을 생성하고 관리하는 역할을 합니다.</li>



<li><code><strong>CancellationToken</strong></code>을 생성할 수 있으며, <strong><code>Cancel()</code></strong> 메서드를 호출하면 해당 토큰을 통해 작업을 중단할 수 있습니다.</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancellationToken</h4>



<ul class="wp-block-list">
<li><code><strong>CancellationTokenSource</strong></code>에서 생성한 취소 토큰을 <strong>비동기 작업</strong>이나 <strong>스레드</strong>에 전달하여, <strong>취소 여부를 확인</strong>하는 데 사용됩니다.</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-table"><table><thead><tr><th>역할</th><th>설명</th></tr></thead><tbody><tr><td><code>CancellationTokenSource</code></td><td><strong>취소 요청을 보내는 쪽 (발신자)</strong> 역할을 합니다. <code>Cancel()</code>, <code>CancelAfter()</code>, <code>Dispose()</code> 등을 호출 할 수 있습니다.</td></tr><tr><td><code>CancellationToken</code></td><td><strong>취소 요청을 받는 쪽 (수신자)</strong> 역할입니다. <code>IsCancellationRequested</code>로 확인하거나, <code>ThrowIfCancellationRequested()</code> 등을 사용해 취소 여부를 감지할 수 있습니다.</td></tr></tbody></table></figure>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 기본적인 사용법</h3>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancellationToken 사용 예제</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        CancellationTokenSource cts = new CancellationTokenSource();
        CancellationToken token = cts.Token;

        Task task = DoWorkAsync(token);

        // 3초 후에 작업 취소 요청
        await Task.Delay(3000);
        cts.Cancel();

        await task;
    }

    static async Task DoWorkAsync(CancellationToken token)
    {
        for (int i = 0; i &lt; 10; i++)
        {
            // 작업이 취소되었는지 확인
            if (token.IsCancellationRequested)
            {
                Console.WriteLine("작업이 취소되었습니다.");
                return;
            }

            Console.WriteLine($"작업 진행 중... {i}");
            await Task.Delay(1000); // 1초 대기
        }
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">작업 진행 중... 0
작업 진행 중... 1
작업 진행 중... 2
작업이 취소되었습니다.
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50d.png" alt="🔍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>설명</strong></h5>



<ol class="wp-block-list">
<li> <code><strong>CancellationTokenSource</strong></code>를 생성하여 <strong><code>CancellationToken</code></strong>을 가져옴</li>



<li> <code><strong>DoWorkAsync()</strong></code> 메서드에서 <code><strong>token.IsCancellationRequested</strong></code>를 통해 취소 여부 확인</li>



<li> <code><strong>Task.Delay(3000)</strong></code> 후 <code><strong>cts.Cancel()</strong></code>을 호출하여 <strong>비동기 작업을 취소</strong></li>
</ol>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 알아두면 유용한 기능</h3>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ThrowIfCancellationRequested()</h4>



<p>이전의 예제에서는 <code><strong>IsCancellationRequested</strong></code>로 확인 후 <code>return</code> 했지만, <code><strong>ThrowIfCancellationRequested()</strong></code>를 사용하면 <strong>예외(Exception) 형태로 중단</strong>할 수도 있습니다.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">static async Task DoWorkAsync(CancellationToken token)
{
    for (int i = 0; i &lt; 10; i++)
    {
        token.ThrowIfCancellationRequested(); // 취소 요청 시 예외 발생

        Console.WriteLine($"작업 진행 중... {i}");
        await Task.Delay(1000);
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>예외 처리 추가</strong> (try-catch로 OperationCanceledException을 catch가 가능)</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">try
{
    await DoWorkAsync(token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("작업이 취소되었습니다. (예외 발생)");
}
</pre>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Task.Run()에서 CancellationToken</h4>



<p>비동기 작업을 <code><strong>Task.Run()</strong></code>을 사용하여 실행하는 경우, <strong><code>CancellationToken</code>을 직접 전달</strong>할 수 있습니다.</p>



<p><code><strong>Task.Run()</strong></code>과 함께 사용할 경우, <code><strong>CancellationToken</strong></code>을 직접 전달하면 자동으로 <code><strong>OperationCanceledException</strong></code>이 발생하여 처리하기 편리합니다.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">CancellationTokenSource cts = new CancellationTokenSource();

Task task = Task.Run(() => 
{
    for (int i = 0; i &lt; 10; i++)
    {
        cts.Token.ThrowIfCancellationRequested();
        Console.WriteLine($"작업 진행 중... {i}");
        Thread.Sleep(1000);
    }
}, cts.Token); // CancellationToken을 직접 전달

await Task.Delay(3000);
cts.Cancel(); // 3초 후 취소
</pre>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Register()를 활용한 CallBack 함수</h4>



<p><code><strong>CancellationToken.Register()</strong></code>를 사용하면, <strong>취소될 때</strong> 특정 작업을 실행할 수 있습니다.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cts.Token.Register(() => Console.WriteLine("취소 요청이 감지되었습니다!"));
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>사용 예제</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        CancellationTokenSource cts = new CancellationTokenSource();
        CancellationToken token = cts.Token;

        // 취소 요청 시 실행될 콜백 등록
        token.Register(() => Console.WriteLine("취소 요청이 감지되었습니다!"));

        Task task = DoWorkAsync(token);

        await Task.Delay(3000);
        cts.Cancel(); // 3초 후 취소 요청

        await task;
    }

    static async Task DoWorkAsync(CancellationToken token)
    {
        for (int i = 0; i &lt; 10; i++)
        {
            if (token.IsCancellationRequested)
            {
                Console.WriteLine("작업이 취소되었습니다.");
                return;
            }

            Console.WriteLine($"작업 진행 중... {i}");
            await Task.Delay(1000);
        }
    }
}
</pre>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">작업 진행 중... 0
작업 진행 중... 1
작업 진행 중... 2
취소 요청이 감지되었습니다!
작업이 취소되었습니다.
</pre>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> async와 CancellationToken을 활용한 HttpClient 요청 취소</h4>



<p><code><strong>HttpClient</strong></code>에서 <code><strong>CancellationToken</strong></code>을 사용하여 HTTP 요청을 중단할 수도 있습니다.</p>



<p><strong><code>HttpClient</code> </strong>요청이 너무 오래 걸리면 <code><strong>CancellationToken</strong></code>을 이용해 요청을 취소할 수 있습니다.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        using (HttpClient client = new HttpClient())
        using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(2))) // 2초 후 자동 취소
        {
            try
            {
                HttpResponseMessage response = await client.GetAsync("https://example.com", cts.Token);
                Console.WriteLine("응답 수신 완료!");
            }
            catch (TaskCanceledException)
            {
                Console.WriteLine("HTTP 요청이 취소되었습니다.");
            }
        }
    }
}
</pre>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancelAfter()를 활용한 자동 취소</h4>



<p>일정 시간이 지나면 자동으로 취소되도록 설정 가능 (<code><strong>CancelAfter(milliseconds)</strong></code>)</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cts.Token.Register(() => Console.WriteLine("취소 요청이 감지되었습니다!"));
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>사용 예제</strong> (5초 후 자동 취소되는 코드)</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        CancellationTokenSource cts = new CancellationTokenSource();
        cts.CancelAfter(5000); // 5초 후 자동 취소

        try
        {
            await DoWorkAsync(cts.Token);
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("작업이 시간 초과로 취소되었습니다.");
        }
    }

    static async Task DoWorkAsync(CancellationToken token)
    {
        for (int i = 0; i &lt; 10; i++)
        {
            token.ThrowIfCancellationRequested();
            Console.WriteLine($"작업 진행 중... {i}");
            await Task.Delay(1000);
        }
    }
}
</pre>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> LinkedTokenSource를 사용하여 여러 토큰을 결합</h4>



<p>여러 <code><strong>CancellationTokenSource</strong></code>를 결합하여 하나의 토큰으로 관리 가능</p>



<p>어느 하나라도 취소되면 전체 작업이 취소됨</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        CancellationTokenSource cts1 = new CancellationTokenSource();
        CancellationTokenSource cts2 = new CancellationTokenSource();

        // 두 개의 토큰을 하나로 결합
        using (CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token))
        {
            Task task = DoWorkAsync(linkedCts.Token);

            await Task.Delay(3000);
            cts1.Cancel(); // 하나의 토큰만 취소해도 작업 전체가 중단됨

            await task;
        }
    }

    static async Task DoWorkAsync(CancellationToken token)
    {
        for (int i = 0; i &lt; 10; i++)
        {
            token.ThrowIfCancellationRequested();
            Console.WriteLine($"작업 진행 중... {i}");
            await Task.Delay(1000);
        }
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>결과적으로 <code><strong>cts1.Cancel();</strong></code> 호출 시 <code><strong>linkedCts</strong></code>도 취소됨</p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Parallel.ForEach()에서 CancellationToken 적용</h4>



<p><code><strong>Parallel.ForEach()</strong></code>에서 <code><strong>CancellationToken</strong></code>을 사용하여 병렬 처리 도중 특정 조건에서 중단할 수도 있습니다.</p>



<p><code><strong>ParallelOptions</strong></code>을 통해 취소 토큰을 설정하면 병렬 처리에서도 취소를 손쉽게 관리할 수 있습니다.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">ParallelOptions options = new ParallelOptions
{
    CancellationToken = cts.Token,
    MaxDegreeOfParallelism = 4 // 최대 4개의 스레드 사용
};

try
{
    Parallel.ForEach(Enumerable.Range(1, 100), options, (num, state) =>
    {
        options.CancellationToken.ThrowIfCancellationRequested();
        Console.WriteLine($"Processing {num}");
        Thread.Sleep(500); // 가상의 작업
    });
}
catch (OperationCanceledException)
{
    Console.WriteLine("병렬 작업이 취소되었습니다.");
}
</pre>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 주의 사항</h3>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 리소스 정리의 중요성</h4>



<p>취소된 작업에서도 적절한 리소스 정리가 필요합니다. </p>



<p>try/finally 블록이나 using 문을 적절이 활용하는 것이 좋습니다.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">static async Task ProcessFileAsync(string path, CancellationToken token)
{
    FileStream file = null;
    try
    {
        file = new FileStream(path, FileMode.Open);
        // 파일 처리 작업
        token.ThrowIfCancellationRequested();
    }
    catch (OperationCanceledException)
    {
        Console.WriteLine("파일 처리가 취소되었습니다.");
        throw;
    }
    finally
    {
        // 취소 여부와 상관없이 항상 실행됨
        file?.Dispose();
    }
}</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" />  CancellationToken 확인 빈도</h4>



<p>장시간 실행되는 작업에서는 <strong>적절한 간격</strong>으로 <strong>취소 토큰을 확인하는 것이 중요</strong>합니다.</p>



<p>취소 토큰 확인은 가벼운 연산이지만, 매우 빈번하게 호출되는 코드에서는 성능에 영향을 줄 수 있습니다.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">static void ProcessLargeData(IEnumerable&lt;int> items, CancellationToken token)
{
    int count = 0;
    foreach (var item in items)
    {
        // 100개 항목마다 취소 여부 확인 (너무 자주 확인하면 성능 저하)
        if (count++ % 100 == 0 &amp;&amp; token.IsCancellationRequested)
        {
            Console.WriteLine("작업이 취소되었습니다.");
            return;
        }
        
        // 항목 처리...
    }
}</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f539.png" alt="🔹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CancellationTokenSource.Dispose() 중요성</h4>



<p>CancellationTokenSource는 사용 후 수명이 끝나면 반드시 Dispose()를 호출해야 합니다. (메모리 누수)</p>



<p>using 문을 사용하는 것을 추천합니다.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">using (var cts = new CancellationTokenSource())
{
    // 작업 수행
}
// 여기서 자동으로 cts.Dispose() 호출됨</pre>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 공식 문서 사용 예제</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.cancellationtokensource?view=net-9.0
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      // Define the cancellation token.
      CancellationTokenSource source = new CancellationTokenSource();
      CancellationToken token = source.Token;

      Random rnd = new Random();
      Object lockObj = new Object();
      
      List&lt;Task&lt;int[]>> tasks = new List&lt;Task&lt;int[]>>();
      TaskFactory factory = new TaskFactory(token);
      for (int taskCtr = 0; taskCtr &lt;= 10; taskCtr++) {
         int iteration = taskCtr + 1;
         tasks.Add(factory.StartNew( () => {
           int value;
           int[] values = new int[10];
           for (int ctr = 1; ctr &lt;= 10; ctr++) {
              lock (lockObj) {
                 value = rnd.Next(0,101);
              }
              if (value == 0) { 
                 source.Cancel();
                 Console.WriteLine("Cancelling at task {0}", iteration);
                 break;
              }   
              values[ctr-1] = value; 
           }
           return values;
        }, token));   
      }
      try {
         Task&lt;double> fTask = factory.ContinueWhenAll(tasks.ToArray(), 
         (results) => {
            Console.WriteLine("Calculating overall mean...");
            long sum = 0;
            int n = 0; 
            foreach (var t in results) {
               foreach (var r in t.Result) {
                  sum += r;
                  n++;
               }
            }
            return sum/(double) n;
         } , token);
         Console.WriteLine("The mean is {0}.", fTask.Result);
      }   
      catch (AggregateException ae) {
         foreach (Exception e in ae.InnerExceptions) {
            if (e is TaskCanceledException)
               Console.WriteLine("Unable to compute mean: {0}", 
                  ((TaskCanceledException) e).Message);
            else
               Console.WriteLine("Exception: " + e.GetType().Name);
         }
      }
      finally {
         source.Dispose();
      }
   }
}
// Repeated execution of the example produces output like the following:
//       Cancelling at task 5
//       Unable to compute mean: A task was canceled.
//       
//       Cancelling at task 10
//       Unable to compute mean: A task was canceled.
//       
//       Calculating overall mean...
//       The mean is 5.29545454545455.
//       
//       Cancelling at task 4
//       Unable to compute mean: A task was canceled.
//       
//       Cancelling at task 5
//       Unable to compute mean: A task was canceled.
//       
//       Cancelling at task 6
//       Unable to compute mean: A task was canceled.
//       
//       Calculating overall mean...
//       The mean is 4.97363636363636.
//       
//       Cancelling at task 4
//       Unable to compute mean: A task was canceled.
//       
//       Cancelling at task 5
//       Unable to compute mean: A task was canceled.
//       
//       Cancelling at task 4
//       Unable to compute mean: A task was canceled.
//       
//       Calculating overall mean...
//       The mean is 4.86545454545455.</pre>
<p>The post <a href="https://lycos7560.com/c/c%ec%9d%98-cancellationtoken-cancellationtokensource/39889/">C#의 CancellationToken, CancellationTokenSource</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://lycos7560.com/c/c%ec%9d%98-cancellationtoken-cancellationtokensource/39889/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>ECS &#8211; EntityQuery 정리</title>
		<link>https://lycos7560.com/unity/ecs-entityquery-%ec%a0%95%eb%a6%ac/39563/</link>
					<comments>https://lycos7560.com/unity/ecs-entityquery-%ec%a0%95%eb%a6%ac/39563/#respond</comments>
		
		<dc:creator><![CDATA[lycos7560]]></dc:creator>
		<pubDate>Sun, 09 Feb 2025 10:22:42 +0000</pubDate>
				<category><![CDATA[Unity]]></category>
		<category><![CDATA[AsNativeArray]]></category>
		<category><![CDATA[AsNativeArray()]]></category>
		<category><![CDATA[BufferTypeHandle]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Chunk components]]></category>
		<category><![CDATA[Cleanup components]]></category>
		<category><![CDATA[Component]]></category>
		<category><![CDATA[concept]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[DOTS]]></category>
		<category><![CDATA[ECS]]></category>
		<category><![CDATA[Entity Component System]]></category>
		<category><![CDATA[EntityQuery]]></category>
		<category><![CDATA[IJobChunk]]></category>
		<category><![CDATA[job]]></category>
		<category><![CDATA[Job 시스템]]></category>
		<category><![CDATA[Managed Components]]></category>
		<category><![CDATA[OnUpdate]]></category>
		<category><![CDATA[OnUpdate()]]></category>
		<category><![CDATA[Physics]]></category>
		<category><![CDATA[Physics Scene Basic]]></category>
		<category><![CDATA[Sample]]></category>
		<category><![CDATA[ScheduleParallel]]></category>
		<category><![CDATA[Shared Components]]></category>
		<category><![CDATA[study]]></category>
		<category><![CDATA[SystemAPI]]></category>
		<category><![CDATA[Tag components]]></category>
		<category><![CDATA[ToEntityArray()]]></category>
		<category><![CDATA[Unity Physics 101]]></category>
		<category><![CDATA[Unmanaged]]></category>
		<guid isPermaLink="false">https://lycos7560.com/?p=39563</guid>

					<description><![CDATA[<p>EntityQuery 정리 ECS(Entity Component System)에서 특정 조건을 만족하는 Entity들을 효율적으로 검색하는 도구 Entity가 가진 컴포넌트 조합을 기준으로 검색하며, 이를 통해 메모리 캐시 효율을 극대화 1. EntityQuery의 기본 개념 &#8211; 특정 컴포넌트를 가진 Entity 찾기 2. EntityQuery의 주요 조건 조건 설명 WithAll&#60;T&#62;() 해당 컴포넌트를 모두 가진 Entity만 검색 WithAny&#60;T&#62;() 지정한 컴포넌트 중 하나라도 가진 Entity 검색 [&#8230;]</p>
<p>The post <a href="https://lycos7560.com/unity/ecs-entityquery-%ec%a0%95%eb%a6%ac/39563/">ECS &#8211; EntityQuery 정리</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></description>
										<content:encoded><![CDATA[				<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-0a6626f3      "
					data-scroll= "1"
					data-offset= "30"
					style=""
				>
				<div class="uagb-toc__wrap">
						<div class="uagb-toc__title">
							EntityQuery						</div>
																						<div class="uagb-toc__list-wrap ">
						<ol class="uagb-toc__list"><li class="uagb-toc__list"><a href="#entityquery-정리" class="uagb-toc-link__trigger">EntityQuery 정리</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-entityquery의-기본-개념" class="uagb-toc-link__trigger">1. EntityQuery의 기본 개념</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#특정-컴포넌트를-가진-entity-찾기" class="uagb-toc-link__trigger">&#8211; 특정 컴포넌트를 가진 Entity 찾기</a></li></ul><li class="uagb-toc__list"><a href="#2-entityquery의-주요-조건" class="uagb-toc-link__trigger">2. EntityQuery의 주요 조건</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#특정-조건의-엔티티-찾기" class="uagb-toc-link__trigger">&#8211; 특정 조건의 엔티티 찾기</a></li></ul><li class="uagb-toc__list"><a href="#3-entityquery를-사용한-데이터-접근-방법" class="uagb-toc-link__trigger">3. EntityQuery를 사용한 데이터 접근 방법</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-systemapiquery-사용" class="uagb-toc-link__trigger">(1) SystemAPI.Query() 사용</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#2-toentityarray로-entity-리스트-가져오기" class="uagb-toc-link__trigger">(2) ToEntityArray()로 Entity 리스트 가져오기</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#3-tocomponentdataarray로-특정-컴포넌트-리스트-가져오기" class="uagb-toc-link__trigger">(3) ToComponentDataArray()로 특정 컴포넌트 리스트 가져오기</a></li></ul><li class="uagb-toc__list"><a href="#4-ijobchunk과-함께-사용하기" class="uagb-toc-link__trigger">4. IJobChunk과 함께 사용하기</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#q-componenttypehandle을-사용하여-nativearray를-생성하는-것과-미리-nativearray를-넘겨주는-것의-차이점" class="uagb-toc-link__trigger">(Q) ComponentTypeHandle을 사용하여 NativeArray를 생성하는 것과 미리 NativeArray를 넘겨주는 것의 차이점</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-componenttypehandlet을-사용하는-이유" class="uagb-toc-link__trigger">(1) ComponentTypeHandle을 사용하는 이유</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#2-componenttypehandlet과-nativearrayt-차이점-비교" class="uagb-toc-link__trigger">(2) ComponentTypeHandle과 NativeArray 차이점 비교</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#3-componenttypehandlet-방식" class="uagb-toc-link__trigger">(3) ComponentTypeHandle 방식</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#4-nativearray-job-방식" class="uagb-toc-link__trigger">(4) NativeArray  Job 방식</a></li></ul></li></ul><li class="uagb-toc__list"><a href="#5-entityquery의-추가-기능" class="uagb-toc-link__trigger">5. EntityQuery의 추가 기능</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#1-calculateentitycount로-개수-확인" class="uagb-toc-link__trigger">(1) CalculateEntityCount()로 개수 확인</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#2-setchangedversionfilter로-변경된-컴포넌트만-검색" class="uagb-toc-link__trigger">(2) SetChangedVersionFilter()로 변경된 컴포넌트만 검색</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#3-enabledisable로-쿼리-활성화비활성화" class="uagb-toc-link__trigger">(3) Enable/Disable로 쿼리 활성화/비활성화</a></ul></ul></ol>					</div>
									</div>
				</div>
			


<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">EntityQuery 정리</h2>



<p>ECS(Entity Component System)에서 <strong>특정 조건을 만족하는 Entity들을 효율적으로 검색</strong>하는 도구</p>



<p>Entity가 가진 <strong>컴포넌트 조합을 기준</strong>으로 검색하며, 이를 통해 <strong>메모리 캐시 효율을 극대화</strong></p>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">1. <strong>EntityQuery의 기본 개념</strong></h3>



<ul class="wp-block-list">
<li><strong>Entity 필터링</strong>: 특정한 <strong>컴포넌트를 포함하거나 제외하는 기준</strong>을 정할 수 있다.</li>



<li><strong>Chunk 단위 검색</strong>: <code>EntityQuery</code>는 Entity 개별 조회가 아닌 Chunk 단위(Archetype Chunk)로 데이터를 가져옴</li>



<li><strong>즉시 검색 or <code>Job</code> 시스템과 병렬 처리</strong> 가능</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">&#8211; 특정 컴포넌트를 가진 Entity 찾기</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">public partial struct FindEntitiesSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        // PositionComponent와 VelocityComponent를 가진 Entity 찾기
        EntityQuery query = SystemAPI.QueryBuilder()
            .WithAll&lt;PositionComponent, VelocityComponent>()
            .Build();

        foreach (var (position, velocity) in SystemAPI.Query&lt;RefRW&lt;PositionComponent>, RefRO&lt;VelocityComponent>>())
        {
            position.ValueRW.Value += velocity.ValueRO.Value * SystemAPI.Time.DeltaTime;
        }
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<ul class="wp-block-list">
<li>WithAll() → 모든 엔티티 중 PositionComponent와 VelocityComponent를 가진 것만 검색</li>



<li>RefRW → 읽기/쓰기 가능</li>



<li>RefRO → 읽기 전용</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading">2. EntityQuery의 주요 조건</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>조건</th><th>설명</th></tr></thead><tbody><tr><td><code>WithAll&lt;T&gt;()</code></td><td>해당 <strong>컴포넌트를 모두 가진 Entity만 검색</strong></td></tr><tr><td><code>WithAny&lt;T&gt;()</code></td><td>지정한 <strong>컴포넌트 중 하나라도 가진 <strong>Entity</strong> 검색</strong></td></tr><tr><td><code>WithNone&lt;T&gt;()</code></td><td>특정한 <strong>컴포넌트를 가지지 않은 <strong>Entity</strong> 검색</strong></td></tr><tr><td><code>WithDisabled&lt;T&gt;()</code></td><td><strong>비활성화된 컴포넌트</strong>가 있는 Entity 검색</td></tr><tr><td><code>WithAbsent&lt;T&gt;()</code></td><td>특정한 <strong>컴포넌트가 없는 <strong>Entity</strong> 검색</strong></td></tr></tbody></table></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">&#8211; <strong>특정 조건의 엔티티 찾기</strong></h4>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">EntityQuery query = SystemAPI.QueryBuilder()
    .WithAll&lt;PositionComponent>()   // PositionComponent가 있어야 함
    .WithAny&lt;VelocityComponent, AccelerationComponent>()  // 둘 중 하나만 있으면 됨
    .WithNone&lt;DestroyedTag>()        // DestroyedTag가 있으면 제외
    .Build();
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<ul class="wp-block-list">
<li>WithAll() → 반드시 포함</li>



<li>WithAny() → 하나라도 포함</li>



<li>WithNone() → 포함하면 안 됨</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading">3. EntityQuery를 사용한 데이터 접근 방법</h3>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(1) <strong>SystemAPI.Query() 사용</strong></h4>



<ul class="wp-block-list">
<li><code>EntityQuery</code>를 생성하고 <code>foreach</code> 루프에서 엔티티 데이터를 순회 가능</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">foreach (var (position, velocity) in SystemAPI.Query&lt;RefRW&lt;PositionComponent>, RefRO&lt;VelocityComponent>>())
{
    position.ValueRW.Value += velocity.ValueRO.Value * SystemAPI.Time.DeltaTime;
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(2) <strong>ToEntityArray()로 Entity 리스트 가져오기</strong></h4>



<ul class="wp-block-list">
<li><code>ToEntityArray()</code>를 사용하면 <strong>해당 <code>EntityQuery</code>에 해당하는 Entity 리스트를 가져옴</strong></li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">var entities = query.ToEntityArray(Allocator.Temp);
foreach (var entity in entities)
{
    Debug.Log($"찾은 Entity: {entity}");
}
entities.Dispose();
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<ul class="wp-block-list">
<li><code>ToEntityArray(Allocator.Temp)</code> → <strong>NativeArray로 Entity를 가져옴</strong></li>



<li><code>Dispose()</code> 필수! <strong>메모리 해제 안 하면 메모리 누수 발생</strong></li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(3) <strong>ToComponentDataArray()로 특정 컴포넌트 리스트 가져오기</strong></h4>



<ul class="wp-block-list">
<li>특정 컴포넌트의 값만 가져올 수도 있음.</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">var positions = query.ToComponentDataArray&lt;PositionComponent>(Allocator.Temp);
foreach (var position in positions)
{
    Debug.Log($"Position: {position.Value}");
}
positions.Dispose();
</pre>



<ul class="wp-block-list">
<li><strong>데이터만 필요한 경우 성능 최적화 가능</strong></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading">4. <strong>IJobChunk과 함께 사용하기</strong></h3>



<ul class="wp-block-list">
<li><strong><code>IJobChunk</code>를 사용하면 <code>EntityQuery</code>를 멀티스레드로 병렬 처리 가능</strong></li>



<li> <code>ArchetypeChunk</code>을 사용하여 <strong>Chunk 단위 데이터 접근</strong> 가능</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[BurstCompile]
public struct MoveJob : IJobChunk
{
    public ComponentTypeHandle&lt;PositionComponent> PositionHandle;
    [ReadOnly] public ComponentTypeHandle&lt;VelocityComponent> VelocityHandle;
    public float DeltaTime;

    public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
    {
        var positions = chunk.GetNativeArray(PositionHandle);
        var velocities = chunk.GetNativeArray(VelocityHandle);

        for (int i = 0; i &lt; chunk.Count; i++)
        {
            positions[i] = new PositionComponent
            {
                Value = positions[i].Value + velocities[i].Value * DeltaTime
            };
        }
    }
}

public partial struct MoveSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        var query = SystemAPI.QueryBuilder()
            .WithAll&lt;PositionComponent, VelocityComponent>()
            .Build();

        var positionHandle = SystemAPI.GetComponentTypeHandle&lt;PositionComponent>();
        var velocityHandle = SystemAPI.GetComponentTypeHandle&lt;VelocityComponent>(isReadOnly: true);

        var job = new MoveJob
        {
            PositionHandle = positionHandle,
            VelocityHandle = velocityHandle,
            DeltaTime = SystemAPI.Time.DeltaTime
        };
        // query를 기반으로 Schedule()을 호출
        state.Dependency = job.Schedule(query, state.Dependency);
    }
}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<ul class="wp-block-list">
<li><code>GetComponentTypeHandle&lt;T>()</code> 사용 → <strong>컴포넌트 데이터를 가져올 때 캐시 최적화</strong><br><code>GetComponentTypeHandle&lt;T>()</code>은 <strong>ECS(Worlds)의 청크 단위 데이터 접근을 최적화</strong>하기 위한 API</li>



<li><code>IJobChunk</code>으로 <strong>멀티스레드 병렬 처리 가능</strong></li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong><code>job.Schedule(query, state.Dependency)</code>의 실행 과정</strong></p>



<p><strong><code>query</code>를 사용하여 <code>IJobChunk</code>가 처리할 청크들을 찾음</strong></p>



<ul class="wp-block-list">
<li><code>query</code>는 <code>PositionComponent</code>와 <code>VelocityComponent</code>를 포함하는 엔티티들의 <strong>청크 목록</strong>을 가져옴.</li>



<li><code>IJobChunk</code>는 이 청크 목록을 기반으로 실행됨.</li>
</ul>



<p> <strong><code>job.Schedule()</code>을 호출하여 <code>MoveJob</code>을 실행</strong></p>



<ul class="wp-block-list">
<li><code>query</code>에서 반환된 청크를 <code>MoveJob</code>에서 병렬적으로 처리.</li>



<li>내부적으로 <strong>각 청크별로 <code>MoveJob.Execute()</code>가 실행됨</strong>.</li>
</ul>



<p><strong><code>state.Dependency</code>를 업데이트하여 잡 실행을 관리</strong></p>



<ul class="wp-block-list">
<li><code>state.Dependency</code>는 현재 시스템의 <strong>의존성 체인</strong>을 관리.</li>



<li>이전 프레임에서 실행된 다른 잡들과의 <strong>의존 관계를 고려하여 동기화</strong>함.</li>



<li>병렬 처리를 안전하게 실행하기 위해 필요함.</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>매개변수</th><th>타입</th><th>설명</th></tr></thead><tbody><tr><td><code>chunk</code></td><td><code>ArchetypeChunk</code></td><td>현재 처리 중인 <strong>Chunk</strong> 객체. <br>해당 <strong>Chunk</strong> 내의 Entity 및 컴포넌트에 접근할 수 있음.</td></tr><tr><td><code>chunkIndex</code></td><td><code>int</code></td><td>현재 <strong><strong>Chunk</strong> 의 인덱스</strong> (0부터 시작). <br>병렬 작업을 할 때 <strong>Chunk</strong> 가 몇 번째인지 확인 가능.</td></tr><tr><td><code>firstEntityIndex</code></td><td><code>int</code></td><td>현재 <strong>Chunk</strong> 에서 <strong>첫 번째 Entity 의 전역 인덱스</strong>.<br>(전체 Entity  중 몇 번째인지 나타냄)</td></tr></tbody></table></figure>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(Q) ComponentTypeHandle을 사용하여 NativeArray를 생성하는 것과 미리 NativeArray를 넘겨주는 것의 차이점</h4>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading">(1) <code>ComponentTypeHandle&lt;T></code>을 사용하는 이유</h5>



<p><code>GetComponentTypeHandle&lt;T>()</code>을 사용하여 <code>IJobChunk</code> 내부에서 <code>NativeArray</code>를 가져오는 이유는 <strong>Chunk 단위 접근 최적화</strong> 때문이다.</p>



<ul class="wp-block-list">
<li><code>ComponentTypeHandle&lt;T></code>을 사용하면 <strong>각 Chunk에 맞는 <code>NativeArray</code>를 개별적으로 가져올 수 있음</strong></li>



<li>만약 <code>NativeArray</code>를 미리 만들어서 넘겨준다면, <strong>Chunk별로 나눠진 데이터가 하나의 배열에 병합되어야 하므로 메모리 효율이 떨어지고 캐시 활용도가 낮아짐</strong></li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading">(2) <code>ComponentTypeHandle&lt;T></code>과 <code>NativeArray&lt;T></code> 차이점 비교</h5>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>방식</th><th>설명</th><th>장점</th><th>단점</th></tr></thead><tbody><tr><td><strong><code>ComponentTypeHandle&lt;T></code> 사용 </strong><br><strong>(<code>IJobChunk</code> 내부에서 <code>GetNativeArray()</code>)</strong></td><td><strong>각 청크에서 해당 컴포넌트의 데이터 배열을 가져옴</strong></td><td><strong>&#8211; 청크별로 최적화된 데이터 접근 가능</strong><br><strong>&#8211; 캐시 친화적이며 성능 최적화 가능</strong><br><strong>&#8211; Burst 및 멀티스레딩에 적합</strong></td><td><strong>&#8211; <code>IJobChunk</code>을 사용해야 함</strong></td></tr><tr><td><strong><code>NativeArray&lt;T&gt;</code>를 미리 만들어 Job에 넘김</strong></td><td><strong>전체 데이터를 하나의 <code>NativeArray</code>로 만들고 Job에서 사용</strong></td><td><strong>&#8211; 간단한 구조, 직관적</strong><br><strong>&#8211; 작은 데이터셋에서는 부담이 적음</strong></td><td><strong>&#8211; 전체 데이터를 하나의 배열로 만들기 때문에 캐시 미스 발생 가능성 증가</strong><br><strong>&#8211; Chunk별 최적화가 불가능하여 성능 저하 가능성 있음</strong></td></tr></tbody></table></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading">(3) <code>ComponentTypeHandle&lt;T></code> 방식</h5>



<p>1> <code>SystemAPI.GetComponentTypeHandle&lt;T>()</code> 실행</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">var positionHandle = SystemAPI.GetComponentTypeHandle&lt;PositionComponent>();
var velocityHandle = SystemAPI.GetComponentTypeHandle&lt;VelocityComponent>(isReadOnly: true);
</pre>



<ul class="wp-block-list">
<li><code>ComponentTypeHandle&lt;T></code>을 가져옴</li>



<li>Chunk별로 데이터가 분산되어 있기 때문에 <code>NativeArray&lt;T></code>로 직접 변환하지 않음</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>2> <code>MoveJob.Schedule()</code> 실행</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">var job = new MoveJob
{
    PositionHandle = positionHandle,
    VelocityHandle = velocityHandle,
    DeltaTime = SystemAPI.Time.DeltaTime
};

state.Dependency = job.Schedule(query, state.Dependency);
</pre>



<ul class="wp-block-list">
<li><code>MoveJob</code>을 스케줄할 때 <code>ComponentTypeHandle&lt;T></code>을 넘김</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>3> <code>MoveJob.Execute()</code> 내부에서 <code>GetNativeArray()</code> 실행</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">var positions = chunk.GetNativeArray(PositionHandle);
var velocities = chunk.GetNativeArray(VelocityHandle);
</pre>



<ul class="wp-block-list">
<li>각 Chunk에서 <code>NativeArray&lt;T></code>를 가져와서 사용함.</li>



<li>이렇게 하면 각 Chunk가 독립적으로 자신의 데이터에 접근할 수 있으며, 캐시 최적화 및 멀티스레딩 효율 증가</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading">(4) <code>NativeArray</code>  Job 방식</h5>



<p>만약 <code>NativeArray&lt;T></code>를 미리 만들어서 Job에 넘기면, <strong>멀티스레딩 최적화가 어렵고 성능 저하 가능성 증가</strong>.</p>



<p><strong>전체 데이터를 하나의 <code>NativeArray</code>로 병합</strong>하는 과정이 필요, <strong>Chunk별 데이터 레이아웃이 깨질 수 있음</strong> → CPU 캐시 효율 저하.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">NativeArray&lt;PositionComponent> positions = new NativeArray&lt;PositionComponent>(entityCount, Allocator.TempJob);
NativeArray&lt;VelocityComponent> velocities = new NativeArray&lt;VelocityComponent>(entityCount, Allocator.TempJob);

// Job에 NativeArray를 직접 넘김
var job = new MoveJob
{
    Positions = positions,
    Velocities = velocities,
    DeltaTime = SystemAPI.Time.DeltaTime
};

state.Dependency = job.Schedule(state.Dependency);
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>이 경우, <strong><code>positions</code>와 <code>velocities</code>를 Chunk별로 나누지 않고 전체 데이터를 하나의 배열로 만듦.</strong></p>



<p>Chunk별 데이터가 섞일 가능성이 높아져 캐시 미스(Cache Miss)가 증가할 수 있음</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide" style="margin-top:var(--wp--preset--spacing--80);margin-bottom:var(--wp--preset--spacing--80)"/>



<h3 class="wp-block-heading">5. <strong>EntityQuery의 추가 기능</strong></h3>



<h4 class="wp-block-heading">(1) CalculateEntityCount()로 개수 확인</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">int entityCount = query.CalculateEntityCount();
Debug.Log($"현재 쿼리 결과 개수: {entityCount}");
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(2) SetChangedVersionFilter()로 변경된 컴포넌트만 검색</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">query.SetChangedVersionFilter&lt;PositionComponent>();
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>최근 변경된 <code>PositionComponent</code>를 가진 엔티티만 검색</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">(3) Enable/Disable로 쿼리 활성화/비활성화</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">query.SetEnabled(false);  // 쿼리 비활성화
query.SetEnabled(true);   // 다시 활성화
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>쿼리를 특정 조건에서만 사용하고 싶을 때 활용</p>
<p>The post <a href="https://lycos7560.com/unity/ecs-entityquery-%ec%a0%95%eb%a6%ac/39563/">ECS &#8211; EntityQuery 정리</a> appeared first on <a href="https://lycos7560.com">어제와 내일의 나 그 사이의 이야기</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://lycos7560.com/unity/ecs-entityquery-%ec%a0%95%eb%a6%ac/39563/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
