UDN
Search public documentation:

ScaleformActionScriptBestPracticesKR
English Translation
日本語訳
中国翻译

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 홈 > 유저 인터페이스와 HUD > 스케일폼 GFx > 스케일폼 GFx ActionScript 실전 사례

스케일폼 GFx ActionScript 실전 사례


문서 변경내역: James Tan 작성. 홍성진 번역.

개요


ActionScript 는 네이티브 머신 코드로 컴파일되지 않고, 바이트 코드로 변환됩니다. 컴파일된 네이티브 코드만큼 빠르지는 않지만, 인터프리터 언어보다는 빠르죠. ActionScript 가 느리다고는 해도, 대부분의 멀티미디어 상황에서 퍼포먼스를 제한하는 요인은 그래픽, 오디오, 비디오와 같은 애셋이지 코드는 아닙니다.

ActionScript 전용 최적화 기법이랄 것은 별로 없지만, 컴파일러 최적화 없이도 어느 언어에서나 잘 알려진 코드 작성 기법이면 충분합니다. 예를 들어 변하지 않는 부분이 루프 반복처리부 안에 있을 경우, 루프 안에서 밖으로 옮겨주기만 해도 루프는 훨씬 빨라집니다.

ALERT! : ActionScript (액션스크립트)는 앞으로 AS 라 줄여 쓰겠습니다.
ALERT! : Virtual Machine (가상 머신)은 앞으로 VM 이라 줄여 쓰겠습니다.

일반적인 ActionScript 지침


