Use any version of Cocos2d-x (1.x,2.x,3.0), call Addchild in OnEnter, be careful, because it can lead to two kinds of inexplicable bugs, the inexplicable bug is of course difficult to locate! Not to mention the bug is hidden in the bottom of the engine.
Next is the scene restore:
Under a certain node, you need to execute such a logic, in the game scene, add a few nodes, because the game scene is the parent node of the node, so directly getparent and then call the parent node Addchild, in the OnEnter function to add looks more appropriate, Because the parent node of the node can be accessed at this time, and in the Init function, it has not been added to the game scene
The magical thing happened, after this added node, can not play the animation, and add the location of the node to the node before moving to add, the animation can play normally, check the code, no results, first write down the problem.
Then another magical thing happened and our program crashed! With the exclusion method found, is the onenter under the addition of nodes caused by the crash, but interestingly, onenter under a For loop add 5 nodes, when I put the number of nodes that is 4, the program can be normal execution! And when added to 5 or more, the program crashes again!
See here I seem to understand what, open 2dx ccnode::addchild code, in each Addchild, will be based on the current array capacity, to expand.
1 voidCcarraydoublecapacity (Ccarray *arr)2 {3Arr->max *=2;4ccobject** NEWARR = (ccobject**)realloc(Arr->arr, Arr->max *sizeof(ccobject*) );5 //Would fail when there's not enough memory6Ccassert (NEWARR! =0,"Ccarraydoublecapacity failed. Not enough memory");7Arr->arr =NEWARR;8}
The above code re-allocates memory with ReAlloc, but in Ccnode's onenter, it is traversing the array, executing all the child nodes OnEnter
1 voidCcnode::onenter ()2 {3Arraymakeobjectsperformselector (M_pchildren, OnEnter, ccnode*);4 5 This-resumeschedulerandactions ();6 7M_bisrunning =true;8 9 if(M_escripttype! =Kscripttypenone)Ten { OneCcscriptenginemanager::sharedmanager ()->getscriptengine ()->executenodeevent ( This, kccnodeonenter); A } -}
In Arraymakeobjectsperformselector, a macro is called to the bottom of the 2DX, Ccarray_foreach
1 #defineCcarray_foreach (__array__, __object__)2 if((__array__) && (__array__)->data->num >0) 3 for(ccobject** arr = (__array__)->data->arr, **end = (__array__)->data->arr + (__array__)->data->num-1; 4Arr <= End && (((__object__) = *arr)! = NULL/*| | true*/); 5arr++)
This macro is used to traverse Ccarray, which is traversed by a pointer offset, so when our array is expanded, the address of the pointer changes, and Ccarray_foreach is still accessing the original pointer, which of course crashes.
In fact, this bug is very good to solve, only need to modify the Ccarray_foreach traversal, instead of access to subscript, under the Ccnode::onenter function, the code is adjusted to the following, the bug resolved
1 voidCcnode::onenter ()2 {3 //Arraymakeobjectsperformselector (M_pchildren, OnEnter, ccnode*);4 if(NULL! =M_pchildren)5 {6 for(inti =0; I < M_pchildren->count (); ++i)7 {8((ccnode*) (m_pchildren->data->arr[i))OnEnter ();9 }Ten } One A This-resumeschedulerandactions (); - -M_bisrunning =true; the - if(M_escripttype! =Kscripttypenone) - { -Ccscriptenginemanager::sharedmanager ()->getscriptengine ()->executenodeevent ( This, kccnodeonenter); + } -}
Do not Addchild () in OnEnter ()