콘텐츠로 이동

스켈레톤 연습

이 섹션에서는 LightScript 연동의 기본 구조, 핵심 기술 요구 사항, 실제 사례, 명명 규칙, 효율성 팁을 설명합니다. 업데이트 루프, 미터 동작, 효과 트리거 로직을 다루며 일반적인 함정을 강조합니다. 디버깅, 처음부터 구축, 또는 다른 사람의 코드를 유지 관리하는 경우 모두, 이 가이드는 고품질 연동의 핵심 표준으로 명확성, 안정성, 성능을 강조합니다.

이 섹션에서는 문제가 일반적으로 발생하는 위치와 버그를 찾고 수정하는 방법에 중점을 두어 유지 관리 관점에서 LightScript 설정에 대한 빠른 개요를 제공합니다. 이상적인 LightScript 구조를 간략히 살펴본 다음 문제 해결을 다루고 FAQ로 마무리합니다.

기본 스켈레톤에는 <head>, <body>, **<script>**가 필요합니다. 모든 미터 및 사용자 컨트롤 선언은 <head> 안에 있어야 합니다. 모든 캔버스 선언은 **<body>**에 속합니다. 다른 모든 것은 <script> 섹션에 배치해야 합니다.

**<head>**는 모든 LightScript에서 가장 중요하고 복잡한 부분 중 하나입니다. 여기서 잘못된 사용자 컨트롤이나 미터는 충돌 루프를 유발하거나 자신 및 그 이후에 선언된 미터를 비활성화할 수 있습니다.

미터를 만들 때 다음을 확인해야 합니다:

  • 완벽한 구문(충돌 및 잘못된 미터 방지)
  • 중복된 미터 이름 없음(중복은 덮어써짐)
  • 화면 경계를 넘는 미터 없음(충돌 및 오류 유발)
  • 미터에 누락되거나 추가된 옵션 없음(충돌 유발)
  • 모든 미터에 해상도 조정 포함(일관된 동작 보장)

해상도에 관해서는 가장 일반적인 화면 비율은 다음과 같습니다:

  • 16:9 (3840x2160, 2560x1440, 1920x1080, 1600x900, 1366x768, 1360x768, 1280x720)
  • 16:10 (2560x1600, 1920x1200, 1680x1050, 1440x900, 1280x800)
  • 21:9 (5120x2160, 3440x1440)

기본적으로 2560x1440 해상도를 사용합니다.

모든 LightScript16:9, 16:10, 21:9 화면 비율을 지원해야 합니다. 4:3은 사용자 기반의 상당한 비율을 차지하지는 않지만 미래 호환성을 위해 고려해야 합니다.

다음은 여러 해상도 설정이 있는 미터의 구조 예시입니다:

미터의 기본 위치와 크기는 동일한 화면 비율 내의 다른 모든 해상도에 적용됩니다. 예를 들어, 1600x900에서 작동하도록 미터를 원래 조정했다면, 해당 미터는 다른 모든 16:9 해상도에서 올바르게 작동해야 합니다. 하지만 예외가 있습니다. Fortnite는 동일한 화면 비율 내에서도 여러 다른 미터 위치를 가지고 있으며, 일부 화면 비율 자체가 오해를 불러일으킬 수 있습니다. 예를 들어, 전 세계적으로 흔한 해상도인 1366x768은 종종 16:9로 나열되지만 실제로는 정확한 16:9 비율이 아닙니다. 마찬가지로 21:9와 같은 울트라와이드 비율은 명목상의 치수와 거의 일치하지 않습니다. 연동 개발자로서의 경험상 21:9로 표시됨에도 불구하고 정확한 21:9 해상도를 접한 적이 없습니다. 이 때문에 각 울트라와이드 해상도는 개별적으로 생성, 테스트, 구성해야 합니다.

모든 조정은 여는 <meta> 태그와 닫는 </meta> 태그 사이에 배치해야 합니다. 그렇지 않으면 작동하지 않습니다. 기본 미터가 16:9를 기반으로 하고 해당 해상도에서 일관되게 동작한다면, 다른 16:9 해상도에 대한 조정을 추가할 필요가 없습니다. 하지만 비율이 일관적이더라도 16:1021:9와 같은 다른 화면 비율의 모든 해상도에 대한 항목을 추가해야 합니다.