AS 실행 속도 향상을 위한 일반적인 최적화는 다음과 같습니다:

  • SWF 를 Flash 버전 8 이상으로 퍼블리시 합니다.
  • AS 를 조금 사용할 수록 파일 퍼포먼스는 좋아집니다. 항상 최소한의 코드로 어떤 일을 하도록 작성하시기 바랍니다. AS 는 주로 상호작용 부분에 쓸 것이지, 그래픽적인 요소를 만드는 데 쓸 것이 아닙니다. 코드에서 attachMovie 호출을 과하게 사용하도록 구성했다면, FLA 파일 구성 방식을 다시 고려해 보시기 바랍니다.
  • 스크립트 애니메이션은 가급적 사용을 삼가십시오. 일반적으로 타임라인 애니메이션의 퍼포먼스가 더 좋습니다.
  • 과도한 문자열(string) 조작을 피하십시오.
  • "if" 문을 사용하는 루핑 무비 클립을 너무 많이 사용하면 종료 문제가 생길 수 있습니다.
  • on() 이나 onClipEvent() 이벤트 핸들러는 가급적 자제하고, 그 대신 onEnterFrame, onPress 등을 사용하십시오.
  • 주요 AS 로직은 가급적 한 프레임에 놓지 마십시오. 그 대신 중요 코드의 큰 부분은 함수 안에 넣도록 합니다. 소스의 위치가 프레임 안이거나 (onClipEvent, on 같은) 구형 이벤트 핸들러일 때보다 함수 본문 안에 있을 때, Flash AS 컴파일러가 훨씬 빠른 코드를 만들 수 있습니다. 물론 단순한 로직은 프레임에 놔둬도 괜찮습니다. 이를테면 (gotoAndPlay, play, stop 등의) 타임라인 콘트롤이나 기타 중요치 않은 로직들 정도는요.
  • 애니메이션이 여럿 들어있어 타임라인이 긴 무비클립에서는 "장거리" gotoAndPlay/gotoAndStop 사용을 삼가십시오.
    1. 정방향 gotoAndPlay/gotoAndStop 의 경우, 타겟 프레임이 현재 프레임에서 멀 수록 타임라인 콘트롤의 비용이 비싸집니다. 따라서 정방향 gotoAndPlay/gotoAndStop 는 첫 프레임에서 마지막 프레임으로 갈 때 가장 비싸집니다.
    2. 역방향 gotoAndPlay/gotoAndStop 의 경우, 타겟 프레임이 타임라인 시작에서 멀 수록 타임라인 콘트롤의 비용이 비싸집니다. 따라서 역방향 gotoAndPlay/gotoAndStop 는 마지막 프레임에서 마지막 직전 프레임으로 갈 때 가장 비싸집니다.
  • 타임라인이 짧은 무비클립을 사용하십시오. gotoAndPlay/gotoAndStop 비용은 키프레임의 수와 타임라인 애니메이션 복잡도에 따라 크게 달라집니다. 따라서 gotoAndPlay/gotoAndStop 을 호출하여 조작하려는 경우엔 타임라인을 길고 복잡하게 만들지 마십시오. 그보다는 타임라인이 짧은 무비클립 여러개로 분할하고, gotoAndPlay/gotoAndStop 호출을 줄이는 것이 좋습니다.
  • 많은 오브젝트를 동시에 업데이트하는 경우, 그 오브젝트들을 그룹으로 묶어 업데이트되도록 하는 시스템을 개발하는 것이 필수입니다. C++ 측에서는 C++ 에서 AS 로 많은 양의 데이터 전달을 위해 GFxMovie::SetVariableArray 를 호출합니다. 그런 다음 업로드된 배열에 따라 여러 개의 오브젝트를 한에 업데이트하는 invoke 가 뒤따릅니다. 보통 다수의 invoke 를 그룹으로 묶어 한 번에 호출하는 것이, 각각의 오브젝트마다 호출하는 것보다 몇 배는 빠릅니다.
  • 한 프레임에 너무 많은 작업을 하지 않도록 하십시오. 안그러면 GFx 가 Stage 를 렌더할 시간이 부족해져 버벅임이 느껴질 수가 있습니다. 작업할 양을 작은 덩어리로 분해하여, GFx 가 버벅임 없이 미리 지정된 프레임 속도로 Stage 를 새로고칠 수 있도록 하시기 바랍니다.
  • Object 유형을 너무 많이 사용하지 마십시오.
    1. 데이터 유형은 정확히 해야 합니다. 그래야 컴파일러가 형 검사를 하여 버그를 찾아낼 수 있거든요. 마땅한 대안이 없다 싶을 때만 Object 유형을 사용하시기 바랍니다.
  • eval() 함수나 배열 접근 연산자 사용을 자제하십시오. 보통은 로컬 리퍼런스 한 번 설정해 주는 것이 효율로 보나 뭘로 보나 낫습니다.
  • 루프의 조건으로는 myArr.length 자체를 사용하기 보다는, 변수에 Array.length 를 할당해서 쓰시기 바랍니다. 예를 들어:

이런 식의 코드가 좋습니다:

  var fontArr:Array = TextField.getFontList();
  var arrayLen:Number = fontArr.length;
  for (var i:Number = 0; i < arrayLen; i++) {
    trace(fontArr[i]);
  }
  

