From 5e0eca6cdf2ece059babaf2134c2c820cf673492 Mon Sep 17 00:00:00 2001 From: gahusb Date: Tue, 16 Jun 2026 00:37:36 +0900 Subject: [PATCH] =?UTF-8?q?fix(monster):=20MonsterAttack.OnBeginPlay=20Ani?= =?UTF-8?q?mationClip=20=ED=83=80=EC=9E=85=EA=B0=80=EB=93=9C=20(LEA-3023/2?= =?UTF-8?q?007)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 증상: 전투맵 진입 시 몬스터마다 [LEA-3023] TypeMismatch(AnimationClip) + [LEA-2007] AttemptToIndex(clip nil) 서버 로그 스팸(몬스터 수만큼 반복). 원인: MonsterAttack.OnBeginPlay(chasemonster 모델 상속·메이커 저작·생성기 없음)가 정적 Sprite인 SpriteRUID를 _ResourceService:LoadAnimationClipAndWait에 넘김 → AnimationClip이 아니라 nil 반환(LEA-3023) → clip.Frames[1] 인덱싱(LEA-2007). 이 멜리 공격 로직은 카드 기반 턴제 전투에서 호출하는 코드가 전혀 없는 죽은 코드라 크래시 외 게임 영향은 없으나 로그를 더럽힘. 수정: LoadAnimationClipAndWait 호출 전 GetTypeAndWait가 ResourceType.AnimationClip이 아니면 early-return + clip nil 가드. 정적 스프라이트 몬스터는 공격범위 설정을 건너뜀 (원래 미사용), 애니메이션 클립 몬스터는 기존대로 동작. 주의: MonsterAttack은 생성기 없는 메이커 저작 codeblock이라 디스크 직접 패치. 적용하려면 메이커에서 로컬 워크스페이스 reload 필요. Co-Authored-By: Claude Opus 4.8 (1M context) --- RootDesk/MyDesk/MonsterAttack.codeblock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RootDesk/MyDesk/MonsterAttack.codeblock b/RootDesk/MyDesk/MonsterAttack.codeblock index 8d52193..5aaa1e2 100644 --- a/RootDesk/MyDesk/MonsterAttack.codeblock +++ b/RootDesk/MyDesk/MonsterAttack.codeblock @@ -85,7 +85,7 @@ "Name": null }, "Arguments": [], - "Code": "local monster = self.Entity.Monster\nif not monster then\n\treturn\nend\n\nself.Shape = BoxShape(Vector2.zero, Vector2.one, 0)\n\n-- sprite 사이즈를 가져와 공격 영역으로 사용한다\n_ResourceService:PreloadAsync({self.Entity.SpriteRendererComponent.SpriteRUID}, function()\n\tlocal clip = _ResourceService:LoadAnimationClipAndWait(self.Entity.SpriteRendererComponent.SpriteRUID)\n\tlocal firstFrameSprite = clip.Frames[1].FrameSprite\n\tlocal firstSpriteSizeInPixel = Vector2(firstFrameSprite.Width, firstFrameSprite.Height)\n\tlocal ppu = firstFrameSprite.PixelPerUnit\n\n\tself.SpriteSize = firstSpriteSizeInPixel / ppu\n\tself.PositionOffset = (firstSpriteSizeInPixel / 2 - firstFrameSprite.PivotPixel:ToVector2()) / ppu\n\t\n\t_TimerService:SetTimerRepeat(function() \n\t\tif monster.IsDead == false then\n\t\t\tself:AttackNear()\n\t\tend\n\tend, self.AttackInterval)\nend)", + "Code": "local monster = self.Entity.Monster\nif not monster then\n\treturn\nend\n\nself.Shape = BoxShape(Vector2.zero, Vector2.one, 0)\n\n-- sprite 사이즈를 가져와 공격 영역으로 사용한다\n_ResourceService:PreloadAsync({self.Entity.SpriteRendererComponent.SpriteRUID}, function()\n\tif _ResourceService:GetTypeAndWait(self.Entity.SpriteRendererComponent.SpriteRUID) ~= ResourceType.AnimationClip then\n\t\treturn\n\tend\n\tlocal clip = _ResourceService:LoadAnimationClipAndWait(self.Entity.SpriteRendererComponent.SpriteRUID)\n\tif clip == nil then\n\t\treturn\n\tend\n\tlocal firstFrameSprite = clip.Frames[1].FrameSprite\n\tlocal firstSpriteSizeInPixel = Vector2(firstFrameSprite.Width, firstFrameSprite.Height)\n\tlocal ppu = firstFrameSprite.PixelPerUnit\n\n\tself.SpriteSize = firstSpriteSizeInPixel / ppu\n\tself.PositionOffset = (firstSpriteSizeInPixel / 2 - firstFrameSprite.PivotPixel:ToVector2()) / ppu\n\t\n\t_TimerService:SetTimerRepeat(function() \n\t\tif monster.IsDead == false then\n\t\t\tself:AttackNear()\n\t\tend\n\tend, self.AttackInterval)\nend)", "Scope": 2, "ExecSpace": 1, "Attributes": [], -- 2.49.1