[task] | instruction_following [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | ParticleServiceTest02 스크립트 컴포넌트의 Property 블록에 선언된 두 변수의 이름과 타입을 2열 3행(헤더 포함) 표로 정리하세요. [answer] | | 이름 | 타입 | | :--- | :--- | | ResetEntity | Entity | | SpawnList | SyncTable<number> | [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 반복 재생되는 파티클을 생성하거나 삭제하는 방법을 알아봅시다. 특정 엔티티에 캐릭터가 닿으면 파티클이 생성되다가 캐릭터가 목표 지점에 도착하면 파티클 생성이 멈추는 예제를 만들어보겠습니다. 1. 파티클을 뿜어낼 엔티티와 목표 엔티티를 배치합니다. 본 예제에서는 파티클을 뿜어낼 엔티티로 **object-24**(호리병)을, 목표 엔티티로는 **object-928**(소화기)를 사용했습니다. 2. 배치한 모든 엔티티에 TriggerComponent를 추가합니다. 3. Workspace - MyDesk에 새
[task] | single_turn [pass] | ⏳ 미판정 [title] | 웹 브라우저 활용하기 [question] | WebViewComponent의 Scroll 메서드를 사용할 때 Vector2의 값이 양수면 아래로, 음수면 위로 이동하는 것 같은데, 실제 동작 방향과 매개변수 의미는 어떻게 되나요? [answer] | 제공된 참고 문서에는 `WebViewComponent`의 `Scroll` 메서드에서 `Vector2` 매개변수의 값이 양수/음수일 때의 실제 스크롤 방향(위/아래)에 대한 명시적인 설명이 포함되어 있지 않습니다. 문서에서 확인할 수 있는 정보는 다음과 같습니다: 1. `Scroll(Vector2(x, y))` 메서드가 존재하며, `Vector2` 인자를 받습니다. 2. 예제 코드에서는 다음과 같이 사용됩니다: * `Home` 키 입력 시: `self.Entity.WebViewComponent:Scroll(Vecto [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | UI로 웹 브라우저를 배치하면 화면의 특정 위치에 항상 웹 브라우저가 보이도록 할 수 있습니다. 1. **Hierarchy - ui** 아래에서 원하는 UI 그룹의 콘텍스트 메뉴를 엽니다. **Create Entity - Create UIEmpty**를 선택해 **UIEmpty**를 생성합니다. 2. 프로퍼티 에디터에서 **UIEmpty**에 **WebViewComponent**를 추가하고 원하는 Url을 입력합니다. 3. 엔티티의 크기를 적절하게 조절한 후 **[시작]** 버튼을 눌러 테스트해 봅시다. 화면의 특정 위치에
[task] | two_turn [pass] | ⏳ 미판정 [title] | 루아 프로파일러를 활용하여 최적화하기 [question] | MonsterController의 OnUpdate처럼 호출 횟수가 많지만 평균 실행 시간이 짧은 함수의 총 실행 시간이 길어지는 현상은 어떤 원인으로 설명되며, 이를 해결하기 위해 스크립트에서 어떤 최적화 전략을 적용해야 하나요? [answer] | **원인 분석** MonsterController의 `OnUpdate`와 같이 호출 횟수가 많지만 평균 실행 시간이 매우 짧은 함수의 총 실행 시간이 길어지는 현상은 **높은 호출 빈도** 때문입니다. 개별 함수 실행 시간은 짧더라도, 게임 프레임마다 반복적으로 호출될 경우 누적된 비용이 전체 성능에 상당한 영향을 미칩니다. 특히 단순한 프로퍼티 접근이나 로직 처리라도 호출 횟수가 많으면 그만큼 시스템 부하가 증가하여 총 실행 시간이 길어집니다. **최적화 전략** 이러한 문제를 해결하기 위해 스크립트에서 다음과 같은 최적화 [followup] | 프로파일링 결과 수정이 필요해 보이지만 내용이 긴 스크립트 함수의 세부 분석을 위해 `profiler.beginscope`과 `profiler.endscope`를 어떻게 사용하여 표본을 추출할 수 있는 코드 예시를 보여주세요? [followup_answer] | 프로파일링 결과에서 수정이 필요해 보이지만 내용이 긴 스크립트 함수의 세부 분석을 위해 `profiler.beginscope`과 `profiler.endscope`를 사용하는 방법은 다음과 같습니다. 분석하려는 함수 내부에서 특정 코드 구간(루프, 로직 블록 등)의 시작 위치에 `profiler.beginscope("이름")`을, 해당 구간의 종료 위치에 `profiler.endscope()`를 배치합니다. 이렇게 하면 프로파일링 데이터에서 해당 구간이 독립적인 표본으로 분리되어 상세한 실행 시간을 확인할 수 있습니다. 아래는 [scores] | [judge_reason] | [source_doc] | 샘플 데이터를 보면 Frame의 Total Self Time이 전체의 62% 이상을 차지하는 것을 알 수 있습니다. Frame에서의 Self Time은 스크립트 실행을 제외하고 Native에서 소요된 시간이므로 Native Scope의 세부 분석이 필요한 상황입니다. 루아 프로파일러의 **File - Option**에서 **Native Scope**에 체크한 후 다시 프로파일링해봅시다. 다시 수집한 데이터의 카테고리를 살펴보면 Native Scope 세부 분석이 이루어졌음을 알 수 있습니다. Frame의 Total Self T
[task] | two_turn [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | 캐릭터가 특정 엔티티와 충돌할 때 파티클 재생을 멈추는 방법을 알고 싶다 [answer] | 캐릭터가 특정 엔티티와 충돌(트리거 진입)할 때 파티클 재생을 멈추려면, 캐릭터에 `BasicParticleComponent`를 추가하고 트리거 이벤트를 처리하는 스크립트를 작성하면 됩니다. 구현 단계를 설명드리면 다음과 같습니다. 1. **캐릭터에 파티클 컴포넌트 추가**: `Workspace > DefaultPlayer`의 Property에서 `BasicParticleComponent`를 추가합니다. 원하는 파티클(예: `FireField`)을 설정합니다. 2. **스크립트 컴포넌트 생성**: `Workspace > My [followup] | `TriggerEnterEvent` 핸들러 내에서 `Stop()`을 호출하여 FireField 파티클을 제어하는 스크립트 구조와 `TriggerComponent` 설정 과정은 어떻게 되나? [followup_answer] | `TriggerEnterEvent` 핸들러 내에서 `Stop()`을 호출하여 FireField 파티클을 제어하는 스크립트 구조와 `TriggerComponent` 설정 과정은 다음과 같습니다. ### 1. 스크립트 구조 캐릭터(`DefaultPlayer`)에 파티클을 붙이고, 충돌 시 멈추게 하려면 다음과 같이 구성합니다. 1. **컴포넌트 추가**: * `Workspace > DefaultPlayer`의 Property에 `BasicParticleComponent`를 추가합니다. * `ParticleT [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 [파티클 사용하기](/docs/?postId=1036) 가이드에서 파티클 컴포넌트의 개념 및 종류에 대해 알아보았습니다. 이번 시간에는 스크립트를 사용해 파티클을 활용하는 예제를 살펴보겠습니다. # 파티클 스크립트 ## 파티클 프로퍼티 제어 캐릭터와의 거리에 따라 파티클의 재생 속도가 바뀌는 예제를 통해 파티클 프로퍼티를 제어하는 방법을 살펴봅시다. 1. 파티클이 잘 보이도록 어두운 배경을 설정하고 지형을 배치한 뒤 원하는 파티클을 배치합니다. 본 예제에서는 Background로 **back-16**을 설
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | UIGroupComponent의 DefaultShow 프로퍼티를 설정하는 방법을 2문장 이내로 설명하세요. [answer] | UIGroup에서 UIGroupComponent를 선택한 뒤 DefaultShow 프로퍼티를 true로 설정합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 파티클을 재생할 수 있는 UI를 만들어봅시다. 1. **Hierachy - World - ui**에 새로운 **UIGroup**을 추가합니다. 2. 추가한 UIGroup에서 **UIGroupComponent**의 **DefaultShow** 프로퍼티를 **true**로 설정합니다. ![[object Object]](https://mod-file.dn.nexoncdn.co.kr/bbs/1738820526946c8b71422566e4a919660cc52294d2f78.png "DefaultShow") 3. UIGroup에서 **콘
[task] | single_turn [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | BasicParticleComponent의 PlaySpeed 프로퍼티에 거리 값을 그대로 대입하면, 캐릭터가 매우 가까울 때 파티클 재생이 완전히 멈추지 않는 현상을 어떻게 해결할 수 있나요? [answer] | 제공된 참고 문서에는 `BasicParticleComponent`의 `PlaySpeed` 프로퍼티에 거리 값을 대입하는 예제와 `Play()`, `Stop()` 함수의 사용법에 대한 정보만 포함되어 있습니다. 문서에는 `PlaySpeed`가 0 이하가 될 때나 특정 임계값 미만일 때 파티클 재생이 어떻게 처리되는지에 대한 설명, 또는 `PlaySpeed` 값이 0에 가까울 때 재생이 멈추지 않는 현상을 해결하기 위한 `Mathf.Clamp`, `if` 조건문 등 구체적인 해결 방법이나 관련 API가 문서화되어 있지 않습니다. 따 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 [파티클 사용하기](/docs/?postId=1036) 가이드에서 파티클 컴포넌트의 개념 및 종류에 대해 알아보았습니다. 이번 시간에는 스크립트를 사용해 파티클을 활용하는 예제를 살펴보겠습니다. # 파티클 스크립트 ## 파티클 프로퍼티 제어 캐릭터와의 거리에 따라 파티클의 재생 속도가 바뀌는 예제를 통해 파티클 프로퍼티를 제어하는 방법을 살펴봅시다. 1. 파티클이 잘 보이도록 어두운 배경을 설정하고 지형을 배치한 뒤 원하는 파티클을 배치합니다. 본 예제에서는 Background로 **back-16**을 설
[task] | two_turn [pass] | ⏳ 미판정 [title] | 웹 브라우저 활용하기 [question] | KeyDownEvent 핸들러 내에서 self.Entity.WebViewComponent:GoBack() 등의 메서드를 호출하여 키 입력으로 웹 브라우저를 제어하는 mLua 코드 예시를 보여주세요. [answer] | 키 입력으로 웹 브라우저를 제어하는 mLua 코드 예시는 다음과 같습니다. `KeyDownEvent` 핸들러 내에서 특정 키가 입력되면 `self.Entity.WebViewComponent`의 메서드를 호출하여 웹 브라우저의 뒤로 가기, 앞으로 가기, 새로 고침, 확대/축소, 스크롤 기능을 수행합니다. ```lua Event Handler: [service: InputService] HandleKeyDownEvent(KeyDownEvent event) { --------------- Native Event Sender In [followup] | 만약 엔티티에 WebViewComponent가 없거나 키 입력이 서버에서만 처리되어야 하는 경우, 해당 코드를 수정하거나 에러를 방지하는 방법은 무엇인가요? [followup_answer] | 제공된 참고 문서에는 `WebViewComponent`가 없는 경우의 에러 방지 처리 방법이나, 키 입력을 서버에서 처리하도록 수정하는 방법에 대한 정보가 포함되어 있지 않습니다. 문서에는 클라이언트 공간(`Space: Client`)에서 `KeyDownEvent`를 처리하여 `self.Entity.WebViewComponent`의 메서드를 호출하는 예제만 제시되어 있으며, 컴포넌트 존재 여부 확인 로직이나 서버/클라이언트 실행 공간 변경에 대한 내용은 없습니다. [scores] | [judge_reason] | [source_doc] | UI로 웹 브라우저를 배치하면 화면의 특정 위치에 항상 웹 브라우저가 보이도록 할 수 있습니다. 1. **Hierarchy - ui** 아래에서 원하는 UI 그룹의 콘텍스트 메뉴를 엽니다. **Create Entity - Create UIEmpty**를 선택해 **UIEmpty**를 생성합니다. 2. 프로퍼티 에디터에서 **UIEmpty**에 **WebViewComponent**를 추가하고 원하는 Url을 입력합니다. 3. 엔티티의 크기를 적절하게 조절한 후 **[시작]** 버튼을 눌러 테스트해 봅시다. 화면의 특정 위치에
[task] | two_turn [pass] | ⏳ 미판정 [title] | 엔티티에 물리 적용하기 [question] | `SetLinearVelocity()` 함수는 질량 값과 관계없이 속도를 설정한다고 하는데, 이 함수를 사용했을 때 기존에 가해지고 있던 힘(`ApplyForce`)의 영향을 어떻게 받는지, 그리고 `ClientOnly`가 `true`인 경우와 `false`인 경우 물리 연산 동기화 차이가 어떤 상황(예: 다중 클라이언트 환경)에서 문제로 나타날 수 있는지 설명해 주세요. [answer] | 제공된 문서만으로는 `SetLinearVelocity()` 함수를 호출했을 때 기존에 가해지고 있던 `ApplyForce()`의 영향에 대해 명시적으로 설명하고 있지 않습니다. 따라서 두 함수가 동시에 적용될 때의 구체적인 물리 엔진 동작이나 우선순위에 대해 답변할 수 없습니다. 다만, `ClientOnly` 프로퍼티 설정에 따른 물리 연산 동기화 차이는 다음과 같이 설명할 수 있습니다. **1. `ClientOnly`가 `true`인 경우** * 물리 연산이 **Client(클라이언트) 공간**에서 수행됩니다. * 함수 [followup] | `ClientOnly`가 `false`인 서버 사이드 스크립트에서 엔티티의 속도를 0으로 초기화하기 위해 `SetLinearVelocity(Vector2(0,0))`를 호출하는 `OnBeginPlay` 함수 코드를 작성해 주세요. [followup_answer] | ```lua Method: [server] void OnBeginPlay() { self.Entity.PhysicsRigidbodyComponent:SetLinearVelocity(Vector2(0, 0)) } ``` [scores] | [judge_reason] | [source_doc] | #### 힘을 가하는 함수 `ApplyForce()`, `ApplyTorque()` 함수는 지속적인 힘을 가할 수 있습니다. 특정 Key를 눌러 지속적으로 특정 방향으로 힘 가하고 싶을 때가 해당됩니다. 매개 변수 force는 힘을 의미합니다. 해당 Entity에 대응하는 물리 강체의 질량 값에 영향을 받습니다. #### 충격량을 적용하는 함수 `ApplyAngularImpulse()`, `ApplyLinearImpulse()` 함수는 일시적으로 짧은 충격을 가할 수 있습니다. 대포 발파, 방망이 휘두르기 같은 짧은 충격을 주
[task] | single_turn [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | 캐릭터가 트리거 영역에 진입할 때 파티클을 멈추는 예제에서 TriggerBodyEntity 변수를 선언만 하고 사용하지 않는 이유는 무엇인가요? [answer] | 제시된 예제에서 `TriggerBodyEntity` 변수를 선언하고도 실제 로직에서 사용하지 않는 이유는, 해당 스크립트가 **어떤 객체가 트리거 영역에 들어왔는지에 상관없이** 파티클을 멈추는 동작을 수행하도록 의도되었기 때문입니다. 참고 문서의 '파티클 재생 상태 변경' 예제를 보면, 이벤트 핸들러 내부에서 특정 엔티티 이름이나 타입을 확인하는 조건문(`if`문)이 없습니다. 단순히 `HandleTriggerEnterEvent`가 발동되면 무조건적으로 `self.Entity.BasicParticleComponent:Stop() [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 [파티클 사용하기](/docs/?postId=1036) 가이드에서 파티클 컴포넌트의 개념 및 종류에 대해 알아보았습니다. 이번 시간에는 스크립트를 사용해 파티클을 활용하는 예제를 살펴보겠습니다. # 파티클 스크립트 ## 파티클 프로퍼티 제어 캐릭터와의 거리에 따라 파티클의 재생 속도가 바뀌는 예제를 통해 파티클 프로퍼티를 제어하는 방법을 살펴봅시다. 1. 파티클이 잘 보이도록 어두운 배경을 설정하고 지형을 배치한 뒤 원하는 파티클을 배치합니다. 본 예제에서는 Background로 **back-16**을 설
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | 파티클이 시작될 때와 루프할 때 각각 어떤 이벤트 핸들러 함수를 호출해야 하는지 설명하세요. [answer] | 파티클이 시작될 때와 루프할 때 각각 다른 이벤트 핸들러 함수를 사용해야 합니다. 1. **파티클 시작 시**: `HandleParticleEmitStartEvent` 함수를 호출해야 합니다. 이 이벤트는 파티클이 처음 시작될 때 발생하며, 해당 핸들러 내부에서 원하는 로직(예: 대미지 공격 등)을 실행할 수 있습니다. 2. **파티클 루프 시**: `HandleParticleLoopEvent` 함수를 호출해야 합니다. 이 이벤트는 파티클이 반복(루프)될 때마다 발생하며, 이 핸들러 내부에서도 동일한 로직을 실행하여 반복적인 효 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 파티클 이벤트를 활용하여 파티클을 반복 생성할 때마다 대미지를 주거나 연출을 보여줄 수 있습니다. 번개가 칠 때마다 공격 기능이 작동하여 캐릭터에게 대미지를 주는 예제를 통해 파티클 이벤트의 활용 방법을 살펴봅시다. 1. Preset List - **LightningStrikeSharp** 파티클을 배치합니다. 2. AttackComponent를 Extend하여 새 스크립트 컴포넌트 ExtendAttackComponent를 생성합니다. 3. ExtendAttackComponent를 열고 `OnLightni
[task] | code [pass] | ⏳ 미판정 [title] | 루아 프로파일러를 활용하여 최적화하기 [question] | self:MyMethod() 호출 시 ServerElapsedSeconds 가 길어지는 원인을 찾기 위해 함수 본문 전체를 profiler.beginscope("MyMethod_Total") 과 profiler.endscope() 로 감싸고 내부의 각 주요 로직 블록을 별도 스킵으로 분리하여 측정하는 스크립트를 작성해줘 [answer] | `self:MyMethod()` 호출 시 `ServerElapsedSeconds`가 길어지는 원인을 찾기 위해, 요청하신 대로 함수 전체를 하나의 스킵으로 감싸고 내부 주요 로직을 별도 스킵으로 분리하는 방식의 스크립트입니다. 참고 문서에 따르면, `profiler.beginscope("name")`과 `profiler.endscope()`를 사용하여 특정 코드 구간의 실행 시간을 프로파일러에서 표본 추출할 수 있습니다. 아래 예제는 서버에서 실행되는 `OnUpdate` 내에서 `MyMethod`를 호출하고, `MyMethod` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 샘플 데이터를 보면 Frame의 Total Self Time이 전체의 62% 이상을 차지하는 것을 알 수 있습니다. Frame에서의 Self Time은 스크립트 실행을 제외하고 Native에서 소요된 시간이므로 Native Scope의 세부 분석이 필요한 상황입니다. 루아 프로파일러의 **File - Option**에서 **Native Scope**에 체크한 후 다시 프로파일링해봅시다. 다시 수집한 데이터의 카테고리를 살펴보면 Native Scope 세부 분석이 이루어졌음을 알 수 있습니다. Frame의 Total Self T
[task] | code [pass] | ⏳ 미판정 [title] | 루아 프로파일러를 활용하여 최적화하기 [question] | TriggerComponent 의 OnUpdate 메서드 내부에 profiler.beginscope("TriggerCheck") 과 profiler.endscope() 를 삽입하여 네이티브 함수 호출의 실제 소요 시간을 프로파일링 데이터로 추출하는 스크립트를 작성해줘 [answer] | TriggerComponent의 `OnUpdate`는 네이티브(Native) 컴포넌트 내부에서 동작하는 함수이므로, 사용자가 직접 `OnUpdate` 메서드 본문을 작성하거나 수정하여 `profiler.beginscope`를 삽입할 수 없습니다. 따라서 요청하신 "TriggerComponent의 OnUpdate 메서드 내부에 직접 삽입"하는 방법은 불가능합니다. 대신, 문서에 따르면 네이티브 함수의 성능을 확인하려면 **루아 프로파일러의 설정**을 통해 분석해야 합니다. TriggerComponent의 `OnUpdate`가 프로 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 샘플 데이터를 보면 Frame의 Total Self Time이 전체의 62% 이상을 차지하는 것을 알 수 있습니다. Frame에서의 Self Time은 스크립트 실행을 제외하고 Native에서 소요된 시간이므로 Native Scope의 세부 분석이 필요한 상황입니다. 루아 프로파일러의 **File - Option**에서 **Native Scope**에 체크한 후 다시 프로파일링해봅시다. 다시 수집한 데이터의 카테고리를 살펴보면 Native Scope 세부 분석이 이루어졌음을 알 수 있습니다. Frame의 Total Self T
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | 문서에서 언급된 콘텍스트 메뉴 경로와 대상 엔티티 이름을 표로 정리해서 출력하세요. [answer] | 문서에 언급된 콘텍스트 메뉴 경로와 대상 엔티티 이름은 다음과 같습니다. | 대상 엔티티 | 콘텍스트 메뉴 경로 | 결과 (생성/수정) | | :--- | :--- | :--- | | **UIGroup** | Create Empty > Create Button | 새로운 **UIButton** 추가 | | **UIButton** | Create Entity as Child > Create UIEmpty | **UIEmpty** 엔티티 생성 (이름을 **UIParticle**로 변경) | [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 파티클을 재생할 수 있는 UI를 만들어봅시다. 1. **Hierachy - World - ui**에 새로운 **UIGroup**을 추가합니다. 2. 추가한 UIGroup에서 **UIGroupComponent**의 **DefaultShow** 프로퍼티를 **true**로 설정합니다. ![[object Object]](https://mod-file.dn.nexoncdn.co.kr/bbs/1738820526946c8b71422566e4a919660cc52294d2f78.png "DefaultShow") 3. UIGroup에서 **콘
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | UIGroup에서 UIButton을 추가하고 자식으로 UIParticle을 생성하는 순서를 단계별 번호 목록으로 작성하세요. [answer] | UIGroup에서 UIButton을 추가하고 자식으로 UIParticle을 생성하는 순서는 다음과 같습니다. 1. **Hierarchy - World - ui**에 새로운 **UIGroup**을 추가합니다. 2. 추가한 UIGroup에서 **UIGroupComponent**의 **DefaultShow** 프로퍼티를 **true**로 설정합니다. 3. UIGroup에서 **콘텍스트 메뉴 - Create Empty - Create Button**을 눌러 새로운 **UIButton**을 추가합니다. 4. UIButton에서 **콘텍스트 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 파티클을 재생할 수 있는 UI를 만들어봅시다. 1. **Hierachy - World - ui**에 새로운 **UIGroup**을 추가합니다. 2. 추가한 UIGroup에서 **UIGroupComponent**의 **DefaultShow** 프로퍼티를 **true**로 설정합니다. ![[object Object]](https://mod-file.dn.nexoncdn.co.kr/bbs/1738820526946c8b71422566e4a919660cc52294d2f78.png "DefaultShow") 3. UIGroup에서 **콘
[task] | two_turn [pass] | ⏳ 미판정 [title] | 루아 프로파일러를 활용하여 최적화하기 [question] | 게임 플레이 중 특정 상황에서 처리 속도가 느려지는 병목 지점을 찾아 최적화하고 싶은데, 루아 프로파일러를 어떻게 활용하면 될까요? [answer] | 게임 플레이 중 특정 상황에서 처리 속도가 느려지는 병목 지점을 찾아 최적화하려면 루아 프로파일러를 사용하여 스크립트 실행 시간, 메모리 할당, 네트워크 트래픽 등을 측정하고 분석할 수 있습니다. 아래에 실행 방법과 분석 요소를 정리했습니다. ### 1. 루아 프로파일러 실행하기 루아 프로파일러를 실행하기 전, 윈도우 7 이상의 운영체제와 `.NET Core 3.1 Desktop Runtime` 이상 버전이 설치되어 있는지 확인해야 합니다. **제작 중인 월드에서 실행하는 경우:** 1. 게임 만들기 화면에서 **Window [followup] | 루아 프로파일러를 실행하기 위해 필요한 운영체제 및 .NET Core 3.1 Desktop Runtime 설치 조건과, 제작 중인 월드에서 Window 메뉴를 통해 프로파일러를 띄우는 구체적인 단계를 알려주세요. [followup_answer] | 루아 프로파일러를 실행하기 위한 환경 요구 사항과 제작 중인 월드에서 프로파일러를 실행하는 구체적인 단계는 다음과 같습니다. ### 1. 환경 요구 사항 (운영체제 및 런타임) 루아 프로파일러를 정상적으로 실행하려면 다음 조건을 충족해야 합니다. * **운영체제**: 최신 업데이트가 적용된 **윈도우 7 이상**의 운영체제여야 합니다. * **.NET Core Runtime**: **`.NET Core 3.1 Desktop Runtime`** 이상의 버전이 설치되어 있어야 합니다. * 만약 루아 프로파일러를 [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 제작한 게임을 플레이하다 보면 다양한 상황에서 느려지는 것을 경험할 수 있습니다. 이처럼 게임의 처리 속도에서 부하가 걸리는 병목 지점(Bottleneck)을 찾아 수정하는 것을 최적화라고 합니다. 일부 병목 지점만 해결해도 게임의 전체적인 성능 향상을 기대할 수 있기 때문에 최적화는 상당히 중요한 작업입니다. 루아 프로파일러는 이러한 스크립트 최적화 작업을 더욱 손쉽게 진행할 수 있도록 도와줍니다. 이번 시간에는 **루아 프로파일러**가 무엇인지 알아보고 활용법을 살펴보도록 합시다. **더 알아보기** >
[task] | two_turn [pass] | ⏳ 미판정 [title] | 엔티티에 물리 적용하기 [question] | 물리 강체에 힘을 가할 때 `ApplyForce()`와 `ApplyLinearImpulse()` 중 어떤 함수를 선택해야 하는지, 질량 값이 결과에 미치는 차이점을 설명해 주세요. [answer] | `ApplyForce()`와 `ApplyLinearImpulse()`는 모두 물리 강체의 질량 값에 영향을 받지만, 힘의 작용 방식과 지속 시간이 다르므로 목적에 따라 선택해야 합니다. ### 1. 함수 선택 기준 * **`ApplyForce()` (지속적인 힘)** * 특정 방향에 **지속적으로** 힘을 가할 때 사용합니다. * 예: 키를 길게 눌러 캐릭터가 계속 가속되거나, 바람이 불어 물체가 계속 밀리는 경우. * 매개변수 `force`는 힘의 크기를 의미합니다. * **`Apply [followup] | 특정 키를 길게 눌러서 캐릭터가 지속적으로 이동하도록 `ApplyForce()`를 매 프레임 호출하는 `[server only]` `OnUpdate` 스크립트 코드를 작성해 주세요. [followup_answer] | 참고 문서에 따르면 `ApplyForce()`는 "특정 Key를 눌러 지속적으로 특정 방향으로 힘 가하고 싶을 때" 사용하며, "지속적인 힘을 가할 수 있습니다"라고 명시되어 있습니다. 하지만 제공된 참고 문서에는 **키 입력 상태를 감지하는 API(예: 키가 눌렸는지 확인하는 함수/이벤트)나 입력 서비스(InputService) 관련 정보가 전혀 없습니다.** mLua에서 키 입력을 처리하는 구체적인 API가 문서에 없으므로, "키를 눌렀는지"를 판별하는 로직은 작성할 수 없습니다. 따라서 아래 코드는 **"외부에서 입력 상태 [scores] | [judge_reason] | [source_doc] | #### 힘을 가하는 함수 `ApplyForce()`, `ApplyTorque()` 함수는 지속적인 힘을 가할 수 있습니다. 특정 Key를 눌러 지속적으로 특정 방향으로 힘 가하고 싶을 때가 해당됩니다. 매개 변수 force는 힘을 의미합니다. 해당 Entity에 대응하는 물리 강체의 질량 값에 영향을 받습니다. #### 충격량을 적용하는 함수 `ApplyAngularImpulse()`, `ApplyLinearImpulse()` 함수는 일시적으로 짧은 충격을 가할 수 있습니다. 대포 발파, 방망이 휘두르기 같은 짧은 충격을 주
[task] | code [pass] | ⏳ 미판정 [title] | 웹 브라우저 활용하기 [question] | WebViewClickedEvent 이벤트 핸들러 내에서 event.NormalizedPosition 변수를 로컬 변수로 선언하고, 이 변수의 x와 y 프로퍼티를 추출하여 "Clicked: (x, y)" 형식의 로그를 출력하는 로직을 작성해줘 [answer] | WebViewClickedEvent 이벤트 핸들러에서 클릭한 지점의 정규화된 좌표(normalizedPosition)를 로컬 변수로 받아서 로그로 출력하는 스크립트는 다음과 같습니다. ```lua Event Handler: [self] HandleWebViewClickedEvent(WebViewClickedEvent event) { --------------- Native Event Sender Info ---------------- -- Sender: WebViewComponent -- Space: Clie [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 웹 브라우저에서 클릭한 지점의 좌표를 로그로 남겨봅시다. **WebViewClickedEvent**를 활용하면 클릭한 지점의 **normalizedPosition**을 확인할 수 있습니다. **normalizedPosition**이란 웹 뷰를 하나의 평면 좌표계라고 했을 때 왼쪽 상단을 (0,0), 오른쪽 하단을 (1,1)로 표현한 위치를 말합니다. 화면의 정중앙 좌표는 (0.5,0.5) 입니다. 1. **WebViewTest** 스크립트에 **WebViewClickedEvent**를 추가하고 다음과 같이 작성합니다. `
[task] | code [pass] | ⏳ 미판정 [title] | 웹 브라우저 활용하기 [question] | WebViewClickedEvent 이벤트가 발생했을 때, 이벤트 객체의 NormalizedPosition 프로퍼티를 참조하여 해당 클릭 위치의 x와 y 값을 개별적으로 로그로 남기는 [self] 공간의 이벤트 핸들러 코드를 작성해줘 [answer] | 요청하신 `WebViewClickedEvent` 이벤트 핸들러 코드입니다. ```lua Event Handler: [self] HandleWebViewClickedEvent(WebViewClickedEvent event) { --------------- Native Event Sender Info ---------------- -- Sender: WebViewComponent -- Space: Client ------------------------------------------------------ [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 웹 브라우저에서 클릭한 지점의 좌표를 로그로 남겨봅시다. **WebViewClickedEvent**를 활용하면 클릭한 지점의 **normalizedPosition**을 확인할 수 있습니다. **normalizedPosition**이란 웹 뷰를 하나의 평면 좌표계라고 했을 때 왼쪽 상단을 (0,0), 오른쪽 하단을 (1,1)로 표현한 위치를 말합니다. 화면의 정중앙 좌표는 (0.5,0.5) 입니다. 1. **WebViewTest** 스크립트에 **WebViewClickedEvent**를 추가하고 다음과 같이 작성합니다. `
[task] | code [pass] | ⏳ 미판정 [title] | 웹 브라우저 활용하기 [question] | 웹 뷰의 좌측 상단(0,0)에서 우측 하단(1,1)까지의 정규화된 좌표계에서 클릭된 지점의 x, y 값을 .. 연산자를 사용해 문자열로 결합하여 콘솔 로그에 기록하는 HandleWebViewClickedEvent 함수를 작성해줘 [answer] | 웹 뷰에서 클릭된 지점의 정규화된 좌표(`normalizedPosition`)를 로그로 출력하는 `HandleWebViewClickedEvent` 함수는 다음과 같이 작성할 수 있습니다. ```lua Event Handler: [self] HandleWebViewClickedEvent(WebViewClickedEvent event) { --------------- Native Event Sender Info ---------------- -- Sender: WebViewComponent -- Space: Cl [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 웹 브라우저에서 클릭한 지점의 좌표를 로그로 남겨봅시다. **WebViewClickedEvent**를 활용하면 클릭한 지점의 **normalizedPosition**을 확인할 수 있습니다. **normalizedPosition**이란 웹 뷰를 하나의 평면 좌표계라고 했을 때 왼쪽 상단을 (0,0), 오른쪽 하단을 (1,1)로 표현한 위치를 말합니다. 화면의 정중앙 좌표는 (0.5,0.5) 입니다. 1. **WebViewTest** 스크립트에 **WebViewClickedEvent**를 추가하고 다음과 같이 작성합니다. `
[task] | single_turn [pass] | ⏳ 미판정 [title] | 웹 브라우저 활용하기 [question] | WebViewComponent를 추가했는데 URL이 뜨지 않고 화면이 하얗게 보일 때, 엔티티의 크기를 제대로 조절해야 하는지 궁금합니다. [answer] | 네, 엔티티의 크기를 적절하게 조절하는 것이 중요합니다. 참고 문서에 따르면, UI로 웹 브라우저를 배치하여 화면의 특정 위치에 보이도록 하려면 다음 단계를 따라야 합니다. 1. **Hierarchy - ui** 아래에서 원하는 UI 그룹의 콘텍스트 메뉴를 엽니다. 2. **Create Entity - Create UIEmpty**를 선택해 **UIEmpty**를 생성합니다. 3. 프로퍼티 에디터에서 생성한 **UIEmpty**에 **WebViewComponent**를 추가하고 원하는 Url을 입력합니다. 4. **엔티티 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | UI로 웹 브라우저를 배치하면 화면의 특정 위치에 항상 웹 브라우저가 보이도록 할 수 있습니다. 1. **Hierarchy - ui** 아래에서 원하는 UI 그룹의 콘텍스트 메뉴를 엽니다. **Create Entity - Create UIEmpty**를 선택해 **UIEmpty**를 생성합니다. 2. 프로퍼티 에디터에서 **UIEmpty**에 **WebViewComponent**를 추가하고 원하는 Url을 입력합니다. 3. 엔티티의 크기를 적절하게 조절한 후 **[시작]** 버튼을 눌러 테스트해 봅시다. 화면의 특정 위치에
[task] | single_turn [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | 파티클 컴포넌트를 DefaultPlayer에 추가하고 ParticleType을 FireField로 설정한 후, 스크립트에서 Stop()을 호출했는데 파티클이 사라지지 않을 경우 가장 먼저 확인해야 할 설정은 무엇인가요? [answer] | 참고 문서에 따르면, `Stop()` 함수를 호출했음에도 파티클이 사라지지 않을 경우 가장 먼저 확인해야 할 설정은 **파티클이 실제 재생(Play) 상태인지**입니다. 문서의 예제 흐름을 보면, 파티클을 제어하기 위해서는 먼저 파티클이 재생되고 있어야 `Stop()`이 정상적으로 동작합니다. `BasicParticleComponent`에 `Stop()`을 호출하기 전에 해당 파티클이 `Play()` 상태인지, 혹은 초기 상태인지 확인해야 합니다. 문서의 '파티클 재생 상태 변경' 예제에서는 `HandleTriggerEnterEv [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 [파티클 사용하기](/docs/?postId=1036) 가이드에서 파티클 컴포넌트의 개념 및 종류에 대해 알아보았습니다. 이번 시간에는 스크립트를 사용해 파티클을 활용하는 예제를 살펴보겠습니다. # 파티클 스크립트 ## 파티클 프로퍼티 제어 캐릭터와의 거리에 따라 파티클의 재생 속도가 바뀌는 예제를 통해 파티클 프로퍼티를 제어하는 방법을 살펴봅시다. 1. 파티클이 잘 보이도록 어두운 배경을 설정하고 지형을 배치한 뒤 원하는 파티클을 배치합니다. 본 예제에서는 Background로 **back-16**을 설
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | 문서에 제시된 번개 파티클 대미지 적용 절차를 실행 순서대로 정리하세요. [answer] | 문서에 제시된 번개 파티클 대미지 적용 절차는 다음과 같은 순서로 실행됩니다. 1. **Preset List**에서 **LightningStrikeSharp** 파티클을 선택하여 배치합니다. 2. **AttackComponent**를 Extend하여 새 스크립트 컴포넌트인 `ExtendAttackComponent`를 생성합니다. 3. `ExtendAttackComponent`를 열고 `OnLightning()` 함수를 추가합니다. ```lua void OnLightning() { self: [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 파티클 이벤트를 활용하여 파티클을 반복 생성할 때마다 대미지를 주거나 연출을 보여줄 수 있습니다. 번개가 칠 때마다 공격 기능이 작동하여 캐릭터에게 대미지를 주는 예제를 통해 파티클 이벤트의 활용 방법을 살펴봅시다. 1. Preset List - **LightningStrikeSharp** 파티클을 배치합니다. 2. AttackComponent를 Extend하여 새 스크립트 컴포넌트 ExtendAttackComponent를 생성합니다. 3. ExtendAttackComponent를 열고 `OnLightni
[task] | code [pass] | ⏳ 미판정 [title] | 웹 브라우저 활용하기 [question] | WebViewClickedEvent의 NormalizedPosition.x와 y 값을 문자열로 변환하여 log 함수로 출력하는 [self] 이벤트 핸들러를 WebViewTest 스크립트에 구현해줘 [answer] | WebViewTest 스크립트에 `WebViewClickedEvent`를 처리하는 이벤트 핸들러를 구현하면 다음과 같습니다. `event.NormalizedPosition`의 `x`와 `y` 값을 문자열로 변환하여 `log` 함수로 출력합니다. ```lua Event Handler: [self] HandleWebViewClickedEvent(WebViewClickedEvent event) { --------------- Native Event Sender Info ---------------- -- Sender: W [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 웹 브라우저에서 클릭한 지점의 좌표를 로그로 남겨봅시다. **WebViewClickedEvent**를 활용하면 클릭한 지점의 **normalizedPosition**을 확인할 수 있습니다. **normalizedPosition**이란 웹 뷰를 하나의 평면 좌표계라고 했을 때 왼쪽 상단을 (0,0), 오른쪽 하단을 (1,1)로 표현한 위치를 말합니다. 화면의 정중앙 좌표는 (0.5,0.5) 입니다. 1. **WebViewTest** 스크립트에 **WebViewClickedEvent**를 추가하고 다음과 같이 작성합니다. `
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | 단계별 번호 목록으로 [answer] | 파티클 이벤트를 활용하여 번개가 칠 때마다 대미지를 주는 연출을 구현하는 단계별 방법은 다음과 같습니다. 1. **파티클 배치**: Preset List에서 `LightningStrikeSharp` 파티클을 배치합니다. 2. **스크립트 컴포넌트 생성**: `AttackComponent`를 Extend하여 `ExtendAttackComponent`라는 새 스크립트 컴포넌트를 생성합니다. 3. **공격 함수 추가**: `ExtendAttackComponent`를 열고 `OnLightning()` 함수를 추가하여 공격 판정을 수 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 파티클 이벤트를 활용하여 파티클을 반복 생성할 때마다 대미지를 주거나 연출을 보여줄 수 있습니다. 번개가 칠 때마다 공격 기능이 작동하여 캐릭터에게 대미지를 주는 예제를 통해 파티클 이벤트의 활용 방법을 살펴봅시다. 1. Preset List - **LightningStrikeSharp** 파티클을 배치합니다. 2. AttackComponent를 Extend하여 새 스크립트 컴포넌트 ExtendAttackComponent를 생성합니다. 3. ExtendAttackComponent를 열고 `OnLightni
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | 문서에 명시된 TriggerEnterEvent 핸들러 내 코드만 출력하되, 모든 설명은 코드 주석(-- )으로만 작성하고 본문 설명 문장은 포함하지 마세요. [answer] | ```lua Event Handler: HandleTriggerEnterEvent(TriggerEnterEvent event) { -- Parameters local TriggerBodyEntity = event.TriggerBodyEntity -------------------------------------------------------- if TriggerBodyEntity ~= self.ResetEntity then -- 캐릭터가 목표 엔티티가 아닌 다른 엔티티에 닿으면 PlayBa [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 반복 재생되는 파티클을 생성하거나 삭제하는 방법을 알아봅시다. 특정 엔티티에 캐릭터가 닿으면 파티클이 생성되다가 캐릭터가 목표 지점에 도착하면 파티클 생성이 멈추는 예제를 만들어보겠습니다. 1. 파티클을 뿜어낼 엔티티와 목표 엔티티를 배치합니다. 본 예제에서는 파티클을 뿜어낼 엔티티로 **object-24**(호리병)을, 목표 엔티티로는 **object-928**(소화기)를 사용했습니다. 2. 배치한 모든 엔티티에 TriggerComponent를 추가합니다. 3. Workspace - MyDesk에 새
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | UIParticle 엔티티에 추가해야 하는 컴포넌트 이름과 ParticleType 설정값을 1문장으로 답하세요. [answer] | UIParticle 엔티티에는 UIBasicParticleComponent 컴포넌트를 추가하고, ParticleType을 CircleBust로 설정해야 합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 1. **UIParticle**에 **UIBasicParticleComponent**를 추가합니다. 2. ParticleType을 **CircleBust**로 선택하고, 원하는 파티클 크기, 속도 등을 조절합니다. 3. **UIBasicParticleComponent**의 **Loop**를 **false**로 설정해 버튼을 눌렀을 때 파티클이 한 번만 재생되도록 합니다. **PlayOnEnable** 또한 **false**로 변경하여 파티클이 월드 진입하자마자 재생되지 않도록 합니다. ![[object Object]](https
[task] | single_turn [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | Loop 매개변수를 true로 설정하면 파티클이 무한정 반복 재생되는 건지, 아니면 특정 시간이나 횟수 동안 반복되는 건지 차이점을 알려주세요. [answer] | 제공된 참고 문서에는 `PlayBasicParticle` 함수의 `Loop` 매개변수를 `true`로 설정했을 때의 구체적인 동작 방식(무한정 반복인지, 특정 시간/횟수 제한이 있는지)에 대한 설명이 포함되어 있지 않습니다. 문서에서는 예제 코드 내에서 `Loop`를 `false`로 설정하여 "파티클이 한 번씩만 재생되도록 한다"는 내용만 명시하고 있을 뿐, `true` 상태에서의 반복 규칙에 대한 기술은 없습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 1. 파티클이 잘 보이도록 어두운 배경을 설정하고 지형을 배치한 뒤 원하는 엔티티를 배치합니다. 본 예제에서는 Preset List에서 Background - **back-51**을 설정하고 Object - **object-174**를 배치했습니다. 2. Workspace - MyDesk에 새 스크립트 컴포넌트 ParticleServiceTest를 생성합니다. 3. 배치한 엔티티(object-174)의 Property에 ParticleServiceTest를 추가합니다. 4. 여기에 TweenCircula
[task] | two_turn [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | LightningStrikeSharp 파티클을 배치하고 AttackComponent를 Extend한 컴포넌트를 연결하여 대미지를 주는 전체 구성 과정이 궁금합니다. [answer] | LightningStrikeSharp 파티클을 활용하여 캐릭터에게 대미지를 주는 전체 구성 과정은 파티클 이벤트(Particle Event)를 통해 공격 로직을 트리거하는 방식으로 이루어집니다. 아래 단계에 따라 구성하면 됩니다. ### 1. 파티클 배치 먼저 에디터에 **LightningStrikeSharp** 파티클을 배치합니다. ### 2. 커스텀 공격 컴포넌트 생성 기존의 `AttackComponent`를 Extend(상속)하여 새로운 스크립트 컴포넌트를 생성합니다. 생성한 컴포넌트 이름은 예시처럼 `ExtendAtta [followup] | ParticleEmitStartEvent와 ParticleLoopEvent에서 OnLightning()을 호출할 때 두 이벤트의 차이점과, 파티클이 반복 생성될 때마다 대미지가 누적되는지 확인하는 테스트 코드를 작성해 주세요. [followup_answer] | 참고 문서에 제공된 정보와 mLua 스크립트 규칙에 기반하여 답변드립니다. ### 1. ParticleEmitStartEvent와 ParticleLoopEvent의 차이점 참고 문서의 코드 주석과 이벤트 이름을 바탕으로 두 이벤트의 차이는 다음과 같습니다. * **ParticleEmitStartEvent**: 파티클이 **처음 시작할 때**(`파티클이 시작할 때`) 한 번만 발생하는 이벤트입니다. * **ParticleLoopEvent**: 파티클이 **루프(반복)될 때** 발생하는 이벤트입니다. 파티클이 지속되거나 반 [scores] | [judge_reason] | [source_doc] | 파티클 이벤트를 활용하여 파티클을 반복 생성할 때마다 대미지를 주거나 연출을 보여줄 수 있습니다. 번개가 칠 때마다 공격 기능이 작동하여 캐릭터에게 대미지를 주는 예제를 통해 파티클 이벤트의 활용 방법을 살펴봅시다. 1. Preset List - **LightningStrikeSharp** 파티클을 배치합니다. 2. AttackComponent를 Extend하여 새 스크립트 컴포넌트 ExtendAttackComponent를 생성합니다. 3. ExtendAttackComponent를 열고 `OnLightni
[task] | code [pass] | ⏳ 미판정 [title] | 공동 제작 팁 [question] | UserService를 활용하여 로컬 플레이어의 이름이 "CreatorName"과 일치하는 경우에만 TestComponent의 Enable 속성을 true로 설정하는 스크립트를 작성해줘 [answer] | ```lua Method: [server only] void SetTestComponentForCreator() { if _UserService.LocalPlayer.Name == "CreatorName" then TestComponent.Enable = true end } ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 메이커에서 플레이 테스트를 하다가 인스턴스 맵으로 이동하면 **Hierarchy** 탭에 아무것도 보이지 않는 현상이 발생할 수 있습니다. 이때는 **Hierarchy** 탭을 닫았다가 다시 열면 정상화됩니다. Workspace나 UI에서도 유사한 현상이 발생할 수 있습니다. 이때 폴더를 접었다 펴면 Check Out 정보가 갱신됩니다. ## 새로운 월드로 이전 공동 제작 중 아래와 같은 현상이 발생하면 해당 월드에 심각한 문제가 발생할 가능성이 높습니다. * 스크립트 에디터에 게임 UI가 보임 * UI를 수정하고 Check
[task] | single_turn [pass] | ⏳ 미판정 [title] | 파티클 활용하기 [question] | 3D 공간이 아닌 UI 위에서만 파티클을 재생하려면 어떤 컴포넌트를 사용해야 하나요? [answer] | UI 위에서만 파티클을 재생하려면 `UIBasicParticleComponent`, `UIAreaParticleComponent`, 또는 `UISpriteParticleComponent` 중 하나를 사용해야 합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 파티클 이벤트를 활용하여 파티클을 반복 생성할 때마다 대미지를 주거나 연출을 보여줄 수 있습니다. 번개가 칠 때마다 공격 기능이 작동하여 캐릭터에게 대미지를 주는 예제를 통해 파티클 이벤트의 활용 방법을 살펴봅시다. 1. Preset List - **LightningStrikeSharp** 파티클을 배치합니다. 2. AttackComponent를 Extend하여 새 스크립트 컴포넌트 ExtendAttackComponent를 생성합니다. 3. ExtendAttackComponent를 열고 `OnLightni