이런 코드는 자제하시구요:

  var fontArr:Array = TextField.getFontList();
  for (var i:Number = 0; i < fontArr.length; i++) {
    trace(fontArr[i]);
  }
  

  • 이벤트 관리를 구체적이고 슬기롭게 합시다. 이벤트 호출 전, 리스너가 존재하는지 (null 이 아닌지) 검사하는 조건을 사용하여 이벤트 리스너 배열을 깔끔히 유지하구요.
  • 오브젝트로의 리퍼런스를 해제하기 전, removeListener() 를 호출하여 오브젝트로부터 리스너를 명시적으로 제거하십시오.
  • 시동 시간 단축을 위해 패키지 이름의 레벨 수를 최소화하십시오. 시동시 AS VM 은 레벨별 오브젝트 하나씩, 오브젝트 체인을 만들어야 합니다. 게다가 각 레벨 오브젝트 생성 전, AS 컴파일러는 레벨이 이미 만들어졌는지 아닌지를 검사하기 위한 "if" 조건절을 추가합니다. 그래서 "com.xxx.yyy.aaa.bbb" 패키지에 대해서라면 VM 은 "com", "xxx", "yyy", "aaa", "bbb" 오브젝트를 생성하며, 그 각각을 생성하기 전 해당 오브젝트가 존재하는지를 검사하는 "if" opcode 가 생깁니다. 그렇게 깊이 중첩된 오브젝트/클래스/함수에 접근하는 것 역시도 느립니다. 각 레벨을 구분해석(parse)해서 이름을 분석("com", 다음 "xxx", 다음 "xxx" 안의 "yyy" 식으로 분석)해야 하기 때문입니다. 이런 추가 부하가 걸리지 않도록 하기 위해, SWF 컴파일하기 전에 전처리기 소프트웨어를 사용하여 경로를 c58923409876.functionName() 식의 단일-레벨 고유 식별자로 축소시키는 개발자도 있습니다.
  • 어플리케이션이 같은 AS 클래스를 사용하는 SWF 파일 여럿으로 이루어진 경우, 컴파일 도중 해당 클래스를 선택 SWF 파일에서 제외시키십시오. 런타임 메모리 필요량을 줄이는 데 도움이 될 수 있습니다.
  • 타임라인 내 키프레임의 AS 완료에 많은 시간이 소요되는 경우, 그 코드를 여러 키프레임에 걸쳐 실행되도록 나누는 것을 고려해 보십시오.
  • 최종 SWF 파일을 퍼블리싱할 때 코드에서 trace() 문을 제거하십시오. Publish Settings 대화상자의 Flash 탭에 있는 Omit Trace Actions 체크 박스를 선택한 다음, 주석 처리하거나 지우면 됩니다. 디버깅에 사용되는 트레이스 문을 실행시간에 효율적으로 끌 수 있습니다.
  • 상속을 하면 메서드 호출 수와 메모리 사용량이 늘어납니다: 필요한 함수성이 전부 들어있는 클래스가, 상위 클래스에서 일부 함수성만을 상속받은 클래스보다, 런타임에서의 효율이 좋습니다. 그러므로 디자인을 할 때, 클래스의 확장성과 코드의 효율성 사이의 줄다리기를 해야 할 수도 있습니다.
  • 어떤 SWF 파일이 (foo.bar.CustomClass 와 같은) 커스텀 AS 클래스가 들어있는 다른 SWF 파일을 로드한 다음 언로드했다면, 그 클래스 정의는 메모리에 남아있습니다. 메모리 절약을 위해서는, 언로드된 SWF 파일의 커스텀 클래스를 명시적으로 지워줘야 합니다. delete 문에 클래스 이름 전체를 확실히 지정하여 사용해 주십시오. 예: delete foo.bar.CustomCLass
  • 모든 코드를 매 프레임마다 실행시킬 필요는 없으니, 시간상으로 100% 중요치 않은 것에 대해서는 (매 프레임마다 코드 일부가 바뀌는) 플립 플롭을 사용하세요.
  • 가급적 onEnterFrames 는 조금만 사용하도록 하십시오.
  • 수학 함수를 사용하기 보다는 데이터 테이블을 미리 계산하세요.
    1. 수학 계산을 많이 한다면, 값을 미리 계산한 다음 (가상) 변수 배열에 보관하는 것을 고려해 보십시오. 데이터 테이블에서 값을 빼 내는 것이 GFx 가 직접 계산하도록 하는 것보다 훨씬 빠를 수 있습니다.

루프

  • 루프나 반복 동작 최적화에 초점을 맞추십시오.
  • 사용되는 루프의 수와 각 루프에 들어가는 코드 양을 제한하세요.
  • 프레임 기반 루프는 필요가 없어지면 바로 멈춥니다.
  • 루프 안에서 한 함수를 여러번 호출하는 것은 좋지 않습니다.
  • 작은 함수의 내용을 루프 안에 포함시키는 것이 낫습니다.

