<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>kyvv 님의 블로그</title>
    <link>https://kyvv.tistory.com/</link>
    <description>kyvv 님의 블로그 입니다.</description>
    <language>ko</language>
    <pubDate>Thu, 11 Jun 2026 15:44:35 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>kyvv</managingEditor>
    <item>
      <title>최종 프로젝트 Esport Team Maker 회고</title>
      <link>https://kyvv.tistory.com/64</link>
      <description>&lt;h2 style=&quot;background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;ESport Team Maker 프로젝트 회고: 효율적인 데이터 관리와 사용자 경험 개선&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. 프로젝트 개요&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;프로젝트 이름:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;ESport Team Maker&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발 기간:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;25.6 ~ 25.8 (8주)&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;참여 인원:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;기획 2 / 개발 4&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 주요 기능 및 개발 과정&lt;/h3&gt;
&lt;p style=&quot;background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;본 프로젝트에서는 본인은 ESport 팀을 구성하고 운영하는 과정을 시뮬레이션하는 과정에서 다음과 같은 핵심 기능들을 구현하고, 효율적인 데이터 관리 및 사용자 경험 개선에 집중했습니다.&lt;/p&gt;
&lt;h4 style=&quot;background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2.1. 싱글톤 패턴 기반의 일정 관리 시스템&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고민:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;게임 내 씬 전환 시 일정 정보 유실 방지, 효율적인 일정 관리&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;해결:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;싱글톤 클래스를 활용하여 일정 관리 시스템을 구축했습니다. 씬 전환에 관계없이 일정 정보 및 게임 내 날짜를 유지하고 관리할 수 있도록 했습니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;구현:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;각 일정은 인터페이스 상속 대신 부모-자식 상속 구조로 설계하여 유지보수 및 확장성을 용이하게 했습니다. 새로운 일정을 추가하거나 기존 일정을 수정할 때 코드 변경 범위를 최소화할 수 있도록 했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;게임의 흐름을 끊김 없이 유지하고, 다양한 일정들을 효율적으로 관리할 수 있었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2.2. CSV -&amp;gt; Scriptable Object 변환 시스템&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고민:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;기획 단계에서 데이터 변경에 따른 개발 부담 증가&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;해결:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;기획자가 직접 데이터를 수정하고, 빠르게 게임에 반영할 수 있도록 CSVImporter 스크립트를 개발했습니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;구현:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;CSV 파일을 Scriptable Object로 변환하는 기능을 구현하여, 데이터 수정 후 빠르게 SO들을 수정하여 빌드 테스트를 진행했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;기획자와 개발자 간의 협업 효율성을 높이고, 데이터 변경에 유연하게 대처할 수 있었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2.3. JSON 기반 게임 진행 상황 저장 시스템&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고민:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;게임 진행 상황 및 시스템 정보의 안전하고 효율적인 저장 및 관리&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;해결:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;JSON 포맷을 사용하여 게임 진행 상황과 시스템 정보(사운드 설정 등)를 저장하고 관리하는 시스템을 구축했습니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;구현:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;간단한 암호화(XOR 변환)를 적용하여 사용자가 데이터 파일을 임의로 조작하는 것을 방지했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;게임 진행 상황을 안전하게 저장하고, 사용자에게 쾌적한 게임 환경을 제공할 수 있었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2.4. 큐(Queue)를 활용한 뉴스 피드 시스템&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고민:&lt;/b&gt;&lt;span&gt; 경기&amp;nbsp;&lt;/span&gt;일정 수행 후 뉴스 피드를 순서대로 보여주는 기능 구현&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;해결:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;큐 자료구조를 활용하여 뉴스 피드가 추가된 순서대로 표시되도록 구현했습니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;게임의 몰입도를 높이고, 사용자에게 여러 팀의 경기 결과를 별도의 UI 팝업 없이도 전달할 수 있었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. 느낀점&lt;/h3&gt;
&lt;p style=&quot;background-color: #fcfbfb; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ESport Team Maker 프로젝트를 진행하면서 데이터 관리의 중요성을 다시 한번 깨달았습니다. 특히, CSV -&amp;gt; Scriptable Object 변환 시스템을 통해 기획자와의 협업 효율성을 높이고, 개발 과정을 단축할 수 있었습니다. 앞으로 프로젝트를 진행할 때 데이터 관리 시스템을 더욱 효율적으로 구축하고, 사용자 경험을 개선하기 위한 다양한 시도를 해봐야겠습니다.&lt;/p&gt;</description>
      <category>[내일배움캠프 Unity 9기]</category>
      <author>kyvv</author>
      <guid isPermaLink="true">https://kyvv.tistory.com/64</guid>
      <comments>https://kyvv.tistory.com/64#entry64comment</comments>
      <pubDate>Fri, 12 Sep 2025 10:59:47 +0900</pubDate>
    </item>
    <item>
      <title>JPS 길 찾기</title>
      <link>https://kyvv.tistory.com/63</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;JPS는 A* 알고리즘에서 개선된 버전의 길 찾기 알고리즘이다.&lt;br /&gt;A*가 시작 지점부터 계속해서 노드를 생성하면서 목적지까지의 길을 찾아가는 반면 JPS는 이 노드 생성의 시행 횟수를 줄이고자 나왔다. 그로 인해 탐색 범위가 더 많아졌다는 단점이 존재하게 되었지만 메모리 활용 측면에서 노드 생성의 횟수가 줄어드는 이점이 더 큰 경우가 많기 때문에 활용성이 더 좋다고 할 수 있다.&lt;br /&gt;아래는 윈도우 창으로 A*와 JPS를 시각화한 결과물의 사진이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;1008&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3FsvG/btsQpBpPJve/JrZmuL68ftCmuz9JrFJIs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3FsvG/btsQpBpPJve/JrZmuL68ftCmuz9JrFJIs1/img.png&quot; data-alt=&quot;A* 길찾기 알고리즘&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3FsvG/btsQpBpPJve/JrZmuL68ftCmuz9JrFJIs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3FsvG%2FbtsQpBpPJve%2FJrZmuL68ftCmuz9JrFJIs1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1902&quot; height=&quot;1008&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;1008&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;A* 길찾기 알고리즘&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;455&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oTTDT/btsQqGjLUu4/UMlUJKHdBizBag5OkSDbnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oTTDT/btsQqGjLUu4/UMlUJKHdBizBag5OkSDbnK/img.png&quot; data-alt=&quot;표시된 칸이 전부 생성된 노드, 노란색 칸은 방문한 노드이며 아래의 JPS와 비교했을 때 생성 및 탐색하는 노드 수가 확연히 많다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oTTDT/btsQqGjLUu4/UMlUJKHdBizBag5OkSDbnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoTTDT%2FbtsQqGjLUu4%2FUMlUJKHdBizBag5OkSDbnK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;601&quot; height=&quot;455&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;455&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;표시된 칸이 전부 생성된 노드, 노란색 칸은 방문한 노드이며 아래의 JPS와 비교했을 때 생성 및 탐색하는 노드 수가 확연히 많다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1899&quot; data-origin-height=&quot;1009&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/86f1J/btsQpzldVh6/P0HhDyv4KPSYoTwBqaEVIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/86f1J/btsQpzldVh6/P0HhDyv4KPSYoTwBqaEVIK/img.png&quot; data-alt=&quot;JPS를 활용한 길찾기 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/86f1J/btsQpzldVh6/P0HhDyv4KPSYoTwBqaEVIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F86f1J%2FbtsQpzldVh6%2FP0HhDyv4KPSYoTwBqaEVIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1899&quot; height=&quot;1009&quot; data-origin-width=&quot;1899&quot; data-origin-height=&quot;1009&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;JPS를 활용한 길찾기 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;820&quot; data-origin-height=&quot;901&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cB6iJP/btsQtcBwk0k/ywdx8GkGWkclPqvA3ofb20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cB6iJP/btsQtcBwk0k/ywdx8GkGWkclPqvA3ofb20/img.png&quot; data-alt=&quot;경로 탐색 일부 코드 - 노드의 메모리 사용량을 줄여보기 위해 탐색 조건인 reason을 UCHAR로 1바이트만 사용하도록 한 후 비트 연산으로 분기를 나눔&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cB6iJP/btsQtcBwk0k/ywdx8GkGWkclPqvA3ofb20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcB6iJP%2FbtsQtcBwk0k%2Fywdx8GkGWkclPqvA3ofb20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;820&quot; height=&quot;901&quot; data-origin-width=&quot;820&quot; data-origin-height=&quot;901&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;경로 탐색 일부 코드 - 노드의 메모리 사용량을 줄여보기 위해 탐색 조건인 reason을 UCHAR로 1바이트만 사용하도록 한 후 비트 연산으로 분기를 나눔&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhXtZY/btsQrwnrTcy/8r6DyI5zK5hl14vHMgSMk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhXtZY/btsQrwnrTcy/8r6DyI5zK5hl14vHMgSMk0/img.png&quot; data-alt=&quot;우측 방향 탐색 코드 - JPS 노드 생성 조건에 맞을 경우 중단, 그 외에는 계속 탐색&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhXtZY/btsQrwnrTcy/8r6DyI5zK5hl14vHMgSMk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhXtZY%2FbtsQrwnrTcy%2F8r6DyI5zK5hl14vHMgSMk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;936&quot; height=&quot;800&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;우측 방향 탐색 코드 - JPS 노드 생성 조건에 맞을 경우 중단, 그 외에는 계속 탐색&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>개인 프로젝트</category>
      <author>kyvv</author>
      <guid isPermaLink="true">https://kyvv.tistory.com/63</guid>
      <comments>https://kyvv.tistory.com/63#entry63comment</comments>
      <pubDate>Tue, 9 Sep 2025 23:09:24 +0900</pubDate>
    </item>
    <item>
      <title>06/18 TIL 프로젝트 마무리 및 발표 자료 정리</title>
      <link>https://kyvv.tistory.com/60</link>
      <description>&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;트러블 슈팅&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플레이어 동기화&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;[발생]&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플레이어 입장시 Host 환경 기준으로 입장한 플레이어들의 입력이 반영되지 않음&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[원인]&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플레이어 Object들이 각 Client 환경 내에서 개인 환경에 대한 입력 권한을 기준으로 입력을 처리하고 무시하면서 Host 환경에 있는 플레이어 Object들의 입력 처리가 이루어지지 않았음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그로 인해 Host 측으로 움직임이 동기화가 이루어지지 않아 Client에서는 움직임이 입력은 되지만 Host 환경에서는 입력 처리가 되지 않아서 움직이지 않게 되었고, 이로 인해 Client 오브젝트들이 Host에서 고정되는 현상이 생겼음&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[개선 시도]&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fusion에 기본 제공 기능이 있는지 파악 시도&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;입력 값은 각 플레이어 고유 적용되도록 제한이 걸려 있는 상황에서 움직임까지 제한할 필요 없다는 판단&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[해결 완료]&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SIMPLE KCC 라는 Fusion2 제공 기능을 통해 캐릭터 컨트롤러 동기화를 맞추고 있다는 공식 문서와 멀티 환경에서 입력값이 넘어오는 것을 공식 문서 및 디버깅으로 확인한 후 우측의 코드를 주석 처리함으로써 해결&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;149&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bu1yuw/btsQpFkxTqf/DSRQ3Cy6neUqdTxLUryA8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bu1yuw/btsQpFkxTqf/DSRQ3Cy6neUqdTxLUryA8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bu1yuw/btsQpFkxTqf/DSRQ3Cy6neUqdTxLUryA8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbu1yuw%2FbtsQpFkxTqf%2FDSRQ3Cy6neUqdTxLUryA8k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;696&quot; height=&quot;149&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;149&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;카메라 핸들&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[발생]&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시네머신을 적용하여 카메라 구현하였으나 총기 반동이 원활하지 않음&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[원인]&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시네머신에서 다른 방식으로 로테이션 값을 처리하여 고정됨.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또한 모든 캐릭터 조작을 담당하는 ProcessInput 함수에서 좌우이동, RefreshCamera에서 상하이동을 따로 구현되어 있는 걸 발견.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;카메라 조작 메소드 RefreshCamera 함수 추적 해보니 여러 곳에 사용되고 있으나 동작하지 않음. (코드 가독성 문제 발생)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;카메라 움직임이 일반구현 &amp;rarr; 서버구현 &amp;rarr; 시네머신구현 등 다른 사람들의 손을 걷치며, 서로 다른 방식으로 구현한 것으로 판단됨.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[개선 시도]&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;총기 반동 적용을 위해 기본 카메라만 이용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;카메라 조작 메서드 RefreshCamera가 오용된 부분을 제거 및 재정의&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[해결 완료]&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RefreshCamera 에 상하좌우 회전코드를 전부 작성하여 가독성 상승. ProcessInput 함수에 넣어 플레이어 조작에 포함됨을 표현.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로젝트를 진행하면서 fusion2에 대해 파악한 점&lt;br /&gt;- 네트워크 오브젝트로 동기화를 맞추고자 한다면 자식부터 부모까지 네트워크 오브젝트가 붙어있어야지 동기화가 잘 이루어진다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 캐릭터의 메인 카메라에 네트워크 오브젝트가 붙게 된다면 레이 캐스트를 카메라 기준으로 쏠 시, 호스트-클라이언트 환경에서는 클라의 ray가 다른 캐릭터(주로 호스트)의 카메라로 동기화가 이루어진다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- InputAuthority : 현재 클라이언트가 이 객체에 대해서 입력(컨트롤)이 가능한가&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- StateAuthority : 이 객체가 호스트 환경에 있는지&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 네트워크 프리팹은 fusion에서 실행 시 config 파일로 올라가 등록이 되며, runner.spawn(네트워크 프리팹)/despawn을 통해 생성/삭제를 할 수 있으며 이는 네트워크에 동기화를 맞춰준다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>[내일배움캠프 Unity 9기]</category>
      <author>kyvv</author>
      <guid isPermaLink="true">https://kyvv.tistory.com/60</guid>
      <comments>https://kyvv.tistory.com/60#entry60comment</comments>
      <pubDate>Wed, 18 Jun 2025 23:27:49 +0900</pubDate>
    </item>
    <item>
      <title>06/05 FSM + BT / 개인 과제 FSM 작성하기</title>
      <link>https://kyvv.tistory.com/52</link>
      <description>&lt;h3 data-end=&quot;243&quot; data-start=&quot;229&quot; data-ke-size=&quot;size23&quot;&gt;  오늘 배운 것&lt;/h3&gt;