마지막으로, OCR 미터를 제외한 모든 미터는 트리거를 위해 HSL 범위가 필요합니다. 이러한 범위는 다음과 같은 요인으로 인해 복잡해질 수 있습니다:

  • 투명 UI 요소
  • 색상 영역의 그라디언트
  • 화면 왜곡 효과
  • 게임 내 메뉴 열기
  • 해상도별 UI 조정
  • 컨트롤러 대 키보드 사용
  • 비디오 녹화(압축 관련 픽셀 오류 유발 가능)

HSL 및 정규화된 좌표에 대한 기본 지침은 개발자 문서에서 다루며 여기서 반복하지 않습니다. 미터 테스트는 “문제 식별” 섹션에서 설명하지만 이것만은 강조하고 싶습니다: 모든 미터를 완벽하게 검증하는 데 필요한 테스트 양은 (미터 수) × (해상도 조정 수) × (게임 모드 수) × (플레이 가능한 캐릭터 수) × (평균 게임 길이)로 계산됩니다. 연습 모드나 다른 해결 방법을 사용할 수 없는 경우 특히 게임당 수 시간의 검증이 쉽게 필요할 수 있습니다.

미터를 효율적으로 유지하십시오. 우리의 표준은 완벽입니다.

<body> 태그는 실제 캔버스 요소가 선언되는 곳입니다. 다음 예시와 거의 동일하게 보여야 합니다. 실제 캔버스 id는 변경할 수 있지만 스크립트에서 올바르게 가져오도록 확인하십시오.

시간을 절약하려면 복사해서 붙여넣으십시오.

모든 연동에서 이 태그 내부에서 네 가지가 발생해야 합니다:

  • 캔버스를 가져와 2D 컨텍스트를 만드는 데 사용합니다.
  • 초기 업데이트 루프가 미터 값을 설정한 다음 이를 유지하기 위해 무기한 자신을 재호출합니다.
  • 업데이트 루프는 사용자 컨트롤 변수를 최신 상태로 유지합니다.
  • 미터는 안정적일 때 콜백 함수를 실행합니다.

기본 코드 스켈레톤을 이미 설정했습니다. 다음 단계는 처음부터 끝까지 효과를 트리거하는 실행 루프를 살펴보는 것입니다.

  1. 비디오 게임 UI는 색상 바, 버튼, 텍스트 박스 등의 형태로 정보를 표시합니다. SignalRGB는 초당 여러 번 이 데이터를 캡처하지만, 실제 캡처 속도는 코드의 효율성에 크게 의존합니다. 명확히 말씀드리자면, 단 하나의 루프나 선언되지 않은 변수도 전체 스크립트를 중단시키고 SignalRGB를 충돌시킬 수도 있습니다. 더 나쁜 것은 기술적으로 작동하지만 너무 비효율적이어서 겨우 1-2 FPS로 정보를 캡처하는 코드를 작성하기 쉽다는 것입니다.
  2. **<head>**에서 선언된 각 미터는 오버헤드를 줄이기 위해 가능한 한 작고 효율적이어야 합니다. 계산을 일찍 자주 하십시오. 화면의 25%를 차지하는 미터는 절대 효율적이지 않습니다. OCR 미터의 경우 전체 단어 대신 개별 글자를 캡처하십시오. 체력 및 마나 바의 경우 필수 세그먼트만 모니터링하십시오. 미터를 최대한 작게 유지하십시오.
  3. 미터는 각 루프마다 새로 고쳐지는 정보를 캡처합니다.
  4. 앞서 Meter 클래스 정의를 다루었는데, 이 클래스는 미터 데이터를 저장하고 정보 배열이 안정적이 되면 콜백을 트리거합니다. 스크립트 상단에서 모든 Meter를 하나의 블록에 선언하십시오. 정리하거나 알파벳 순서로 배열할 수 있지만 수천 줄에 걸쳐 분산시키지 마십시오. 결국 안정성 값을 조정해야 할 때, 어디에 배치했는지 기억하려고 시간을 낭비하게 됩니다.
  5. 업데이트 함수 내부에서 이러한 미터들은 매 루프마다 화면 읽기 로직에서 값을 받습니다. 내부 로직이 안정성을 평가하고 안정적이면 관련 콜백 함수를 트리거합니다.
  6. 이러한 콜백 함수는 업데이트 함수 외부에서 스크립트에 선언되어야 합니다. 내부에서 Meter 값(value, decreased, increased, diff)의 상태를 확인하고 이를 사용하여 효과 애니메이션을 재생할지 여부를 결정하십시오. 업데이트 루프 내부에 모든 것을 직접 넣는 대신 이런 방식으로 코드를 구조화하면 확장 가능한 연동을 구축할 수 있습니다.