함수

  • 가능하면 다중 함수 중첩은 피하십시오.
  • 함수 안에서 'with' 문을 사용하지 마십시오. 이 연산자가 붙으면 최적화가 무력해 집니다.

변수 / 프로퍼티

  • 존재하지 않는 변수, 오브젝트, 함수를 리퍼런스하지 마십시오.
  • 가급적이면 "var" 키워드를 사용합니다. 함수 안에서는 "var" 키워드가 특히나 중요한데, AS 컴파일러는 내부 레지스터를 해시-테이블에 넣고 이름으로 접근하기 보다는 인덱스로 직접 접근하는 식으로 로컬 변수로의 접근을 최적화시키기 때문입니다.
  • 로컬 변수로 충분하면 클래스 변수나 글로벌 변수는 쓰지 마세요.
  • 글로벌 변수는 자신을 정의한 무비클립이 제거되도 가비지 콜렉팅되지 않으니 제한적으로 사용하시는 것이 좋습니다.
  • 변수가 더이상 쓸 일이 없어지면 지우거나 null 로 설정하십시오. 그 데이터는 가비지 콜렉션 용으로 마킹됩니다. 변수를 지우면 실행시간 중의 메모리 사용량 최적화에 도움이 됩니다. 불필요한 애셋이 SWF 파일에서 제거되기 때문입니다. 그래서 null 로 설정하는 것보다는 지우는 것이 낫습니다.
  • 프로퍼티에 접근할 때는 항상 직접 접근해 보는 것이 좋습니다. AS getter 나 setter 메서드를 사용하면 다른 메서드 호출시보다 부하가 크게 걸립니다.

일반 최적화 꼼수


플래시 타임라인

플래시 저작 환경에 있어 두 가지 중요한 부분은 타임라인 프레임과 레이어 입니다. 이 영역은 애셋이 어디에 놓여 있는지를 나타내며 도큐멘트의 작동방식을 결정합니다. 타임라인과 라이브러리를 어찌 구성하여 사용했는지에 따라, 전체 FLA 파일과 그 전체적인 유용성 및 퍼포먼스가 달라집니다.

  • 프레임-기반 루프는 아껴 사용하십시오. 프레임-기반 애니메이션은 FPS 에 묶여있지 않은 시간-기반 모델과는 달리, 어플래케이션의 프레임율에 따라 달라집니다.
  • 프레임-기반 루프는 더이상 쓸 일이 없으면 중지시키세요.
  • 복잡한 코드 블록은 가능하면 한 프레임 이상으로 나누십시오.
  • 코드가 수백 줄인 스크립트는 백 단위 프레임 기반 트윈의 타임라인과 마찬가지로 프로세서를 많이 사용합니다.
  • 애니메이션/상호작용을 타임라인으로 쉽게 만들 수 있는지, AS 를 사용하여 단순화되고 모듈식으로 되어 있는지, 콘텐츠를 평가해 보시기 바랍니다.
  • 레이어 이름에 (Layer 1, Layer 2 식의) 기본값을 쓰지 마십시오. 복잡한 파일을 작업할 때는 기억하거나 애셋 위치를 잡기가 헛갈릴 수 있습니다.

