亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Cocos2d-x不要隨便在onEnter里面addChild

發布時間:2020-06-03 01:35:47 來源:網絡 閱讀:353 作者:wyb10a10 欄目:游戲開發

使用任何版本的Cocos2d-x(1.x,2.x,3.0),在onEnter中調用addChild,都要小心謹慎,因為它有可能導致兩種莫名其妙的BUG,莫名其妙的BUG當然難以定位了!更何況這個BUG隱藏在引擎的底層。

接下來是場景還原:

在某個節點下,需要執行這樣一段邏輯,在游戲場景中,添加幾個節點,由于游戲場景就是該節點的父節點,于是就直接getParent然后調用父節點的addChild,在onEnter函數中添加看上去比較合適,因為這時候該節點的父節點可以訪問,而在init函數中,還沒有被添加到游戲場景中

神奇的事情發生了,在這之后添加的節點,都無法播放動畫了,而把節點添加的位置,移到該節點之前進行添加,動畫就可以正常播放,檢查了一下代碼,無果,先記下該問題

接下來又有一件神奇的事情發生了,我們的程序崩潰了!用排除法發現,是在onEnter下添加節點導致的崩潰,但是有趣的是,onEnter下的一個for循環添加5個節點,當我把節點數量該為4的時候,程序又可以正常執行了!而添加到5或者更多的時候,程序又崩潰了!

看到這里我仿佛明白了什么,打開2dx的CCNode::addChild的代碼,在每次addChild的時候,會根據當前數組的容量,進行擴容

void ccArrayDoubleCapacity(ccArray *arr)
{
    arr->max *= 2;
    CCObject** newArr = (CCObject**)realloc( arr->arr, arr->max * sizeof(CCObject*) );
    // will fail when there's not enough memory
    CCAssert(newArr != 0, "ccArrayDoubleCapacity failed. Not enough memory");
    arr->arr = newArr;
}

上面的代碼用realloc重新分配了內存,但是,在CCNode的onEnter中,是在遍歷這個數組,執行所有子節點的onEnter

void CCNode::onEnter()
{
    arrayMakeObjectsPerformSelector(m_pChildren, onEnter, CCNode*);
    
    this->resumeSchedulerAndActions();

    m_bIsRunning = true;

    if (m_eScriptType != kScriptTypeNone)
    {
        CCScriptEngineManager::sharedManager()->getScriptEngine()->executeNodeEvent(this, kCCNodeOnEnter);
    }
}

在arrayMakeObjectsPerformSelector中,調用到了2dx底層的一個宏,CCARRAY_FOREACH

#define CCARRAY_FOREACH(__array__, __object__)                                                                \
    if ((__array__) && (__array__)->data->num > 0)                                                            \
    for(CCObject** arr = (__array__)->data->arr, **end = (__array__)->data->arr + (__array__)->data->num-1;    \
    arr <= end && (((__object__) = *arr) != NULL/* || true*/);                                                \
    arr++)

這個宏用于遍歷CCArray,它是用指針偏移的方式進行遍歷,所以,當我們的數組擴容之后,指針的地址就變了,CCARRAY_FOREACH還在對原先的指針進行訪問,當然崩潰了
其實這個BUG很好解決,只需要修改一下CCARRAY_FOREACH的遍歷方式,改為下標訪問即可,在CCNode::onEnter函數下,將代碼調整為如下所示,BUG解決。

void CCNode::onEnter()
{
    //arrayMakeObjectsPerformSelector(m_pChildren, onEnter, CCNode*);
    if (NULL != m_pChildren)
    {
        for (int i = 0; i < m_pChildren->count(); ++i)
        {
            ((CCNode*)(m_pChildren->data->arr[i]))->onEnter();
        }
    }
    
    this->resumeSchedulerAndActions();

    m_bIsRunning = true;

    if (m_eScriptType != kScriptTypeNone)
    {
        CCScriptEngineManager::sharedManager()->getScriptEngine()->executeNodeEvent(this, kCCNodeOnEnter);
    }
}

也許我不應該在onEnter里面addChild,但cocos2d-x更不應該讓我在onEnter中添加節點之后崩潰

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

昌乐县| 库尔勒市| 芦溪县| 邢台县| 武陟县| 新建县| 城口县| 菏泽市| 马山县| 新沂市| 芷江| 红河县| 平乐县| 昌吉市| 上饶县| 安宁市| 克拉玛依市| 应城市| 蓬溪县| 深泽县| 彭泽县| 徐闻县| 绵阳市| 甘孜县| 安图县| 滨海县| 大宁县| 玉环县| 柳林县| 永登县| 明水县| 青田县| 白沙| 左贡县| 清新县| 新津县| 台前县| 兰西县| 来宾市| 灯塔市| 河池市|