CocosCreator ScrollView 최적화 시리즈 의 프레임 로드

머리말
JS 는 단일 스 레 드 입 니 다.즉,모든 작업 이 줄 을 서 야 한 다 는 것 을 의미 합 니 다.현재 하나의 작업 이 끝나 야 다음 작업 이 실 행 됩 니 다.앞의 임무 가 오래 걸 리 면 뒤의 임 무 는 계속 기다 릴 수 밖 에 없다.
코 코스 크 리 에이 터 는 자바 스 크 립 트/타 입 스 크 립 트 언어 로 개 발 된 것 으로 본질 적 으로 JS 이 며 이와 같은 특징 을 가지 고 있다.특히 잘못 사용 하면 인터페이스 가 끊 길 가능성 이 높다.
예 를 들 어 ScrollView 의 Content 를 위해 500 개의 노드 를 만 들 때 아래 인터페이스 가 끊 겨 죽 는 문제 가 발생 할 수 있 습 니 다.
PS:원래 불 러 오 는 과정 에서 loading 대화 상자 가 있 었 는데 끊 겨 서 나타 나 지 않 은 것 같 습 니 다.

본 고 를 읽 으 면'프레임 로드'기술 로 상기 문 제 를 어떻게 해결 하 는 지 알 게 될 것 이다.최종 효 과 는 다음 과 같다.

2.카드 사 문제 분석
정상 적 인 상황 에서 우리 가 ScrollView 를 위해 일정한 수량의 하위 노드 를 만 들 때 코드 는 이 럴 수 있 습 니 다.

public directLoad(length: number) {
    for (let i = 0; i < length; i++) {
        this._initItem(i);
    }
}
 
private _initItem(itemIndex: number) {
    let itemNode = cc.instantiate(this.itemPrefab);
    itemNode.width = this.scrollView.content.width / 10;
    itemNode.height = itemNode.width;
    itemNode.parent = this.scrollView.content;
    itemNode.setPosition(0, 0);
}
일반적으로 length 의 값 이 매우 작 습 니 다.예 를 들 어 10 개 일 때 프로그램 이 달 릴 때 문제 가 없 을 것 같 지만 사실은 자세히 살 펴 보면 사실은 잠시 걸 려 죽 을 것 입 니 다.다만 곧 끝 날 것 입 니 다.
특히 length 의 값 이 한 점 급,예 를 들 어 50+개 에 이 르 면 이 코드 는 위 에서 캡 처 한 모습 이 나타 날 것 이다.
결국 문 제 는cc.instantiate을 통 해 노드 를 만 들 고 이 노드setParent를 만 들 때 필요 한 시간 이 생각 보다 작 지 않다 는 것 이다.물론 생각 만큼 크 지 않다.그러나 일정한 수량 을 계속 만 들 면 문제 가 커진다.즉,이 노드 를 만 드 는 데 시간 이 걸 릴 수 있다.
시각 적 으로 이 문 제 를 이해 하면...음...아마 다음 그림 일 거 예요.

Direct Load
위의 그림 에 따 르 면 1~4 프레임 이 모두 점용 되 어 이 기간 에 모든 다른 논 리 를 실행 할 수 없 음 이 분명 합 니 다(Loading 대화 상자 가 나 오지 않 고 회전 애니메이션 카드 가 죽 는 등).
그럼 어떻게 해결 할 까요?
3.해결 방안(이론 편)
어떤 학생 들 은 Promise 비동기 로 해결 하려 고 했 을 수도 있 지만 이 문제 에 있어 Promise 는 빨간색 의 이 연속 적 으로 노드 를 만 드 는 코드 를 뒤에 놓 고 실 행 했 을 뿐 빨간색 코드 가 실 행 될 때 그 시간 에 걸 려 죽 기 때문에 Promise 는 이런 상황 에 대응 할 수 없다.
그럼 어떻게 해결 해 야 되 지?
그 중에서 하나의 해결 방안 은 바로 우리 가 오늘 말 하고 자 하 는'프레임 로드'인 데'프레임 로드'를 어떻게 이해 합 니까?
관례