일반적인 퍼포먼스 최적화

  • 트랜스폼을 합쳐 퍼포먼스를 낫게 하는 방법이 있습니다. 예를 들면 세 가지 트랜스폼을 중첩시키는 대신, 행렬 하나를 수동 계산하는 겁니다.
  • 서서히 느려진다면 메모리가 새는지 검사해 보십시오. 필요없어진 것은 확실히 버리도록 하시구요.
  • 저작 시간에는, trace() 문을 많이 사용하거나 텍스트 필드를 동적으로 업데이트하면 퍼포먼스가 저하되니 그러지 않는 것이 좋습니다. 가급적 필요할 때만 (즉 정기적이 아니라 뭔가 가끔 바뀔 때만) 업데이트하시기 바랍니다.
  • 적용 가능하다면, AS 를 포함하는 레이어와 프레임 라벨이 되는 레이어는 타임라인의 레이어 스택 맨위에 놓으세요. 예를 들면 AS 액션이 들어있는 레이어 이름을 따는 것이 흔히 쓰이는 좋은 방법입니다.
  • 프레임 액션을 다른 레이어에 넣지 마십시오. 그보다는 모든 액션을 한 레이어에 뭉치는 것이 좋습니다. 그러면 AS 코드 관리가 단순해지고, AS 실행 패스가 여러번 발생하는 데 따르는 부하가 사라져 퍼포먼스 향상도 가능합니다.

Advance (진행)

Advance 실행하는 데 시간이 너무 오래 걸리는 경우, 7 가지 정도 최적화가 가능합니다:

  • 모든 프레임마다 AS 코드를 실행하지 마십시오. 매 프레임마다 코드를 invoke 하는 onEnterFrame 핸들러도 아끼시고요.
  • 이벤트-주도형 프로그래밍 방법을 사용하십시오. 뭔가 바뀔 때만 명시적 Invoke 알림을 통해 텍스트 필드나 UI 상태값을 바꾸는 거죠.
  • 안보이는 무비 클립에서는 애니메이션을 중지시키십시오 (_visible 프로퍼티는 참으로 설정됐을 것이고, stop() 함수를 사용하여 애니메이션을 중지시킵니다). 그러면 Advance 리스트에서 그런 무비 클립이 제거됩니다. 참고로 부모 무비 클립이 중지되었어도, 자손을 포함한 계층구조 내 모든 무비 클립을 하나 하나 중지시켜 줘야 합니다.
  • _global.noInvisibleAdvance 을 확장해서 사용하는 대안 기법이 있습니다. 이 확장은 Advance 목록에서 안보이는 무비 클립 그룹을 일일히 중지시킬 필요 없이 제외시키는 데 요긴하게 쓸 수 있습니다. 이 확장 프로퍼티가 참으로 설정되면, 안보이는 무비 클립은 (그 자손을 포함해서) Advance 목록에 추가되지 않으므로 퍼포먼스가 향상됩니다. 한 가지 유념할 것은, 이 기법이 플래시와 완벽 호환되지 않는다는 점입니다. 플래시 파일이 숨겨진 무비 내 어떤 종류의 프레임별 처리에도 의존하지 않도록 하십시오. 이(것과 다른) 확장을 사용하려면 _global.gfxExtensions 를 참으로 설정하여 GFx 확장을 켜 줘야 한다는 점 잊지 마시구요.
  • 스테이지의 무비 클립 수를 줄이십시오. 무비 클립이 중첩될 때마다 Advance 도중 약간의 부하가 걸리므로, 불필요한 중첩은 자제하시기 바랍니다.
  • 타임라인 애니메이션, 키프레임 수, 셰이프 트윈을 줄이십시오.
  • GFx 2.2 이하 버전에서는 MovieClip.noAdvance 프로퍼티를 참으로 설정하면, 보이고 화면상에는 있지만 Advance 나 onEnterFrame 이 필요치 않은 스태틱 무비 클립의 Advance 를 막는 것이 가능합니다. _global.gfxExtensions 를 참으로 설정하여 GFx 확장을 켜 줘야 이 확장 기능을 사용할 수 있습니다. 그러나 GFx 3.0 이상 버전에서는 대부분의 경우에 이렇게 해 줄 필요가 없습니다. GFx 3.0 은 중지된 무비 클립을 전혀 Advance 하거나 Process 하지 않습니다. 더이상 Advance 내 전체 렌더링 그래프를 처리하지 않으며, 그 대신 활성 목록을 유지하기 때문입니다. 이러한 발전 덕에, noAdvance/noInvisibleAdvance 의 주 용도는 그래프의 일부분 처리를 생략하기 위함인지라, 거의 필요가 없어졌습니다. 여전히 onEnterFrame 이나 약간의 애니메이션 오브젝트를 끄는데 사용할 수는 있지만, onEnterFrame 핸들러 자체를 제거한다든가 하는 다른 방식도 있기 때문에 그럴 필요성도 희박합니다.