일반적인 아이디어를 파악했으니 이제 실제 사례 루프를 빠르게 살펴보겠습니다.

  • League of Legends를 플레이하고 있는데, 이 게임은 사용 가능한 스킬 주변에 밝은 노란색 하이라이트를 표시합니다.
  • 각 루프마다 특정 스킬 미터는 미터의 HSL 범위를 완전히 통과하기 때문에 이 색상을 “1” 값으로 감지합니다.
  • 이 **“1”**은 화면 읽기 미터에 연결된 Meter 인스턴스에 전달되어 해당 Meter의 정보 배열에 삽입됩니다.
  • 해당 배열의 모든 값이 **“1”**이면 안정적으로 간주되어 연결된 효과 콜백 함수를 활성화합니다. 이 콜백 함수는 모든 값이 **“0”**이거나 **“.1”**인 경우에도 활성화됩니다. Meter가 신경 쓰는 것은 안정성뿐입니다. 여기서 중요한 점은 Meter가 동일한 값으로 지속적으로 안정적이더라도 콜백 함수가 계속 활성화되지 않는다는 것입니다. 새로운 값으로의 안정화만이 콜백을 활성화합니다.
  • 콜백 함수가 실행되면 몇 가지 조건부 체크에 도달합니다. 이 경우 스킬이 사용되었음을 나타내는 Meter.value가 **“0”**인지 확인하기만 하면 됩니다.
  • Meter 값이 **“1”**이므로 이 체크에 실패하여 스킬 효과가 재생되지 않습니다.
  • 몇 초 후, 스킬을 활성화하면 버튼 주변의 노란색 하이라이트가 사라집니다.
  • 새 미터 값은 0으로 Meter 클래스에 전달됩니다.
  • 안정성에 도달하면 콜백이 활성화되고 조건부가 통과되어 스킬 효과가 재생됩니다. 지연은 전적으로 선언 시 설정하는 Meter 배열의 길이에 의존합니다. 길이가 길수록 지연이 증가하고 거짓 트리거가 줄어드므로 좋은 균형을 찾을 때까지 테스트를 진행하십시오.

화면 읽기 미터는 단순하고 명확하며 설명적인 이름을 가져야 하며, 항상 소문자로 시작해야 합니다. 체력 바 미터를 **“healthBar”**로 명명하는 것은 훌륭합니다. 같은 영역에서 다른 색상을 추적하는 두 미터를 **“healthBarRed”**와 **“healthBarGreen”**으로 명명하는 것도 좋습니다. 하지만 특정 영웅의 궁극기 효과 중에만 나타나는 작은 미터를 **“hrO21_yes”**와 같이 명명하면 코드를 수정하려는 다른 사람에게 고통만 줄 뿐입니다. 운이 없으면 잘못 명명된 작은 미터가 추적하는 내용을 파악하는 데 문자 그대로 한 시간 동안 개별 픽셀을 바라봐야 할 수 있으니 이런 방식은 사용하지 마십시오.

Meter 클래스 인스턴스는 대문자로 시작하고 Meter라는 단어로 끝나야 합니다. “Q_Meter”, “TookDamageMeter”, **“TowerDestroyedMeter”**와 같은 예시는 모두 적합합니다. 이는 <head> 섹션에서 선언된 미터와 명확하게 구별되어야 합니다.

효과 함수도 가능한 한 단순하고 설명적으로 명명해야 합니다. 일부 게임에는 수백 개의 이러한 함수가 있고, 다른 게임에는 열 개 미만이 있을 수 있습니다. 여러 영웅에게 고유한 스킬이 있는 경우 “SonaQ”, “ChamberE”, **“AshUlt”**와 같이 영웅 이름을 접두사로 포함하십시오. League of Legends에는 여러 미터에서 사용되는 여러 조건부가 포함된 “DragonEffect”, “TowerEffect”, **“Q_Effects”**와 같은 함수가 있습니다. 따라서 이런 명명 방식은 규모에 맞게 최적화하는 데도 도움이 됩니다.

단어를 잘못 쓰지 마십시오. 철자가 확실하지 않으면 찾아보십시오. 이름은 누가 코드를 작업하든, 시간이 얼마나 지났든 상관없이 명확하고 읽기 쉬워야 합니다. 알파벳 순으로 이름을 정리하면 빠른 검색에 도움이 됩니다. 특히 해당 섹션을 자주 편집하는 경우에 유용합니다. 이 수준의 정리가 코드 실행에 필수적이지는 않지만, 유지 관리 개발자에게 큰 차이를 만듭니다.