Framing Load
위의 그림 과 결합 하면'프레임 로드'를 잘 이해 할 수 있 습 니 다.구체 적 인 집행 과정 은?
  • 먼저 시간 이 걸 려 죽은 코드 를 여러 소절 로 나 누 었 다
  • 그리고 각 프레임 마다 시간 을 나 누 어 이 단락 들 을 집행 한다
  • 이렇게 되면 각 프레임 마다 우 리 는 다른 논리 에 뛰 어 다 닐 시간 을 남 겼 다(그러면 Loading 대화 상자 도 나 올 수 있 고 회전 애니메이션 도 계속 할 수 있다)
  • OK,이론 을 분명히 말 하면 실제 적 으로 어떻게 하 죠?
    예 를 들 면:
  • 코드 를 어떻게 여러 소절 로 나 눕 니까?
  • 각 프레임 의 시간 을 어떻게 분배 하여 이 단락 들 을 집행 합 니까?
  • 이때 우 리 는 ES6(ES 2015)의 협 정―Generator을 사용 하여 우리 가 실현 하도록 도와 야 한다.
    4.해결 방안(코드 편)
    우리 의 두 번 째 절 에 예 를 들 어 사 용 된 코드(ScrollView 를 위해 일정한 수량의 하위 노드 를 만 듭 니 다)를 예 로 들 면 우 리 는 코드 를 여러 개의 작은 부분 으로 하고 각 프레임 의 시간 을 분배 하여 이 작은 부분 을 실행 할 것 입 니 다.
    4.1 Generator 를 이용 하여 코드 를 여러 개의 작은 부분 으로 나 누 었 다.
    분할 전:
    
    public directLoad(length: number) {
        for (let i = 0; i < length; i++) {
            this._initItem(i);
        }
    }
     
    private _initItem(itemIndex: number) {
        let itemNode = cc.instantiate(this.itemPrefab);
        itemNode.width = this.scrollView.content.width / 10;
        itemNode.height = itemNode.width;
        itemNode.parent = this.scrollView.content;
        itemNode.setPosition(0, 0);
    }
    분할 후:
    
    /**
     * (    )        Generator
     */
    private *_getItemGenerator(length: number) {
        for (let i = 0; i < length; i++) {
            yield this._initItem(i);
        }
    }
     
    /**
     * (         )
     */
    private _initItem(itemIndex: number) {
        let itemNode = cc.instantiate(this.itemPrefab);
        itemNode.width = this.scrollView.content.width / 10;
        itemNode.height = itemNode.width;
        itemNode.parent = this.scrollView.content;
        itemNode.setPosition(0, 0);
    }
    여기 서 원 리 는 Generator 를 이용 하여 한 번 의 for 순환 에서 모든 노드 를 만 들 고 for 순환 의 모든 단 계 를 작은 세그먼트 로 나 누 는 것 입 니 다.
    물론,이'분할 후'코드 는 달 릴 수 없습니다.왜냐하면 그것 은 단지 분할 절 차 를 실 현 했 을 뿐,그것 을 달 릴 수 있 도록 해 야 하기 때 문 입 니 다.우 리 는 아래 의 두 번 째 코드 를 올 려 야 합 니 다.
    4.2 각 프레임 의 시간 을 배정 하여 집행 한다.
    우리 아까 그림 한 번 더 볼 게 요.

    Framing Load
    코드
    
    /**
     *       
     */
    async framingLoad(length: number) {
        await this.executePreFrame(this._getItemGenerator(length), 1);
    }
     
    /**
     *      Generator   
     *
     * @param generator    
     * @param duration     (ms)
     *               Generator     ,         。
     *              8ms,    1 (  16ms) ,  8ms        
     */
    private executePreFrame(generator: Generator, duration: number) {
        return new Promise((resolve, reject) => {
            let gen = generator;
            //       
            let execute = () => {
     
                //     ,        
                let startTime = new Date().getTime();
     
                //       Generator                 
                for (let iter = gen.next(); ; iter = gen.next()) {
     
                    //             Generator      
                    //      ,         
                    if (iter == null || iter.done) {
                        resolve();
                        return;
                    }
     
                    //           ,       
                    //            ,              
                    if (new Date().getTime() - startTime > duration) {
                        
                        //      ,         ,    ,       
                        this.scheduleOnce(() => {
                            execute();
                        });
                        return;
                    }
                }
            };
     
            //       
            execute();
        });
    }
     
    코드 에 대량의 주석 이 첨부 되 어 있 지만 몇 가지 설명 이 필요 합 니 다.
  • 이 작은 임무 들 이 이미 다 수행 되 었 는 지 알 기 위해 저 는 Promise 를 사 용 했 습 니 다.다 완 성 했 을 때resolve한 번
  • 모든 작은 코드 세그먼트 의 실행 시간 이 고정 되 지 않 을 수 있 고 우리 의 기대 시간 을 초과 할 수 있 습 니 다.예 를 들 어 우 리 는 모든 프레임 에 1ms 를 분배 하여 이런 작은 코드 세그먼트 를 실행 하 기 를 기대한다.앞의 3 단 작은 코드 세그먼트 를 가정 하고 모든 단락 의 실행 시간 은 0.2ms,0.5ms,0.4ms 로 가정 한다.그러면 내 가 제시 한 이 코드 에서 이 3 단 작은 코드 세그먼트 를 실행 한 다음 에 본 프레임 을 중지 하고 이 작은 코드 세그먼트 를 계속 집행 할 것 이다.왜냐하면 이곳 의 시간 은 이미 1.1ms 이기 때문이다.내 가 설정 한 1ms 보다 0.1 ms 더 많아.물론 코드 를 스스로 바 꾸 어 최대 1ms 에 따라 엄 격 히 실행 하도록 할 수 있 습 니 다.시간 을 초과 하지 않 고 실행 할 수 있 습 니 다(즉,세 번 째 소절 을 실행 하지 않 습 니 다)
  • 이로써 우 리 는 어느 정도 에'프레임 로드'를 실현 했다.
    이 항목 의 모든 그림,코드 는 Github 창고 에 있 습 니 다.인증 을 실행 하려 면 항목 을 내 려 놓 으 면 됩 니 다.코드 검증 을 직접 하지 않 아 도 됩 니 다.
    👉👉https://github.com/zhitaocai/CocosCreator-ScrollVIewPlus👈👈
    총화
  • 비록 우리 의 제목 은'ScrollView 최적화 시리즈'이지 만 나 는'프레임 로드 를 이용 하여 ScrollView 최적화'하 는 경향 이 있다.이 글 에서 우리 가 예 를 들 면 노드 를 만 드 는 것 이다.그러나 나 는 일부러'프레임 나 누 기 생 성'을 말 하지 않 는 다.이것 은 내 가「 」성능 최적화 방안 이 라 고 생각 하기 때문이다.'프레임 나 누 기 생 성','프레임 나 누 기 운행','프레임 나 누 기 계산','프레임 나 누 기 렌 더 링'등 이 있다.
  • 프레임 실현 에 있어 서 우 리 는this.scheduleOnce함 수 를 사 용 했 지만 사실은update(dt:number)에서 실 행 될 수 있 습 니 다.제'테스트 항목'을 수정 하여 검증 해 보 세 요~
  • TypeScript 를 Generator 로 사용 하려 면 Cocos 프로젝트 의tsconfig.json을 고 쳐 야 합 니 다.compilerOptions.lib배열 에 추가es2015
  • 이상 은 바로 CocosCreator ScrollView 최적화 시리즈 의 프레임 로드 에 대한 상세 한 내용 입 니 다.CocosCreator ScrollView 최적화 프레임 로드 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 하 십시오!

    좋은 웹페이지 즐겨찾기