onClipEvent 와 on 이벤트

onClipEvent() 와 on() 이벤트는 자제하시고, onEnterFrame, onPress 등을 사용하세요. 이유는 여러가지가 있습니다:

  • 함수 스타일의 이벤트 핸들러는 런타임 설치/제거 가능합니다.
  • 함수 안의 바이트 코드는 구형 onClipEvent 나 on 핸들러 안에서보다 최적화가 잘 됩니다. 주요 최적화는 this, _global, arguments, super 등을 미리 캐시하는 것과, 로컬 변수에 256 내부 레지스터를 사용하는 것에 있습니다. 이 최적화는 함수에 대해서만 작동합니다.

첫 프레임이 실행되기 전 onLoad 함수 스타일의 핸들러 설치가 필요할 때, 유일한 문제점이 발생합니다. 이 경우, onEnterFrame 설치를 위해 문서화되지 않은 이벤트 핸들러 onClipEvent(construct) 를 사용할 수 있습니다.

  onClipEvent(construct) {
    this.onLoad = function() {
      //function body
    }
  }
  

아니면 onClipEvent(load) 를 사용하고 거기서 정규 함수를 호출합니다. 이 접근법은 함수 호출이 추가되는 데 대한 부하가 추가로 걸려 효율이 떨어지기는 합니다.

onEnterFrame

onEnterFrame 이벤트 핸들러 사용을 최소화하십시오. 그게 아니라면 항상 실행시키기 보다는, 필요할 때 설치하고 제거해 주기라도 해야 합니다. onEnterFrame 핸들러를 너무 많이 쓰면 퍼포먼스가 심각하게 떨어질 수 있습니다. 대안으로는 setInterval 와 setTimeout 함수를 고려해 보십시오. setInterval 을 사용할 때는:

  • 핸들러가 더이상 필요해 지지 않으면 clearInterval 을 호출해야 한다는 점, 잊지 마시구요.
  • setInterval 과 setTimeout 핸들러는 onEnterFrame 보다 자주 실행되면 그보다 느려질 수도 있습니다. 그렇게 되지 않기 위해서는 시간 간격 값을 넉넉히 잡으시기 바랍니다.

onEnterFrame 핸들러를 제거하려면 delete 명령을 사용합니다:

  delete this.onEnterFrame;
  delete mc.onEnterFrame;
  

onEnterFrame 에 null 을 할당(this.onEnterFrame = null)하거나 정의되지 않은 상태로 두지 마십시오. onEnterFrame 핸들러가 완전히 제거되지 않습니다. GFx 는 onEnterFrame 이라는 이름의 멤버가 존재하기에 이 핸들러를 계속해서 처리하려 할 것입니다.

Var 키워드

가급적 var 키워드를 사용하십시오. AS 컴파일러가 로컬 변수에 대한 접근을 최적화하는 방식은, 내부 레지스터를 해시 테이블에 넣고 이름으로 접근하기 보다는 인덱스로 직접 접근하는 방식을 쓰기 때문에, 함수 안에서는 특히나 var 키워드를 쓰는 것이 좋습니다. var 키워드를 사용하면 AS 함수 실행 속도가 두 배도 가능합니다.

최적화되지 않은 코드:

  var i = 1000;
  countIt = function() {
    num = 0;
    for(j=0; j<i; j++) {
      j++;
      num += Math.random();
    }
    displayNumber.text = num;
  }
  