&lt;p data-end=&quot;297&quot; data-start=&quot;244&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;유니티에서 FSM과 BT를 조합하여 게임 캐릭터의 AI를 설계하는 구조에 대해 학습했다.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-end=&quot;302&quot; data-start=&quot;299&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;319&quot; data-start=&quot;304&quot; data-ke-size=&quot;size23&quot;&gt;  핵심 개념 정리&lt;/h3&gt;
&lt;h4 data-end=&quot;365&quot; data-start=&quot;321&quot; data-ke-size=&quot;size20&quot;&gt;1. FSM (Finite State Machine, 유한 상태 기계)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;495&quot; data-start=&quot;366&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;414&quot; data-start=&quot;366&quot;&gt;캐릭터의 &quot;상태(state)&quot;를 명확하게 구분하고, 상태 전이 조건을 통해 제어함.&lt;/li&gt;
&lt;li data-end=&quot;468&quot; data-start=&quot;415&quot;&gt;예시 상태: Idle, Patrol, Chase, Attack, Die 등&lt;/li&gt;
&lt;li data-end=&quot;495&quot; data-start=&quot;469&quot;&gt;각 상태는 고유한 로직과 전이 조건을 가짐.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;530&quot; data-start=&quot;497&quot; data-ke-size=&quot;size20&quot;&gt;2. BT (Behavior Tree, 행동 트리)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;692&quot; data-start=&quot;531&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;569&quot; data-start=&quot;531&quot;&gt;상태 내부에서의 &lt;b&gt;세부 행동&lt;/b&gt;들을 계층적 트리 구조로 표현함.&lt;/li&gt;
&lt;li data-end=&quot;656&quot; data-start=&quot;570&quot;&gt;트리 노드는 &lt;b&gt;선택(Selector)&lt;/b&gt;, &lt;b&gt;순차(Sequence)&lt;/b&gt;, &lt;b&gt;조건(Condition)&lt;/b&gt;, &lt;b&gt;행동(Action)&lt;/b&gt; 등으로 구성.&lt;/li&gt;
&lt;li data-end=&quot;692&quot; data-start=&quot;657&quot;&gt;복잡한 AI 로직을 분기와 반복 구조로 간결하게 표현 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;697&quot; data-start=&quot;694&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;720&quot; data-start=&quot;699&quot; data-ke-size=&quot;size23&quot;&gt;  FSM + BT 조합 구조&lt;/h3&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;872&quot; data-start=&quot;722&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;872&quot; data-start=&quot;750&quot;&gt;
&lt;tr data-end=&quot;801&quot; data-start=&quot;750&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;756&quot; data-start=&quot;750&quot;&gt;FSM&lt;/td&gt;
&lt;td data-end=&quot;801&quot; data-start=&quot;756&quot; data-col-size=&quot;md&quot;&gt;상위 레벨에서 전체 캐릭터의 상태를 결정. (예: 공격, 추적, 순찰 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;872&quot; data-start=&quot;802&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;808&quot; data-start=&quot;802&quot;&gt;BT&lt;/td&gt;
&lt;td data-end=&quot;872&quot; data-start=&quot;808&quot; data-col-size=&quot;md&quot;&gt;각 상태(FSM State) 내에서 세부 행동을 정의. (예: 공격 중에도 회피, 스킬 선택 등 판단 포함)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1749129496791&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[ FSM ]
└── IdleState
└── PatrolState
    └── [BT] -&amp;gt; Waypoint 탐색 &amp;rarr; Move &amp;rarr; 다음 Waypoint
└── ChaseState
    └── [BT] -&amp;gt; 적 탐지 &amp;rarr; 추적 &amp;rarr; 시야 확인
└── AttackState
    └── [BT] -&amp;gt; 사거리 확인 &amp;rarr; 스킬 선택 &amp;rarr; 공격 or 후퇴&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1122&quot; data-start=&quot;1103&quot; data-ke-size=&quot;size23&quot;&gt;⚙️ 유니티 구현 방식 예시&lt;/h3&gt;
&lt;h4 data-end=&quot;1137&quot; data-start=&quot;1124&quot; data-ke-size=&quot;size20&quot;&gt;✅ FSM 구현&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1237&quot; data-start=&quot;1138&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1197&quot; data-start=&quot;1138&quot;&gt;IState 인터페이스 정의 &amp;rarr; 상태별 클래스(IdleState, ChaseState) 구현&lt;/li&gt;
&lt;li data-end=&quot;1237&quot; data-start=&quot;1198&quot;&gt;StateMachine 클래스에서 상태 전이 및 현재 상태 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1749129508358&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface IState
{
    void Enter();
    void Update();
    void Exit();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1348&quot; data-start=&quot;1336&quot; data-ke-size=&quot;size20&quot;&gt;✅ BT 구현&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1490&quot; data-start=&quot;1349&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1424&quot; data-start=&quot;1349&quot;&gt;간단한 노드 기반 구조 정의 (BTNode, Selector, Sequence, Condition, Action)&lt;/li&gt;
&lt;li data-end=&quot;1490&quot; data-start=&quot;1425&quot;&gt;각 노드에서 Evaluate() 함수로 결과 반환 (Success, Failure, Running)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1749129524982&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public abstract class BTNode
{
    public abstract BTResult Evaluate();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ 통합 사용 예&lt;/p&gt;
&lt;pre id=&quot;code_1749129538381&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// FSM에서 상태 전이
if (enemyDetected)
    stateMachine.ChangeState(new ChaseState());

// 각 상태 내부에서 BT 사용
public class AttackState : IState
{
    private BTNode attackTree;

    public void Enter()
    {
        attackTree = new Selector(
            new SkillAttackNode(),
            new MeleeAttackNode(),
            new RetreatNode()
        );
    }

    public void Update()
    {
        attackTree.Evaluate();
    }

    public void Exit() { }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;2075&quot; data-start=&quot;2067&quot; data-ke-size=&quot;size23&quot;&gt;✅ 장점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2168&quot; data-start=&quot;2076&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2126&quot; data-start=&quot;2076&quot;&gt;FSM으로 &lt;b&gt;전체 흐름 제어&lt;/b&gt;, BT로 &lt;b&gt;세부 행동 제어&lt;/b&gt; &amp;rarr; 명확한 역할 분리&lt;/li&gt;
&lt;li data-end=&quot;2168&quot; data-start=&quot;2127&quot;&gt;재사용성, 유지보수성 뛰어남 (특히 BT는 복잡한 행동도 모듈화 가능)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;2173&quot; data-start=&quot;2170&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;2185&quot; data-start=&quot;2175&quot; data-ke-size=&quot;size23&quot;&gt;⚠️ 유의점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2289&quot; data-start=&quot;2186&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2237&quot; data-start=&quot;2186&quot;&gt;FSM 상태 전이가 많아질 경우 전이 조건 정리가 필요 &amp;rarr; &lt;b&gt;전이 테이블&lt;/b&gt; 도입 권장&lt;/li&gt;
&lt;li data-end=&quot;2289&quot; data-start=&quot;2238&quot;&gt;BT가 깊어질수록 성능 및 디버깅 부담이 커질 수 있음 &amp;rarr; &lt;b&gt;시각화 도구 활용&lt;/b&gt; 고려&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;2294&quot; data-start=&quot;2291&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;2311&quot; data-start=&quot;2296&quot; data-ke-size=&quot;size23&quot;&gt;✍️ 오늘의 인사이트&lt;/h3&gt;
&lt;blockquote data-end=&quot;2452&quot; data-start=&quot;2312&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;2452&quot; data-start=&quot;2314&quot; data-ke-size=&quot;size16&quot;&gt;단일 FSM이나 단일 BT만 사용하는 것보다, 두 구조를 &lt;b&gt;역할에 따라 조합&lt;/b&gt;했을 때 훨씬 더 유연하고 명확한 AI 설계를 할 수 있다. 특히 복잡한 전투 AI에서는 FSM으로 큰 흐름을 관리하고, BT로 세밀한 판단을 나누는 것이 효과적이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;2457&quot; data-start=&quot;2454&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;2471&quot; data-start=&quot;2459&quot; data-ke-size=&quot;size23&quot;&gt;  참고 자료&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2573&quot; data-start=&quot;2472&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2509&quot; data-start=&quot;2472&quot;&gt;Unity AI Programming - FSM vs BT 비교&lt;/li&gt;
&lt;li data-end=&quot;2550&quot; data-start=&quot;2510&quot;&gt;GDC 강연: Behavior Trees for Next-Gen AI&lt;/li&gt;
&lt;li data-end=&quot;2573&quot; data-start=&quot;2551&quot;&gt;책: Game AI Pro 시리즈&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-개인 과제 FSM 제작 현황&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의에서 작성한 코드를 활용해서 필요한 기능만 빼서 사용하려고 했으나, 일부분만 보고 사용하기에는 전체 구조를 파악하기가 어려워져 그냥 처음부터 만들어 나가기로 결정했다.&lt;br /&gt;만들면서 헷갈리는 부분을 강의 코드에서 도움 받는 형식으로,, 이것 때문에 쓸데 없이 시간을 많이 허비했지만, 그래도 전체 코드를 훑어 볼 수 있었던 시간이 되었다. 일단 주말동안 추가 작업은 피할 수가 없구나..&lt;/p&gt;</description>
      <category>[내일배움캠프 Unity 9기]</category>
      <author>kyvv</author>
      <guid isPermaLink="true">https://kyvv.tistory.com/52</guid>
      <comments>https://kyvv.tistory.com/52#entry52comment</comments>
      <pubDate>Thu, 5 Jun 2025 22:21:15 +0900</pubDate>
    </item>
    <item>
      <title>06/04 TIL 두트윈(feat. 메서드 체이닝)</title>
      <link>https://kyvv.tistory.com/51</link>
      <description>&lt;p data-end=&quot;195&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&quot;&lt;b&gt;두트윈(DOTween)&lt;/b&gt;&quot;은 Unity용 &lt;b&gt;고성능 트위닝(tweening) 라이브러리&lt;/b&gt;로, 오브젝트의 &lt;b&gt;이동, 회전, 크기, 색상, 알파 값 등의 애니메이션&lt;/b&gt;을 간단하고 직관적으로 처리할 수 있게 해줍니다.&lt;br /&gt;(DOTween은 &lt;a data-end=&quot;179&quot; data-start=&quot;136&quot;&gt;Demigiant&lt;/a&gt;에서 만든 라이브러리입니다.)&lt;/p&gt;
&lt;hr data-end=&quot;200&quot; data-start=&quot;197&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;221&quot; data-start=&quot;202&quot; data-ke-size=&quot;size26&quot;&gt;✅ DOTween의 주요 특징&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;특징설명
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;604&quot; data-start=&quot;223&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;604&quot; data-start=&quot;251&quot;&gt;
&lt;tr data-end=&quot;306&quot; data-start=&quot;251&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;261&quot; data-start=&quot;251&quot;&gt;&lt;b&gt;고성능&lt;/b&gt;&lt;/td&gt;
&lt;td data-end=&quot;306&quot; data-start=&quot;261&quot; data-col-size=&quot;md&quot;&gt;Unity 내부에서 메모리를 최소화하고 빠르게 작동하도록 최적화되어 있음.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;348&quot; data-start=&quot;307&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;320&quot; data-start=&quot;307&quot;&gt;&lt;b&gt;간편한 문법&lt;/b&gt;&lt;/td&gt;
&lt;td data-end=&quot;348&quot; data-start=&quot;320&quot; data-col-size=&quot;md&quot;&gt;메서드 체이닝 기반의 직관적인 API 제공.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;412&quot; data-start=&quot;349&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;366&quot; data-start=&quot;349&quot;&gt;&lt;b&gt;다양한 트위닝 지원&lt;/b&gt;&lt;/td&gt;
&lt;td data-end=&quot;412&quot; data-start=&quot;366&quot; data-col-size=&quot;md&quot;&gt;위치, 회전, 스케일, 컬러, 알파, UI 등 다양한 요소 애니메이션 지원.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;456&quot; data-start=&quot;413&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;426&quot; data-start=&quot;413&quot;&gt;&lt;b&gt;시퀀스 지원&lt;/b&gt;&lt;/td&gt;
&lt;td data-end=&quot;456&quot; data-start=&quot;426&quot; data-col-size=&quot;md&quot;&gt;여러 트윈을 순차적으로 또는 동시에 실행 가능.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;530&quot; data-start=&quot;457&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;476&quot; data-start=&quot;457&quot;&gt;&lt;b&gt;시간 스케일 무시 가능&lt;/b&gt;&lt;/td&gt;
&lt;td data-end=&quot;530&quot; data-start=&quot;476&quot; data-col-size=&quot;md&quot;&gt;SetUpdate(true)로 Time.timeScale = 0일 때도 동작 가능.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;604&quot; data-start=&quot;531&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;575&quot; data-start=&quot;531&quot;&gt;&lt;b&gt;Play, Pause, Kill, Restart 등 제어 기능 풍부&lt;/b&gt;&lt;/td&gt;
&lt;td data-end=&quot;604&quot; data-start=&quot;575&quot; data-col-size=&quot;md&quot;&gt;애니메이션 상태를 제어하는 다양한 함수 지원.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;609&quot; data-start=&quot;606&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;625&quot; data-start=&quot;611&quot; data-ke-size=&quot;size26&quot;&gt;✅ 기본 사용법 예시&lt;/h2&gt;
&lt;h3 data-end=&quot;643&quot; data-start=&quot;627&quot; data-ke-size=&quot;size23&quot;&gt;1. &lt;b&gt;초기 설정&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;819&quot; data-start=&quot;644&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;762&quot; data-start=&quot;644&quot;&gt;Unity 패키지 매니저 또는 &lt;a data-end=&quot;756&quot; data-start=&quot;663&quot;&gt;Asset Store&lt;/a&gt;에서 설치.&lt;/li&gt;
&lt;li data-end=&quot;819&quot; data-start=&quot;763&quot;&gt;또는 Tools &amp;gt; DOTween Utility Panel에서 설치 완료 확인 후 Setup.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;824&quot; data-start=&quot;821&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;857&quot; data-start=&quot;826&quot; data-ke-size=&quot;size23&quot;&gt;2. &lt;b&gt;위치 트윈 (Transform 이동)&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1749042071283&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;transform.DOMove(new Vector3(5, 0, 0), 1f); // 1초 동안 (5,0,0)으로 이동&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-end=&quot;955&quot; data-start=&quot;939&quot; data-ke-size=&quot;size23&quot;&gt;3. &lt;b&gt;회전 트윈&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1749042077789&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;transform.DORotate(new Vector3(0, 180, 0), 2f);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-end=&quot;1036&quot; data-start=&quot;1019&quot; data-ke-size=&quot;size23&quot;&gt;4. &lt;b&gt;스케일 트윈&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1749042086680&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;transform.DOScale(Vector3.zero, 1f); // 1초 동안 점점 작아짐&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-end=&quot;1140&quot; data-start=&quot;1105&quot; data-ke-size=&quot;size23&quot;&gt;5. &lt;b&gt;색상 트윈 (SpriteRenderer 등)&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1749042094323&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spriteRenderer.DOColor(Color.red, 1f);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;1198&quot; data-start=&quot;1195&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1215&quot; data-start=&quot;1200&quot; data-ke-size=&quot;size26&quot;&gt;✅ 메서드 체이닝 예시&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1749042101567&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;transform.DOMoveX(3f, 1f)
         .SetEase(Ease.InOutBounce)
         .SetLoops(2, LoopType.Yoyo)
         .OnComplete(() =&amp;gt; Debug.Log(&quot;Move done!&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1458&quot; data-start=&quot;1384&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1405&quot; data-start=&quot;1384&quot;&gt;SetEase: 애니메이션 곡선&lt;/li&gt;
&lt;li data-end=&quot;1434&quot; data-start=&quot;1406&quot;&gt;SetLoops: 반복 설정 (횟수, 타입)&lt;/li&gt;
&lt;li data-end=&quot;1458&quot; data-start=&quot;1435&quot;&gt;OnComplete: 완료 시 콜백&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1463&quot; data-start=&quot;1460&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1495&quot; data-start=&quot;1465&quot; data-ke-size=&quot;size26&quot;&gt;✅ Sequence 사용 예시 (복합 애니메이션)&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1749042113424&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Sequence seq = DOTween.Sequence();
seq.Append(transform.DOMoveX(3f, 1f))
	.Append(transform.DOScale(2f, 0.5f))
    .Join(transform.DORotate(new Vector3(0, 180, 0), 1f))
    .AppendCallback(() =&amp;gt; Debug.Log(&quot;Sequence Done&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1800&quot; data-start=&quot;1737&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1754&quot; data-start=&quot;1737&quot;&gt;Append: 순차 실행&lt;/li&gt;
&lt;li data-end=&quot;1770&quot; data-start=&quot;1755&quot;&gt;Join: 병렬 실행&lt;/li&gt;
&lt;li data-end=&quot;1800&quot; data-start=&quot;1771&quot;&gt;AppendCallback: 중간에 함수 삽입&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1805&quot; data-start=&quot;1802&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1819&quot; data-start=&quot;1807&quot; data-ke-size=&quot;size26&quot;&gt;✅ 주의점 및 팁&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;항목설명
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;2197&quot; data-start=&quot;1821&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;2197&quot; data-start=&quot;1849&quot;&gt;
&lt;tr data-end=&quot;1926&quot; data-start=&quot;1849&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1870&quot; data-start=&quot;1849&quot;&gt;&lt;b&gt;DOTween 초기화 필수&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;1926&quot; data-start=&quot;1870&quot;&gt;설치 후 DOTween Utility Panel에서 &lt;b&gt;Setup DOTween&lt;/b&gt; 필수.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2000&quot; data-start=&quot;1927&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1951&quot; data-start=&quot;1927&quot;&gt;&lt;b&gt;PlayMode에서도 잘 동작함&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;2000&quot; data-start=&quot;1951&quot;&gt;TimeScale 0에서도 애니메이션 가능 (SetUpdate(true))&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2074&quot; data-start=&quot;2001&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2026&quot; data-start=&quot;2001&quot;&gt;&lt;b&gt;오브젝트가 파괴되면 트윈도 중단됨&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;2074&quot; data-start=&quot;2026&quot;&gt;SetAutoKill(false)로 방지하거나, Kill() 사용 권장.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2116&quot; data-start=&quot;2075&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2089&quot; data-start=&quot;2075&quot;&gt;&lt;b&gt;GC 최소화됨&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;2116&quot; data-start=&quot;2089&quot;&gt;성능에 민감한 프로젝트에서도 부담이 적음.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2197&quot; data-start=&quot;2117&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2129&quot; data-start=&quot;2117&quot;&gt;&lt;b&gt;UI 지원&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;2197&quot; data-start=&quot;2129&quot;&gt;RectTransform.DOAnchorPos, CanvasGroup.DOFade 등 UI 요소도 트윈 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;2202&quot; data-start=&quot;2199&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2222&quot; data-start=&quot;2204&quot; data-ke-size=&quot;size26&quot;&gt;✅ 대표적인 트윈 함수 정리&lt;/h2&gt;
&lt;div&gt;함수설명
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;2502&quot; data-start=&quot;2224&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;2502&quot; data-start=&quot;2252&quot;&gt;
&lt;tr data-end=&quot;2287&quot; data-start=&quot;2252&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2278&quot; data-start=&quot;2252&quot;&gt;DOMove, DOMoveX/Y/Z&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2287&quot; data-start=&quot;2278&quot;&gt;위치 이동&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2324&quot; data-start=&quot;2288&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2318&quot; data-start=&quot;2288&quot;&gt;DORotate, DOLocalRotate&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2324&quot; data-start=&quot;2318&quot;&gt;회전&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2360&quot; data-start=&quot;2325&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2353&quot; data-start=&quot;2325&quot;&gt;DOScale, DOScaleX/Y/Z&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2360&quot; data-start=&quot;2353&quot;&gt;스케일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2382&quot; data-start=&quot;2361&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2373&quot; data-start=&quot;2361&quot;&gt;DOColor&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2382&quot; data-start=&quot;2373&quot;&gt;색상 변경&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2403&quot; data-start=&quot;2383&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2394&quot; data-start=&quot;2383&quot;&gt;DOFade&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2403&quot; data-start=&quot;2394&quot;&gt;알파 변경&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2432&quot; data-start=&quot;2404&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2421&quot; data-start=&quot;2404&quot;&gt;DOFillAmount&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2432&quot; data-start=&quot;2421&quot;&gt;이미지 채우기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2461&quot; data-start=&quot;2433&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2449&quot; data-start=&quot;2433&quot;&gt;DOAnchorPos&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2461&quot; data-start=&quot;2449&quot;&gt;UI 위치 이동&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2502&quot; data-start=&quot;2462&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2473&quot; data-start=&quot;2462&quot;&gt;DOText&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2502&quot; data-start=&quot;2473&quot;&gt;텍스트 애니메이션 (TextMeshPro 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;139&quot; data-start=&quot;109&quot; data-ke-size=&quot;size26&quot;&gt;✅ C++에서 메서드 체이닝을 사용하는 대표 사례&lt;/h2&gt;
&lt;h3 data-end=&quot;176&quot; data-start=&quot;141&quot; data-ke-size=&quot;size23&quot;&gt;1. &lt;b&gt;C++ iostream (입출력 스트림)&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1749042127225&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;

int main() {
	std::cout &amp;lt;&amp;lt; &quot;Hello, &quot; &amp;lt;&amp;lt; &quot;world!&quot; &amp;lt;&amp;lt; std::endl;
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;427&quot; data-start=&quot;320&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;368&quot; data-start=&quot;320&quot;&gt;std::cout은 operator&amp;lt;&amp;lt;를 체이닝할 수 있도록 설계되어 있음.&lt;/li&gt;
&lt;li data-end=&quot;427&quot; data-start=&quot;369&quot;&gt;operator&amp;lt;&amp;lt;는 참조(보통 ostream&amp;amp;)를 반환하므로, 다음 호출이 이어질 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1749042134442&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;std::ostream&amp;amp; operator&amp;lt;&amp;lt;(std::ostream&amp;amp; os, const char* str);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;505&quot; data-start=&quot;502&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;543&quot; data-start=&quot;507&quot; data-ke-size=&quot;size23&quot;&gt;2. &lt;b&gt;C++ 사용자 정의 클래스에서의 메서드 체이닝&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1749042140988&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Builder { 
	public: Builder&amp;amp; setA(int val) { a = val; return *this; } 
    
    Builder&amp;amp; setB(int val) { b = val; return *this; } 
    
    void print() const { std::cout &amp;lt;&amp;lt; &quot;A: &quot; &amp;lt;&amp;lt; a &amp;lt;&amp;lt; &quot;, B: &quot; &amp;lt;&amp;lt; b &amp;lt;&amp;lt; '\n'; } 
    
    private: int a = 0; int b = 0; 
}; // 사용 예시 Builder obj; obj.setA(10).setB(20).print();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;918&quot; data-start=&quot;915&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;949&quot; data-start=&quot;920&quot; data-ke-size=&quot;size26&quot;&gt;✅ C#에서 메서드 체이닝을 사용하는 대표 사례&lt;/h2&gt;
&lt;h3 data-end=&quot;989&quot; data-start=&quot;951&quot; data-ke-size=&quot;size23&quot;&gt;1. &lt;b&gt;StringBuilder (System.Text)&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1749042287122&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System.Text;

var sb = new StringBuilder();

sb.Append(&quot;Hello &quot;)
  .Append(&quot;World!&quot;)
  .AppendLine();
    
Console.WriteLine(sb.ToString());&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1203&quot; data-start=&quot;1146&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1203&quot; data-start=&quot;1146&quot;&gt;Append, AppendLine 등이 모두 StringBuilder 자신을 반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1208&quot; data-start=&quot;1205&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1233&quot; data-start=&quot;1210&quot; data-ke-size=&quot;size23&quot;&gt;2. &lt;b&gt;LINQ 메서드 체이닝&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1749042366445&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System.Linq;

var result = Enumerable.Range(1, 10)
					   .Where(x =&amp;gt; x % 2 == 0)
                       .Select(x =&amp;gt; x * x)
                       .ToList();

foreach (var x in result) Console.WriteLine(x);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1552&quot; data-start=&quot;1483&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1552&quot; data-start=&quot;1483&quot;&gt;Where, Select, ToList 등 LINQ 메서드들이 체이닝 가능하도록 IEnumerable을 반환.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1557&quot; data-start=&quot;1554&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1567&quot; data-start=&quot;1559&quot; data-ke-size=&quot;size26&quot;&gt;요약 비교&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;언어체이닝 사용 예반환 방식
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1748&quot; data-start=&quot;1569&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;1748&quot; data-start=&quot;1634&quot;&gt;
&lt;tr data-end=&quot;1692&quot; data-start=&quot;1634&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1641&quot; data-start=&quot;1634&quot;&gt;C++&lt;/td&gt;
&lt;td data-end=&quot;1663&quot; data-start=&quot;1641&quot; data-col-size=&quot;sm&quot;&gt;std::cout, 사용자 정의&lt;/td&gt;
&lt;td data-end=&quot;1692&quot; data-start=&quot;1663&quot; data-col-size=&quot;sm&quot;&gt;참조 (&amp;amp;) 또는 포인터 (*this)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1748&quot; data-start=&quot;1693&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1700&quot; data-start=&quot;1693&quot;&gt;C#&lt;/td&gt;
&lt;td data-end=&quot;1724&quot; data-start=&quot;1700&quot; data-col-size=&quot;sm&quot;&gt;StringBuilder, LINQ&lt;/td&gt;
&lt;td data-end=&quot;1748&quot; data-start=&quot;1724&quot; data-col-size=&quot;sm&quot;&gt;자기 자신 또는 IEnumerable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>[내일배움캠프 Unity 9기]</category>
      <author>kyvv</author>
      <guid isPermaLink="true">https://kyvv.tistory.com/51</guid>
      <comments>https://kyvv.tistory.com/51#entry51comment</comments>
      <pubDate>Wed, 4 Jun 2025 22:10:17 +0900</pubDate>
    </item>
    <item>
      <title>06/02 팀프로젝트 마무리 및 새롭게 배워갈만한 부분</title>
      <link>https://kyvv.tistory.com/50</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;어드레서블을 통한 리소스 관리 / 비동기 호출을 통한 로딩씬 UI 구현&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Behavior Tree를 활용한 상태 제어(FSM 혼합 사용 가능함)&lt;br /&gt;싱글톤 클래스의 템플릿(제네릭)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장 메서드를 사용하여 반복적 코드 축약&lt;br /&gt;&lt;br /&gt;자세한 내용들은 시간이 날 때 한 번 정리할 필요가 있음(당장은 개인 인강과 제공된 강의를 수강할 예정)&lt;/p&gt;</description>
      <author>kyvv</author>
      <guid isPermaLink="true">https://kyvv.tistory.com/50</guid>
      <comments>https://kyvv.tistory.com/50#entry50comment</comments>
      <pubDate>Mon, 2 Jun 2025 21:06:10 +0900</pubDate>
    </item>
    <item>
      <title>05/30 TIL SpawnManager 역할 고민, 낮/밤 사이클 전환, NavMesh SamplePosition</title>
      <link>https://kyvv.tistory.com/49</link>
      <description>&lt;h3 data-end=&quot;135&quot; data-start=&quot;103&quot; data-ke-size=&quot;size23&quot;&gt;  SpawnManager 리팩토링 및 역할 확장&lt;/h3&gt;
&lt;h4 data-end=&quot;149&quot; data-start=&quot;137&quot; data-ke-size=&quot;size20&quot;&gt;❓ 의문점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;221&quot; data-start=&quot;150&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;185&quot; data-start=&quot;150&quot;&gt;SpawnManager가 오브젝트 풀만 관리하면 되는가?&lt;/li&gt;
&lt;li data-end=&quot;221&quot; data-start=&quot;186&quot;&gt;씬 전환 시 프리팹 참조를 잃었을 때 다시 로드해야 하는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;235&quot; data-start=&quot;223&quot; data-ke-size=&quot;size20&quot;&gt;✅ 해결점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;374&quot; data-start=&quot;236&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;298&quot; data-start=&quot;236&quot;&gt;&lt;b&gt;기존 역할에 &quot;스폰 위치 지정&quot; 기능을 추가&lt;/b&gt;하면서 더 강력한 SpawnManager로 확장 가능.&lt;/li&gt;
&lt;li data-end=&quot;374&quot; data-start=&quot;299&quot;&gt;&lt;b&gt;씬 전환 후 ScriptableObject의 참조는 유지되지만&lt;/b&gt;, 해당 프리팹은 로딩 상태에 따라 풀/딕셔너리에 재세팅 필요.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;388&quot; data-start=&quot;376&quot; data-ke-size=&quot;size20&quot;&gt;  예시&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;csharp&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;// Init 시 매번 prefab 재세팅&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ItemData data = ResourceManager.Instance.GetResource&amp;lt;ItemData&amp;gt;(key); &lt;/span&gt;&lt;span&gt;&lt;span&gt;if&lt;/span&gt;&lt;/span&gt;&lt;span&gt; (data != &lt;/span&gt;&lt;span&gt;&lt;span&gt;null&lt;/span&gt;&lt;/span&gt;&lt;span&gt;) prefabs[key] = data.prefab; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;550&quot; data-start=&quot;547&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;578&quot; data-start=&quot;552&quot; data-ke-size=&quot;size23&quot;&gt;  낮/밤 사이클에서 빛 오브젝트 전환&lt;/h3&gt;
&lt;h4 data-end=&quot;592&quot; data-start=&quot;580&quot; data-ke-size=&quot;size20&quot;&gt;❓ 의문점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;655&quot; data-start=&quot;593&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;655&quot; data-start=&quot;593&quot;&gt;Light.intensity로 오브젝트를 SetActive() 하면 왜 낮/밤 빛이 동시에 켜지는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;669&quot; data-start=&quot;657&quot; data-ke-size=&quot;size20&quot;&gt;✅ 해결점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;760&quot; data-start=&quot;670&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;710&quot; data-start=&quot;670&quot;&gt;float 비교 (== 0.15f)는 오차 때문에 불안정.&lt;/li&gt;
&lt;li data-end=&quot;760&quot; data-start=&quot;711&quot;&gt;&lt;b&gt;명확한 낮/밤 시간 구간 (time) 기준&lt;/b&gt;으로 켜고 끄는 것이 더 안정적.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;774&quot; data-start=&quot;762&quot; data-ke-size=&quot;size20&quot;&gt;  예시&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;csharp&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;/span&gt;&lt;span&gt; isDayTime = time &amp;gt;= &lt;/span&gt;&lt;span&gt;&lt;span&gt;0.25f&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp; time &amp;lt;= &lt;/span&gt;&lt;span&gt;&lt;span&gt;0.75f&lt;/span&gt;&lt;/span&gt;&lt;span&gt;; sun.SetActive(isDayTime); moon.SetActive(!isDayTime); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;896&quot; data-start=&quot;893&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;931&quot; data-start=&quot;898&quot; data-ke-size=&quot;size23&quot;&gt;  Input System - 숫자 키 1~7 처리&lt;/h3&gt;
&lt;h4 data-end=&quot;945&quot; data-start=&quot;933&quot; data-ke-size=&quot;size20&quot;&gt;❓ 의문점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1038&quot; data-start=&quot;946&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;985&quot; data-start=&quot;946&quot;&gt;Input System에서 숫자 키를 누르면 어떤 값을 받는가?&lt;/li&gt;
&lt;li data-end=&quot;1038&quot; data-start=&quot;986&quot;&gt;ReadValue&amp;lt;int&amp;gt;() - 1 방식으로 0~6 인덱스를 정확히 받을 수 있는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;1052&quot; data-start=&quot;1040&quot; data-ke-size=&quot;size20&quot;&gt;✅ 해결점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1136&quot; data-start=&quot;1053&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1095&quot; data-start=&quot;1053&quot;&gt;Input System에서는 &lt;b&gt;각 키에 별도 액션을 바인딩&lt;/b&gt;하거나&lt;/li&gt;
&lt;li data-end=&quot;1136&quot; data-start=&quot;1096&quot;&gt;Key.1 ~ Key.7을 수동으로 매핑해서 처리해야 정확함.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;1150&quot; data-start=&quot;1138&quot; data-ke-size=&quot;size20&quot;&gt;  예시&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;csharp&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;if&lt;/span&gt;&lt;/span&gt;&lt;span&gt; (Keyboard.current.digit1Key.wasPressedThisFrame) UseQuickSlot(&lt;/span&gt;&lt;span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;&lt;span&gt;// ... 반복&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;1248&quot; data-start=&quot;1245&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1276&quot; data-start=&quot;1250&quot; data-ke-size=&quot;size23&quot;&gt;  인벤토리 &amp;harr; 퀵슬롯 간 아이템 이동&lt;/h3&gt;
&lt;h4 data-end=&quot;1290&quot; data-start=&quot;1278&quot; data-ke-size=&quot;size20&quot;&gt;❓ 의문점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1347&quot; data-start=&quot;1291&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1347&quot; data-start=&quot;1291&quot;&gt;ItemSlot을 참조형으로 넘기면, 퀵슬롯 수량이 바뀌었을 때 인벤토리도 같이 바뀌지 않나?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;1361&quot; data-start=&quot;1349&quot; data-ke-size=&quot;size20&quot;&gt;✅ 해결점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1447&quot; data-start=&quot;1362&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1381&quot; data-start=&quot;1362&quot;&gt;참조형이라면 당연히 연결됨.&lt;/li&gt;
&lt;li data-end=&quot;1447&quot; data-start=&quot;1382&quot;&gt;&lt;b&gt;깊은 복사&lt;/b&gt;를 위해 new ItemSlot(otherSlot) 같은 &lt;b&gt;복사 생성자&lt;/b&gt;를 구현해야 안전.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;1461&quot; data-start=&quot;1449&quot; data-ke-size=&quot;size20&quot;&gt;  예시&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;csharp&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;ItemSlot&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;ItemSlot other&lt;/span&gt;&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;&lt;span&gt;this&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.item = other.item; &lt;/span&gt;&lt;span&gt;&lt;span&gt;this&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.count = other.count; } &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;1574&quot; data-start=&quot;1571&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1602&quot; data-start=&quot;1576&quot; data-ke-size=&quot;size23&quot;&gt;  NavMesh 랜덤 위치 지정 함수&lt;/h3&gt;
&lt;h4 data-end=&quot;1616&quot; data-start=&quot;1604&quot; data-ke-size=&quot;size20&quot;&gt;❓ 의문점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1689&quot; data-start=&quot;1617&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1662&quot; data-start=&quot;1617&quot;&gt;NavMesh.SamplePosition()이 실패하는 경우가 있는가?&lt;/li&gt;
&lt;li data-end=&quot;1689&quot; data-start=&quot;1663&quot;&gt;왜 항상 범위 내에서 결과가 나오지 않을까?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;1703&quot; data-start=&quot;1691&quot; data-ke-size=&quot;size20&quot;&gt;✅ 해결점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1764&quot; data-start=&quot;1704&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1729&quot; data-start=&quot;1704&quot;&gt;샘플링 범위 내 지형이 없다면 실패함.&lt;/li&gt;
&lt;li data-end=&quot;1764&quot; data-start=&quot;1730&quot;&gt;&lt;b&gt;반복 재시도&lt;/b&gt; + range 조정으로 보완 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;1778&quot; data-start=&quot;1766&quot; data-ke-size=&quot;size20&quot;&gt;  예시&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;csharp&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;for&lt;/span&gt;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span&gt; i = &lt;/span&gt;&lt;span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/span&gt;&lt;span&gt;; i &amp;lt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;span&gt;; i++) { &lt;/span&gt;&lt;span&gt;&lt;span&gt;if&lt;/span&gt;&lt;/span&gt;&lt;span&gt; (NavMesh.SamplePosition(...)) &lt;/span&gt;&lt;span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/span&gt;&lt;span&gt; hit.position; } Debug.LogWarning(&lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;유효한 위치를 찾지 못했습니다.&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;1927&quot; data-start=&quot;1924&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1944&quot; data-start=&quot;1929&quot; data-ke-size=&quot;size23&quot;&gt;⏳ 날짜 카운트 방식&lt;/h3&gt;
&lt;h4 data-end=&quot;1958&quot; data-start=&quot;1946&quot; data-ke-size=&quot;size20&quot;&gt;❓ 의문점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2021&quot; data-start=&quot;1959&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2021&quot; data-start=&quot;1959&quot;&gt;time = (time + rate * deltaTime) % 1 구조에서 언제 날짜를 증가시켜야 할까?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;2035&quot; data-start=&quot;2023&quot; data-ke-size=&quot;size20&quot;&gt;✅ 해결점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2099&quot; data-start=&quot;2036&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2099&quot; data-start=&quot;2036&quot;&gt;prevTime &amp;gt; time인 순간은 &lt;b&gt;0을 지나간 시점&lt;/b&gt;, 즉 &lt;b&gt;하루가 지난 것&lt;/b&gt;으로 판단 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;2113&quot; data-start=&quot;2101&quot; data-ke-size=&quot;size20&quot;&gt;  예시&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;csharp&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;if&lt;/span&gt;&lt;/span&gt;&lt;span&gt; (time &amp;lt; prevTime) ++dayCount; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;2169&quot; data-start=&quot;2166&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2179&quot; data-start=&quot;2171&quot; data-ke-size=&quot;size26&quot;&gt;  정리&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2416&quot; data-start=&quot;2181&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2219&quot; data-start=&quot;2181&quot;&gt;단순 기능에서 역할을 확장할 땐 &lt;b&gt;모듈화와 책임 분리&lt;/b&gt;가 핵심&lt;/li&gt;
&lt;li data-end=&quot;2262&quot; data-start=&quot;2220&quot;&gt;Unity의 float 기반 값 비교는 &lt;b&gt;절대 == 하지 말 것&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;2316&quot; data-start=&quot;2263&quot;&gt;Input System의 유연성은 높지만, 복잡한 키 매핑은 &lt;b&gt;명시적으로 처리해야 확실&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;2363&quot; data-start=&quot;2317&quot;&gt;데이터 구조가 &lt;b&gt;참조형&lt;/b&gt;일 땐, 상태 공유에 주의하고 필요시 깊은 복사 고려&lt;/li&gt;
&lt;li data-end=&quot;2416&quot; data-start=&quot;2364&quot;&gt;NavMesh나 시간 기반 계산 등은 &lt;b&gt;실패 가능성에 대한 대비 로직&lt;/b&gt;을 항상 포함&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>[내일배움캠프 Unity 9기]</category>
      <author>kyvv</author>
      <guid isPermaLink="true">https://kyvv.tistory.com/49</guid>
      <comments>https://kyvv.tistory.com/49#entry49comment</comments>
      <pubDate>Fri, 30 May 2025 22:21:37 +0900</pubDate>
    </item>
    <item>
      <title>05/29 인벤토리 시스템 구조 개선 및 버그 수정</title>
      <link>https://kyvv.tistory.com/48</link>
      <description>&lt;h4 data-end=&quot;137&quot; data-start=&quot;125&quot; data-ke-size=&quot;size20&quot;&gt;✅ 학습 내용&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;373&quot; data-start=&quot;138&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;234&quot; data-start=&quot;138&quot;&gt;PlayerInventoryController 클래스 내에서 items 리스트는 inventoryItems 리스트와 &lt;b&gt;중복되는 데이터&lt;/b&gt;라는 사실을 파악함.&lt;/li&gt;
&lt;li data-end=&quot;316&quot; data-start=&quot;235&quot;&gt;items는 ItemSlot 내부의 item과 1:1로 연결되어 있어, 모든 기능을 inventoryItems만으로 구현 가능.&lt;/li&gt;
&lt;li data-end=&quot;373&quot; data-start=&quot;317&quot;&gt;불필요한 리스트(items)는 메모리 낭비 및 유지보수 부담을 야기할 수 있으므로 제거 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;391&quot; data-start=&quot;375&quot; data-ke-size=&quot;size20&quot;&gt; ️ 리팩토링 방향&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;686&quot; data-start=&quot;392&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;447&quot; data-start=&quot;392&quot;&gt;items[index]를 전부 inventoryItems[index].item으로 변경.&lt;/li&gt;
&lt;li data-end=&quot;601&quot; data-start=&quot;448&quot;&gt;외부에서 ItemData 목록이 필요할 경우:&lt;/li&gt;
&lt;li data-end=&quot;601&quot; data-start=&quot;480&quot;&gt;
&lt;div&gt;csharp&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;/span&gt;&lt;span&gt; IReadOnlyList&amp;lt;ItemData&amp;gt; Items =&amp;gt; inventoryItems.Select(slot =&amp;gt; slot.item).ToList().AsReadOnly(); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li data-end=&quot;686&quot; data-start=&quot;602&quot;&gt;ItemSlot 클래스 내 item을 public ItemData Item { get; private set; } 식으로 캡슐화할 계획.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;700&quot; data-start=&quot;688&quot; data-ke-size=&quot;size20&quot;&gt;  느낀 점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;842&quot; data-start=&quot;701&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;798&quot; data-start=&quot;701&quot;&gt;구조 설계 시 &lt;b&gt;중복 데이터&lt;/b&gt;는 가능한 줄이고, **단일 책임 원칙(SRP)**에 따라 필요한 데이터는 한 곳에서만 관리하도록 설계하는 것이 유지보수에 훨씬 유리하다.&lt;/li&gt;
&lt;li data-end=&quot;842&quot; data-start=&quot;799&quot;&gt;데이터와 UI는 분리하되, 내부 구조는 최대한 단순하고 명확하게 가져가자.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-start=&quot;688&quot; data-end=&quot;700&quot; data-ke-size=&quot;size20&quot;&gt;  버그 수정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인벤토리에서 장착 아이템을 선택할 경우, 장착 슬롯으로 옮겨가는데 이 때 장착 아이템의 우측에 있던 아이템도 함께 지워지는 문제가 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 아이템 슬롯을 클릭할 때와 장착 아이템을 선택했을 때 로직이 모두 해당 아이템을 지우도록 호출되어서 생긴 문제(장착 함수에서 당연하게도 선택된 아이템이 인벤토리에서 지워질 것이라는 예상에 작업한 내용이 위와 같은 문제를 발생시킨 것)&lt;br /&gt;따라서 장착 함수 내에서 아이템을 지우는 코드를 제거하는 방향으로 합의&lt;/p&gt;</description>
      <category>[내일배움캠프 Unity 9기]</category>
      <author>kyvv</author>
      <guid isPermaLink="true">https://kyvv.tistory.com/48</guid>
      <comments>https://kyvv.tistory.com/48#entry48comment</comments>
      <pubDate>Thu, 29 May 2025 21:59:54 +0900</pubDate>
    </item>
    <item>
      <title>05/28 TIL Unity 매니저 싱글톤 설계 및 Resources.Load 문제 디버깅</title>
      <link>https://kyvv.tistory.com/47</link>
      <description>&lt;h3 data-end=&quot;195&quot; data-start=&quot;180&quot; data-ke-size=&quot;size23&quot;&gt;✅ 오늘 해결한 문제&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;387&quot; data-start=&quot;197&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;245&quot; data-start=&quot;197&quot;&gt;SpawnManager에서 NullReferenceException 발생&lt;/li&gt;
&lt;li data-end=&quot;387&quot; data-start=&quot;246&quot;&gt;Instance 호출 시 new GameObject().AddComponent&amp;lt;T&amp;gt;() 구조가 문제인가 의심했지만, 실제 원인은 &lt;b&gt;Resources.Load()가 null을 반환한 상태에서 .gameObject를 호출&lt;/b&gt;한 것이었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;392&quot; data-start=&quot;389&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;408&quot; data-start=&quot;394&quot; data-ke-size=&quot;size23&quot;&gt;  오늘 배운 것&lt;/h3&gt;
&lt;h4 data-end=&quot;460&quot; data-start=&quot;410&quot; data-ke-size=&quot;size20&quot;&gt;1. &lt;b&gt;Unity에서 AddComponent 시점에 Awake가 즉시 호출됨&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;619&quot; data-start=&quot;461&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;511&quot; data-start=&quot;461&quot;&gt;AddComponent&amp;lt;SpawnManager&amp;gt;() &amp;rarr; 즉시 Awake() 호출&lt;/li&gt;
&lt;li data-end=&quot;571&quot; data-start=&quot;512&quot;&gt;따라서 Awake() 안에서 Instance나 다른 매니저 참조 시 &lt;b&gt;순환 참조 위험&lt;/b&gt; 존재&lt;/li&gt;
&lt;li data-end=&quot;619&quot; data-start=&quot;572&quot;&gt;해결: Awake()에서는 참조 지양, Init() 분리해서 명시적 초기화&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;672&quot; data-start=&quot;621&quot; data-ke-size=&quot;size20&quot;&gt;2. &lt;b&gt;Resources.Load()는 경로가 잘못되면 null을 반환한다&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;722&quot; data-start=&quot;673&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;705&quot; data-start=&quot;673&quot;&gt;.gameObject처럼 바로 접근하면 NRE 발생&lt;/li&gt;
&lt;li data-end=&quot;722&quot; data-start=&quot;706&quot;&gt;항상 null 체크 필요:&lt;/li&gt;
&lt;li data-end=&quot;722&quot; data-start=&quot;706&quot;&gt;실제 마주한 문제점 --&amp;gt; 경로 문자열에 오타로 인해서 Prefab을 찾을 수 없었음&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1748434106390&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var rock = Resources.Load&amp;lt;GameObject&amp;gt;(&quot;경로&quot;); if (rock == null) { Debug.LogError(&quot;Prefab을 찾을 수 없습니다.&quot;); }
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;908&quot; data-start=&quot;848&quot; data-ke-size=&quot;size20&quot;&gt;3. &lt;b&gt;Resources.Load&amp;lt;GameObject&amp;gt;()의 반환값은 GameObject다&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;970&quot; data-start=&quot;909&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;950&quot; data-start=&quot;909&quot;&gt;.gameObject를 붙이면 오히려 불필요하거나 오류 발생 가능성&lt;/li&gt;
&lt;li data-end=&quot;970&quot; data-start=&quot;951&quot;&gt;즉, 아래처럼 사용하면 충분함:&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1748434121170&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var rock = Resources.Load&amp;lt;GameObject&amp;gt;(&quot;Items/Prefabs/Resource/stone&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;1105&quot; data-start=&quot;1057&quot; data-ke-size=&quot;size20&quot;&gt;4. &lt;b&gt;매니저 초기화는 생성(Create)과 초기화(Init)를 분리하자&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1144&quot; data-start=&quot;1106&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1138&quot; data-start=&quot;1106&quot;&gt;Instance 생성과 초기화가 꼬이지 않도록 분리&lt;/li&gt;
&lt;li data-end=&quot;1144&quot; data-start=&quot;1139&quot;&gt;예시:&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1748434129191&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SpawnManager.CreateIfNeeded(); SpawnManager.Instance.Init();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;1224&quot; data-start=&quot;1221&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1242&quot; data-start=&quot;1226&quot; data-ke-size=&quot;size23&quot;&gt;  리팩터링 고려사항&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1394&quot; data-start=&quot;1244&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1298&quot; data-start=&quot;1244&quot;&gt;Resources.Load()를 대체할 수 있는 Addressable 시스템 도입 고려&lt;/li&gt;
&lt;li data-end=&quot;1360&quot; data-start=&quot;1299&quot;&gt;매니저 자동 등록 시스템: ManagerBootstrapper, IModule 인터페이스 설계 가능&lt;/li&gt;
&lt;li data-end=&quot;1394&quot; data-start=&quot;1361&quot;&gt;오브젝트 풀을 T 타입 기반으로 설계해 재사용성 강화&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>[내일배움캠프 Unity 9기]</category>
      <author>kyvv</author>
      <guid isPermaLink="true">https://kyvv.tistory.com/47</guid>
      <comments>https://kyvv.tistory.com/47#entry47comment</comments>
      <pubDate>Wed, 28 May 2025 21:12:23 +0900</pubDate>
    </item>
    <item>
      <title>05/27 TIL 오브젝트 풀에 관한 고찰</title>
      <link>https://kyvv.tistory.com/46</link>
      <description>&lt;h2 data-end=&quot;189&quot; data-start=&quot;177&quot; data-ke-size=&quot;size26&quot;&gt;✅ 오늘 배운 것&lt;/h2&gt;
&lt;h3 data-end=&quot;220&quot; data-start=&quot;191&quot; data-ke-size=&quot;size23&quot;&gt;1. &lt;b&gt;프리팹이 다르면 풀도 나눠야 한다&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;435&quot; data-start=&quot;221&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;335&quot; data-start=&quot;221&quot;&gt;WoodItem, RockItem처럼 ResourceItem을 상속한 클래스가 여러 개 있더라도,&lt;br /&gt;&lt;b&gt;프리팹(GameObject)&lt;/b&gt; 이 다르면 &lt;b&gt;하나의 풀에서 관리하면 안 됨&lt;/b&gt;.&lt;/li&gt;
&lt;li data-end=&quot;435&quot; data-start=&quot;336&quot;&gt;ObjectPool&amp;lt;T&amp;gt;의 createFunc는 단 하나의 프리팹으로 고정되기 때문에&lt;br /&gt;나중에 다른 프리팹을 넣거나 생성하면 &lt;b&gt;의도하지 않은 결과가 발생&lt;/b&gt;함.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;472&quot; data-start=&quot;437&quot; data-ke-size=&quot;size23&quot;&gt;2. &lt;b&gt;풀은 '타입'이 아닌 '프리팹 단위'로 관리&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;727&quot; data-start=&quot;473&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;593&quot; data-start=&quot;473&quot;&gt;PoolManager&amp;lt;ResourceItem&amp;gt; 같은 구조에서 한 풀에 여러 종류의 아이템을 넣고 싶을 수 있으나,&lt;br /&gt;&lt;b&gt;각 프리팹마다 별개의 PoolManager를 생성&lt;/b&gt;하는 방식이 안전하고 명확하다.&lt;/li&gt;
&lt;li data-end=&quot;727&quot; data-start=&quot;594&quot;&gt;따라서 Dictionary&amp;lt;GameObject, PoolManager&amp;lt;ResourceItem&amp;gt;&amp;gt; 혹은&lt;br /&gt;Dictionary&amp;lt;string, PoolManager&amp;lt;ResourceItem&amp;gt;&amp;gt; 와 같은 구조를 사용하는 것이 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;757&quot; data-start=&quot;729&quot; data-ke-size=&quot;size23&quot;&gt;3. &lt;b&gt;프리팹 기준 키로 풀 분기 처리&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;pre id=&quot;code_1748347977714&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (!pools.ContainsKey(prefab)) 
{
 	pools[prefab] = new PoolManager&amp;lt;ResourceItem&amp;gt;(prefab.GetComponent&amp;lt;ResourceItem&amp;gt;(), transform);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;972&quot; data-start=&quot;907&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;943&quot; data-start=&quot;907&quot;&gt;프리팹 기준으로 풀을 만들어두고, 같은 프리팹이면 재사용.&lt;/li&gt;
&lt;li data-end=&quot;972&quot; data-start=&quot;944&quot;&gt;다른 프리팹이 들어오면 새로 풀을 만들어 할당.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;977&quot; data-start=&quot;974&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;987&quot; data-start=&quot;979&quot; data-ke-size=&quot;size26&quot;&gt;  정리&lt;/h2&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1262&quot; data-start=&quot;989&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;구분&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;잘못된 예&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;올바른 예&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1104&quot; data-start=&quot;1047&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1054&quot; data-start=&quot;1047&quot;&gt;풀 기준&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1080&quot; data-start=&quot;1054&quot;&gt;ResourceItem 타입으로 하나의 풀&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;1104&quot; data-start=&quot;1080&quot;&gt;프리팹마다 PoolManager 분리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1160&quot; data-start=&quot;1105&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1113&quot; data-start=&quot;1105&quot;&gt;생성 방식&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1139&quot; data-start=&quot;1113&quot;&gt;createFunc 하나로 여러 종류 생성&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;1160&quot; data-start=&quot;1139&quot;&gt;프리팹 기준으로 개별 생성 함수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1262&quot; data-start=&quot;1161&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1169&quot; data-start=&quot;1161&quot;&gt;사용 구조&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1208&quot; data-start=&quot;1169&quot;&gt;PoolManager&amp;lt;ResourceItem&amp;gt; 하나로 다 처리&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;1262&quot; data-start=&quot;1208&quot;&gt;Dictionary&amp;lt;Prefab, PoolManager&amp;lt;ResourceItem&amp;gt;&amp;gt; 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-end=&quot;1267&quot; data-start=&quot;1264&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1280&quot; data-start=&quot;1269&quot; data-ke-size=&quot;size26&quot;&gt; ️ 느낀 점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1466&quot; data-start=&quot;1281&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1382&quot; data-start=&quot;1281&quot;&gt;처음에는 &quot;같은 타입인데 왜 다른 풀로 나눠야 하지?&quot;라고 생각했지만,&lt;br /&gt;Unity에서 &lt;b&gt;프리팹 = 생성의 기준&lt;/b&gt;이기 때문에 풀도 프리팹 단위로 쪼개는 것이 자연스러움.&lt;/li&gt;
&lt;li data-end=&quot;1382&quot; data-start=&quot;1281&quot;&gt;프리팹 별로 풀이 생성되는 측면이 유지/보수 측면에서 더 유리하다.(기능별로&amp;nbsp; 인터페이스를 받거나 상속 구조로 갈 수는 있긴 하다)&lt;/li&gt;
&lt;li data-end=&quot;1466&quot; data-start=&quot;1383&quot;&gt;설계를 미리 고려하지 않으면 풀 구조가 꼬일 수 있기 때문에&lt;br /&gt;&lt;b&gt;프리팹 &amp;harr; 풀의 관계를 명확히 분리하는 설계가 중요&lt;/b&gt;하다는 걸 체감했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1471&quot; data-start=&quot;1468&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1486&quot; data-start=&quot;1473&quot; data-ke-size=&quot;size26&quot;&gt; ️ 내일 할 일&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1615&quot; data-start=&quot;1487&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1528&quot; data-start=&quot;1487&quot;&gt;SpawnManager 내에서 프리팹 기준으로 풀을 관리하는 구조 완성&lt;/li&gt;
&lt;li data-end=&quot;1585&quot; data-start=&quot;1529&quot;&gt;ItemData에 GetPrefab() 같은 접근자를 두어 풀 등록 시 사용하기 쉽게 개선&lt;/li&gt;
&lt;li data-end=&quot;1615&quot; data-start=&quot;1586&quot;&gt;풀 생성과 반환 시 디버깅 로그 추가로 흐름 추적&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>[내일배움캠프 Unity 9기]</category>
      <author>kyvv</author>
      <guid isPermaLink="true">https://kyvv.tistory.com/46</guid>
      <comments>https://kyvv.tistory.com/46#entry46comment</comments>
      <pubDate>Tue, 27 May 2025 21:15:17 +0900</pubDate>
    </item>
  </channel>
</rss>