최적화된 코드:

  var i = 1000;
  countIt = function() {
    var num = 0;
    var ii = i;
    for(var j=0; j<ii; j++) {
      j++;
      num += Math.random();
    }
    displayNumber.text = num;
  }
  

미리 캐시하기

로컬 변수 내 자주 액세스되는 읽기-전용 오브젝트 멤버를 (var 키워드로) 미리 캐시합니다.

최적화되지 않은 코드:

  function foo(var obj:Object) {
    for (var i = 0; i < obj.size; i++) {
      obj.value[i] = obj.num1 * obj.num2;
    }
  }
  

최적화된 코드:

  function foo(var obj:Object) {
    var sz = obj.size;
    var n1 = obj.num1;
    var n2 = obj.num1;
    for (var i = 0; i < sz; i++) {
      obj.value[i] = n1*n2;
    }
  }
  

미리 캐시하기는 다른 상황에서도 효율적으로 사용할 수 있습니다. 예를 더 들어보자면:

  var floor = Math.floor
  var ceil = Math.ceil
  num = floor(x) ? ceil(y);
  var keyDown = Key.isDown;
  var keyLeft = Key.LEFT;
  if (keyDown(keyLeft)) {
    // do something;
  }
  

긴 경로 미리 캐시

다음과 같이 긴 경로를 반복 사용하지 마십시오:

  mc.ch1.hc3.djf3.jd9._x = 233;
  mc.ch1.hc3.djf3._x = 455;
  

로컬 변수의 파일 경로 부분을 미리 캐시하는 겁니다:

  var djf3 = mc.ch1.hc3.djf3;
  djf3._x = 455;
  var jd9 = djf3.jd9;
  jd9._x = 223;
  

복잡한 표현식

복잡한 C 스타일의 표현식을 자제합니다:

  this[_global.mynames[queue]][_global.slots[i]].gosplash.text = _global.MyStrings[queue];
  

이런 표현식은 작은 부분으로 나누고, 로컬 변수에 중간 데이터를 보관합니다:

  var _splqueue = this[_global.mynames[queue]];
  var _splstring = _global.MyStrings[queue];
  var slot_i = _global.slots[i];
  _splqueue[slot_i].gosplash.text = _splstring;
  

분할된 부분에 리퍼런스가 여럿 있을 때는 특히나 중요합니다. 다음 루프를 예로 들어 봅시다:

  for(i=0; i<3; i++) {
    this[_global.mynames[queue]][_global.slots[i]].gosplash.text = _global.MyStrings[queue];
    this[_global.mynames[queue]][_global.slots[i]].gosplash2.text = _global.MyStrings[queue];
     this[_global.mynames[queue]][_global.slots[i]].gosplash2.textColor = 0x000000;
  }
  

위의 루프를 개선한 버전은 다음과 같습니다:

  var _splqueue = this[_global.mynames[queue]];
  var _splstring = _global.MyStrings[queue];
  for (var i=0; i<3; i++) {
    var slot_i = _global.slots[i];
    _splqueue[slot_i].gosplash.text = _splstring;
    _splqueue[slot_i].gosplash2.text = splstring;
    _splqueue[slot_i].gosplash2.textColor = 0x000000;
  }
  

위의 코드도 최적화 여지가 남아 있습니다. 가급적 같은 배열 요소를 여러 번 참조하지 않도록 하고요. 로컬 변수에서 해결된 오브젝트는 미리 캐시하는 것입니다:

  var _splqueue = this[_global.mynames[queue]];
  var _splstring = _global.MyStrings[queue];
  for (var i=0; i<3; i++) {
    var slot_i = _global.slots[i];
    var elem = _splqueue[slot_i];
    elem.gosplash.text = _splstring;
    var gspl2 = elem.gosplash2;
    gspl2.text = splstring;
    gspl2.textColor = 0x000000;
  }