前言
本文基于 Cocos Creator 2.4.5 撰寫蔑舞。
?? 普天同慶
來(lái)了來(lái)了皆串,《源碼解讀》系列文章終于又來(lái)了!
?? 溫馨提醒
本文包含大段引擎源碼追驴,使用大屏設(shè)備閱讀體驗(yàn)更佳械哟!
Hi There!
節(jié)點(diǎn)(cc.Node)作為 Cocos Creator 引擎中最基本的單位,所有組件都需要依附在節(jié)點(diǎn)上殿雪。
同時(shí)節(jié)點(diǎn)也是我們?nèi)粘i_(kāi)發(fā)中接觸最頻繁的東西暇咆。
我們經(jīng)常會(huì)需要「改變節(jié)點(diǎn)的排序」來(lái)完成一些效果(如圖像的遮擋)。
A Question?
?? 你有沒(méi)有想過(guò):
節(jié)點(diǎn)的排序是如何實(shí)現(xiàn)的丙曙?
Oops!
?? 我在分析了源碼后發(fā)現(xiàn):
節(jié)點(diǎn)的排序并沒(méi)有想象中那么簡(jiǎn)單爸业!
?? 渣皮語(yǔ)錄
聽(tīng)皮皮一句勸,zIndex 的水太深亏镰,你把握不壮犊酢!
正文
節(jié)點(diǎn)順序 (Node Order)
?? 如何修改節(jié)點(diǎn)的順序索抓?
首先钧忽,在 Cocos Creator 編輯器中的「層級(jí)管理器」中毯炮,我們可以隨意拖動(dòng)節(jié)點(diǎn)來(lái)改變節(jié)點(diǎn)的順序。
?? 但是耸黑,在代碼中我們要怎么做呢桃煎?
我最先想到的是節(jié)點(diǎn)的 setSiblingIndex
函數(shù),然后是節(jié)點(diǎn)的 zIndex
屬性大刊。
我猜大多數(shù)人都不清楚這兩個(gè)方案有什么區(qū)別为迈。
那么接下來(lái)就讓我們深入源碼,一探究竟缺菌!
siblingIndex
「siblingIndex」即「同級(jí)索引」葫辐,意為「同一父節(jié)點(diǎn)下的兄弟節(jié)點(diǎn)間的位置」姓迅。
siblingIndex 越小的節(jié)點(diǎn)排越前葡公,索引最小值為 0
,也就是第一個(gè)節(jié)點(diǎn)的索引值。
需要注意的是蛾绎,實(shí)際上節(jié)點(diǎn)并沒(méi)有 siblingIndex 屬性,只有 getSiblingIndex
和 setSiblingIndex
這兩個(gè)相關(guān)函數(shù)鸦列。
注:本文統(tǒng)一使用 siblingIndex 來(lái)代指 getSiblingIndex
和 setSiblingIndex
函數(shù)租冠。
另外,getSiblingIndex
和 setSiblingIndex
函數(shù)是由 cc._BaseNode
實(shí)現(xiàn)的薯嗤。
?? cc._BaseNode
大家對(duì)這個(gè)類可能會(huì)比較陌生顽爹,簡(jiǎn)單來(lái)說(shuō)
cc._BaseNode
是cc.Node
的基類。此類「定義了節(jié)點(diǎn)的基礎(chǔ)屬性和函數(shù)」骆姐,包括但不僅限于
setParent
镜粤、addChild
和getComponent
等常用函數(shù)...
?? 源碼節(jié)選:
函數(shù):cc._BaseNode.prototype.getSiblingIndex
getSiblingIndex() {
if (this._parent) {
return this._parent._children.indexOf(this);
} else {
return 0;
}
},
函數(shù):cc._BaseNode.prototype.setSiblingIndex
setSiblingIndex(index) {
if (!this._parent) {
return;
}
if (this._parent._objFlags & Deactivating) {
return;
}
var siblings = this._parent._children;
index = index !== -1 ? index : siblings.length - 1;
var oldIndex = siblings.indexOf(this);
if (index !== oldIndex) {
siblings.splice(oldIndex, 1);
if (index < siblings.length) {
siblings.splice(index, 0, this);
} else {
siblings.push(this);
}
this._onSiblingIndexChanged && this._onSiblingIndexChanged(index);
}
},
[源碼] base-node.js#L514: https://github.com/cocos-creator/engine/blob/2.4.5/cocos2d/core/utils/base-node.js#L514
??? 做了什么?
扒拉源碼后發(fā)現(xiàn)玻褪,siblingIndex 的本質(zhì)其實(shí)很簡(jiǎn)單肉渴。
那就是「當(dāng)前節(jié)點(diǎn)在父節(jié)點(diǎn)的 _children
屬性中的下標(biāo)(位置)」。
getSiblingIndex
函數(shù)返回的是「當(dāng)前節(jié)點(diǎn)在父節(jié)點(diǎn)的 _children
屬性中的下標(biāo)(位置)」带射。
setSiblingIndex
函數(shù)則是設(shè)置「當(dāng)前節(jié)點(diǎn)在父節(jié)點(diǎn)的 _children
屬性中的下標(biāo)(位置)」同规。
??
cc._BaseNode.prototype._children
節(jié)點(diǎn)的
_children
屬性其實(shí)就是節(jié)點(diǎn)的children
屬性。而
children
屬性是一個(gè)getter
窟社,返回的是自身的_children
屬性券勺。另外
children
屬性沒(méi)有實(shí)現(xiàn)setter
,所以你直接給children
屬性賦值是無(wú)效的灿里。
zIndex
「zIndex」是「用來(lái)對(duì)節(jié)點(diǎn)進(jìn)行排序的關(guān)鍵屬性」关炼,它決定了一個(gè)節(jié)點(diǎn)在兄弟節(jié)點(diǎn)之間的位置。
zIndex
的值介于 cc.macro.MIN_ZINDEX
和 cc.macro.MAX_ZINDEX
之間匣吊。
另外盗扒,zIndex
屬性是在 cc.Node
內(nèi)使用 Cocos 定制版 getter
和 setter
實(shí)現(xiàn)的跪楞。
?? 源碼節(jié)選:
屬性: cc.Node.prototype.zIndex
// 為了減少篇幅,已省略部分不相關(guān)代碼
zIndex: {
get() {
return this._localZOrder >> 16;
},
set(value) {
if (value > macro.MAX_ZINDEX) {
value = macro.MAX_ZINDEX;
} else if (value < macro.MIN_ZINDEX) {
value = macro.MIN_ZINDEX;
}
if (this.zIndex !== value) {
this._localZOrder = (this._localZOrder & 0x0000ffff) | (value << 16);
this.emit(EventType.SIBLING_ORDER_CHANGED);
this._onSiblingIndexChanged();
}
}
},
[源碼] CCNode.js#L1549: https://github.com/cocos-creator/engine/blob/2.4.5/cocos2d/core/CCNode.js#L1549
??? 做了什么侣灶?
扒拉源碼后發(fā)現(xiàn)甸祭,zIndex
的本質(zhì)其實(shí)也很簡(jiǎn)單。
那就是「返回或設(shè)置節(jié)點(diǎn)的 _localZOrder
屬性」褥影。
?? 沒(méi)那么簡(jiǎn)單池户!
有趣的是,在 getter
中并沒(méi)有直接返回 _localZOrder
屬性凡怎,而是返回了 _localZOrder
屬性右移(>>
)16 位后的數(shù)值校焦。
在 setter
中設(shè)置 _localZOrder
屬性時(shí)也并非簡(jiǎn)單的賦值,又是進(jìn)行了一頓位操作:
這里我們以二進(jìn)制數(shù)的視角來(lái)分解該函數(shù)內(nèi)的位操作统倒。
- 通過(guò)
& 0x0000ffff
取出原_localZOrder
的「低 16 位」寨典; - 將目標(biāo)值
value
「左移 16 位」; - 將左移后的
value
作為「高 16 位」與原_localZOrder
的「低 16 位」合并房匆; - 最后得到一個(gè)「32 位的二進(jìn)制數(shù)」并賦予
_localZOrder
耸成。
?? 嗯?
慢著浴鸿!
_localZOrder
又是干啥用的井氢?咋這么繞!別急岳链,答案在后面~
排序 (Sorting)
細(xì)心的朋友應(yīng)該發(fā)現(xiàn)了花竞,siblingIndex 和 zIndex
的源碼中都沒(méi)有包含實(shí)際的排序邏輯。
但是它們都有一個(gè)共同點(diǎn):「最后都調(diào)用了自身的 _onSiblingIndexChanged
函數(shù)」掸哑。
_onSiblingIndexChanged
?? 源碼節(jié)選:
函數(shù):cc.Node.prototype._onSiblingIndexChanged
_onSiblingIndexChanged() {
if (this._parent) {
this._parent._delaySort();
}
},
??? 做了什么约急?
而 _onSiblingIndexChanged
函數(shù)內(nèi)則是調(diào)用了「父節(jié)點(diǎn)」的 _delaySort
函數(shù)。
_delaySort
?? 源碼節(jié)選:
函數(shù):cc.Node.prototype._delaySort
_delaySort() {
if (!this._reorderChildDirty) {
this._reorderChildDirty = true;
cc.director.__fastOn(cc.Director.EVENT_AFTER_UPDATE, this.sortAllChildren, this);
}
},
??? 做了什么苗分?
一頓操作順藤摸瓜后發(fā)現(xiàn)厌蔽,真正進(jìn)行排序的地方是「父節(jié)點(diǎn)」的 sortAllChildren
函數(shù)。
?? 盲生俭嘁,你發(fā)現(xiàn)了華點(diǎn)躺枕!
值得注意的是,
_delaySort
函數(shù)中的sortAllChildren
函數(shù)調(diào)用不是立即觸發(fā)的供填,而是會(huì)在下一次update
(生命周期)后觸發(fā)拐云。延遲觸發(fā)的目的應(yīng)該是為了避免在同一幀內(nèi)的重復(fù)調(diào)用,從而減少不必要的性能損耗近她。
sortAllChildren
?? 源碼節(jié)選:
函數(shù):cc.Node.prototype.sortAllChildren
// 為了減少篇幅叉瘩,已省略部分不相關(guān)代碼
sortAllChildren() {
if (this._reorderChildDirty) {
this._reorderChildDirty = false;
// Part 1
var _children = this._children, child;
this._childArrivalOrder = 1;
for (let i = 0, len = _children.length; i < len; i++) {
child = _children[i];
child._updateOrderOfArrival();
}
eventManager._setDirtyForNode(this);
// Part 2
if (_children.length > 1) {
let child, child2;
for (let i = 1, count = _children.length; i < count; i++) {
child = _children[i];
let j = i;
for (;
j > 0 && (child2 = _children[j - 1])._localZOrder > child._localZOrder;
j--
) {
_children[j] = child2;
}
_children[j] = child;
}
this.emit(EventType.CHILD_REORDER, this);
}
cc.director.__fastOff(cc.Director.EVENT_AFTER_UPDATE, this.sortAllChildren, this);
}
},
[源碼] CCNode.js#L3680: https://github.com/cocos-creator/engine/blob/2.4.5/cocos2d/core/CCNode.js#L3680
上半部分 (Part 1)
隨著一步步深入,我們終于來(lái)到了關(guān)鍵部分粘捎。
現(xiàn)在讓我們琢磨琢磨這個(gè) sortAllChildren
函數(shù)薇缅。
進(jìn)入該函數(shù)的前半段危彩,映入眼簾的是一行賦值語(yǔ)句,將 _childArrivalOrder
屬性設(shè)(重置)為 1
泳桦;
緊跟其后的是一個(gè) for 循環(huán)汤徽,遍歷了當(dāng)前節(jié)點(diǎn)的所有「子節(jié)點(diǎn)」,并一一執(zhí)行「子節(jié)點(diǎn)」的 _updateOrderOfArrival
函數(shù)灸撰。
?? 嗯谒府?這個(gè) _updateOrderOfArrival
函數(shù)又是何方神圣?
_updateOrderOfArrival
?? 源碼節(jié)選:
函數(shù):cc.Node.prototype._updateOrderOfArrival
_updateOrderOfArrival() {
var arrivalOrder = this._parent ? ++this._parent._childArrivalOrder : 0;
this._localZOrder = (this._localZOrder & 0xffff0000) | arrivalOrder;
this.emit(EventType.SIBLING_ORDER_CHANGED);
},
??? 做了什么浮毯?
顯而易見(jiàn)的是完疫,_updateOrderOfArrival
函數(shù)的作用就是「更新節(jié)點(diǎn)的 _localZOrder
屬性」。
?? 該函數(shù)中同樣也使用了位操作:
同上债蓝,以二進(jìn)制數(shù)的視角來(lái)進(jìn)行分解這里的位操作壳鹤。
- 將父節(jié)點(diǎn)的
_childArrivalOrder
(前置)自增1
,并賦予arrivalOrder
(如無(wú)父節(jié)點(diǎn)則為0
)饰迹; - 通過(guò)
& 0xffff0000
取出當(dāng)前節(jié)點(diǎn)的_localZOrder
的「高 16 位」芳誓; - 將
arrivalOrder
作為「低 16 位」與當(dāng)前節(jié)點(diǎn)的_localZOrder
的「高 16 位」合并; - 最后得到一個(gè)新的「32 位的二進(jìn)制數(shù)」并賦予當(dāng)前節(jié)點(diǎn)的
_localZOrder
屬性蹦锋。
?? 看到這里你是不是已經(jīng)開(kāi)始迷惑了兆沙?
別擔(dān)心欧芽,答案即將揭曉莉掂!
下半部分 (Part 2)
而 sortAllChildren
函數(shù)的下半部分就比較好理解了。
基本就是通過(guò)「插入排序(Insertion Sort)」來(lái)「排序當(dāng)前節(jié)點(diǎn)的 _children
屬性(子節(jié)點(diǎn)數(shù)組)」千扔。
其中主要根據(jù)子節(jié)點(diǎn)的 _localZOrder
屬性的值來(lái)進(jìn)行排序憎妙,_localZOrder
屬性值小的子節(jié)點(diǎn)排前面,反之排后面曲楚。
排序的關(guān)鍵 (Key of sorting)
?? 分析完源碼后發(fā)現(xiàn)厘唾,節(jié)點(diǎn)的排序并沒(méi)有想象中那么簡(jiǎn)單。
我們可以先得出幾個(gè)結(jié)論:
- siblingIndex 是節(jié)點(diǎn)在父節(jié)點(diǎn)的
children
屬性中的下標(biāo)龙誊; -
zIndex
是一個(gè)獨(dú)立的屬性抚垃,和 siblingIndex 沒(méi)有直接聯(lián)系; - siblingIndex 和
zIndex
的改變都會(huì)觸發(fā)排序趟大; - siblingIndex 和
zIndex
共同組成了節(jié)點(diǎn)的_localZOrder
鹤树; -
zIndex
的權(quán)重比 siblingIndex 大; - 節(jié)點(diǎn)的
_localZOrder
直接決定了節(jié)點(diǎn)的最終順序逊朽。
siblingIndex 如何影響排序 (How siblingIndex affects sorting)
我們前面有提到:
-
getSiblingIndex
函數(shù)「返回了當(dāng)前節(jié)點(diǎn)在父節(jié)點(diǎn)的_children
屬性中的下標(biāo)(位置)」罕伯。 -
setSiblingIndex
函數(shù)「設(shè)置了當(dāng)前節(jié)點(diǎn)在父節(jié)點(diǎn)的_children
屬性中的下標(biāo)(位置),并通知父節(jié)點(diǎn)進(jìn)行排序」叽讳。
隨后在父節(jié)點(diǎn)的 sortAllChildren
函數(shù)中的上半部分追他,會(huì)以這個(gè)下標(biāo)作為節(jié)點(diǎn) _localZOrder
的低 16 位坟募。
?? 所以我們可以這樣理解:
siblingIndex 是元素下標(biāo),在排序過(guò)程中邑狸,其決定了 _localZOrder
的「低 16 位」懈糯。
zIndex 如何影響排序 (How zIndex affects sorting)
我們前面有提到:
-
zIndex
的getter
「返回了_localZOrder
的高 16 位」。 -
zIndex
的setter
「設(shè)置了_localZOrder
的高 16 位单雾,并通知父節(jié)點(diǎn)進(jìn)行排序」昂利。
?? 所以我們可以這樣理解:
zIndex
實(shí)際上只是一個(gè)軀殼,其本質(zhì)是 _localZOrder
的「高 16 位」铁坎。
_localZOrder 如何決定順序 (How _localZOrder works)
父節(jié)點(diǎn)的 sortAllChildren
函數(shù)中根據(jù)子節(jié)點(diǎn)的 _localZOrder
大小來(lái)進(jìn)行最終排序蜂奸。
我們可以將 _localZOrder
看做一個(gè)「32 位二進(jìn)制數(shù)」,其由 siblingIndex 和 zIndex
共同組成硬萍。
但是扩所,為什么說(shuō)「zIndex
的權(quán)重比 siblingIndex 大」呢?
因?yàn)?zIndex
決定了 _localZOrder
的「高 16 位」朴乖,而 siblingIndex 決定了 _localZOrder
的「低 16 位」祖屏。
所以,只有在 zIndex
相等的情況下买羞,siblingIndex 的大小才有決定性意義袁勺。
而在 zIndex
不相等的情況下,siblingIndex 的大小就無(wú)所謂了畜普。
?? 舉個(gè)栗子
這里有兩個(gè) 32 位二進(jìn)制數(shù)(偽代碼):
- A:
0000 0000 0000 0001 xxxx xxxx xxxx xxxx
- B:
0000 0000 0000 0010 xxxx xxxx xxxx xxxx
由于 B 的「高 16 位」(
0000 0000 0000 0010
)比 A 的「高 16 位」(0000 0000 0000 0001
)大期丰,所以無(wú)論他們的「低 16 位」中的x
是什么,B 都會(huì)永遠(yuǎn)大于 A吃挑。
實(shí)驗(yàn)一下 (Experiment)
我們可以寫個(gè)小組件來(lái)測(cè)試下 siblingIndex 和 zIndex
對(duì)于 _localZOrder
的影響钝荡。
?? 一頓打碼:
const { ccclass, property, executeInEditMode } = cc._decorator;
@ccclass
@executeInEditMode
export default class Test_NodeOrder extends cc.Component {
@property({ displayName: 'siblingIndex' })
get siblingIndex() {
return this.node.getSiblingIndex();
}
set siblingIndex(value) {
this.node.setSiblingIndex(value);
}
@property({ displayName: 'zIndex' })
get zIndex() {
return this.node.zIndex;
}
set zIndex(value) {
this.node.zIndex = value;
}
@property({ displayName: '_localZOrder' })
get localZOrder() {
return this.node._localZOrder;
}
@property({ displayName: '_localZOrder (二進(jìn)制)' })
get localZOrderBinary() {
return this.node._localZOrder.toString(2).padStart(32, 0);
}
}
場(chǎng)景一 (Scene 1)
在 1 個(gè)節(jié)點(diǎn)下放置了 1 個(gè)子節(jié)點(diǎn)。
?? 子節(jié)點(diǎn)的排序信息:
一般來(lái)說(shuō)舶衬,由于節(jié)點(diǎn)的 _childArrivalOrder
是從 1
開(kāi)始的埠通,并且在計(jì)算時(shí)會(huì)先自增 1
。
所以子節(jié)點(diǎn)的 _localZOrder
的「低 16 位」總會(huì)比其 siblingIndex 大 2 個(gè)數(shù)逛犹。
場(chǎng)景二 (Scene 2)
在 1 個(gè)節(jié)點(diǎn)下放置了 1 個(gè)子節(jié)點(diǎn)端辱,并將子節(jié)點(diǎn)的 zIndex
設(shè)為 1
。
?? 子節(jié)點(diǎn)的排序信息:
可以看到虽画,僅僅將節(jié)點(diǎn)的 zIndex
屬性設(shè)為 1
舞蔽,其 _localZOrder
就高達(dá) 65538
。
?? 大概的計(jì)算過(guò)程如下(極為抽象的偽代碼):
1. zIndex = 1 = 0b0000000000000001
2. siblingIndex = 0
3. arrivalOrder = 1 + (siblingIndex + 1)
4. arrivalOrder = 0b0000000000000010
5. _localZOrder = (zIndex << 16) | arrivalOrder
6. _localZOrder = 0b00000000000000010000000000000000 | 0b0000000000000010
7. _localZOrder = 0b00000000000000010000000000000010 = 65538
?? 繼續(xù)簡(jiǎn)化后的偽代碼:
_localZOrder = (zIndex << 16) | (siblingIndex + 2)
?? By the way
當(dāng)一個(gè)節(jié)點(diǎn)沒(méi)有父節(jié)點(diǎn)時(shí)狸捕,它的
arrivalOrder
永遠(yuǎn)是0
喷鸽。其實(shí)此時(shí)它是啥已經(jīng)不重要了,畢竟沒(méi)有父節(jié)點(diǎn)的節(jié)點(diǎn)本來(lái)就不可能會(huì)被排序灸拍。
場(chǎng)景三 (Scene 3)
在同 1 個(gè)節(jié)點(diǎn)下放置了 6 個(gè)子節(jié)點(diǎn)做祝,將所有子節(jié)點(diǎn)的 zIndex
都設(shè)為 0
砾省。
?? 各個(gè)子節(jié)點(diǎn)的排序信息:
場(chǎng)景四 (Scene 4)
在同 1 個(gè)節(jié)點(diǎn)下放置了 6 個(gè)子節(jié)點(diǎn),將這 6 個(gè)子節(jié)點(diǎn)的 zIndex
設(shè)為 0
到 5
混槐。
?? 各個(gè)子節(jié)點(diǎn)的排序信息:
可以看到编兄,zIndex
的值會(huì)直接體現(xiàn)在 _localZOrder
的「高 16 位」;每當(dāng) zIndex
增加 1
声登,_localZOrder
就會(huì)增加 65537
狠鸳。
所以說(shuō) siblingIndex 怎么可能打得過(guò) zIndex
!
場(chǎng)景五 (Scene 5)
在同 1 個(gè)節(jié)點(diǎn)下放置了 6 個(gè)子節(jié)點(diǎn)悯嗓,將這 6 個(gè)子節(jié)點(diǎn)的 zIndex
設(shè)為 0
到 5
件舵。
?? 修改第 6 個(gè)子節(jié)點(diǎn)的 siblingIndex
從 0
到 4
,其排序信息:
可以看到脯厨,此時(shí)無(wú)論我們?cè)趺葱薷牡?6 個(gè)子節(jié)點(diǎn)的 siblingIndex
铅祸,它都會(huì)自動(dòng)變回 5
(也就是同級(jí)節(jié)點(diǎn)中的最大值)。
因?yàn)檫@個(gè)子節(jié)點(diǎn)的 zIndex
在其同級(jí)節(jié)點(diǎn)之中有著絕對(duì)的優(yōu)勢(shì)合武。
不太對(duì)勁 (Something wrong)
?? 這里有一個(gè)看起來(lái)不太對(duì)勁的現(xiàn)象!
比如临梗,當(dāng)我們把 siblingIndex
從 5
修改為 0
時(shí),_localZOrder
也相應(yīng)從 327687
變成 327682
稼跳;但是當(dāng) siblingIndex
自動(dòng)變回 5
時(shí)盟庞,_localZOrder
也還是 327682
,并沒(méi)有變回 327687
汤善。
?? 為什么會(huì)這樣什猖?
原因其實(shí)很簡(jiǎn)單:
當(dāng)我們修改節(jié)點(diǎn)的 siblingIndex 時(shí)會(huì)觸發(fā)排序,排序過(guò)程中會(huì)「根據(jù)節(jié)點(diǎn)當(dāng)前時(shí)刻的 siblingIndex 和 zIndex
生成新的 _localZOrder
」萎津;
最后在父節(jié)點(diǎn)的 sortAllChildren
函數(shù)中會(huì)根據(jù)子節(jié)點(diǎn)的 _localZOrder
來(lái)對(duì) _children
數(shù)組進(jìn)行排序卸伞,此時(shí)「子節(jié)點(diǎn)的 siblingIndex 也會(huì)被動(dòng)更新」抹镊,「但是 _localZOrder
卻沒(méi)有重新生成」锉屈。
但是,由于 zIndex
存在「絕對(duì)優(yōu)勢(shì)」垮耳,這種“奇怪的現(xiàn)象”其實(shí)并不會(huì)影響到節(jié)點(diǎn)的正常排序~
總結(jié) (Summary)
分析完源碼后颈渊,我們來(lái)總結(jié)一下。
在代碼中修改節(jié)點(diǎn)順序的方法主要有兩種:
- 修改節(jié)點(diǎn)的
zIndex
屬性 - 通過(guò)
setSiblingIndex
函數(shù)設(shè)置
無(wú)論使用以上哪種方法终佛,最終都會(huì)「通過(guò) zIndex
和 siblingIndex 的組合作為依據(jù)來(lái)進(jìn)行排序」俊嗽。
在多數(shù)情況下,「修改節(jié)點(diǎn)的 zIndex
屬性會(huì)使其 setSiblingIndex
函數(shù)失效」铃彰。
這無(wú)形中增加了編碼時(shí)的心智負(fù)擔(dān)绍豁,也增加了問(wèn)題排查的難度。
引擎內(nèi)的用法 (Usage in engine)
出于好奇牙捉,我在引擎源碼中搜了搜竹揍,想看看引擎內(nèi)部有沒(méi)有使用到 zIndex
屬性敬飒。
結(jié)果是:只有幾處與「調(diào)試」相關(guān)的地方使用到了節(jié)點(diǎn)的 zIndex
屬性。
例如:預(yù)覽模式下芬位,左下角的 Profiler 節(jié)點(diǎn)无拗。
以及碰撞組件的調(diào)試框等等,這里就不在贅述了昧碉。
建議 (Suggestion)
所以英染,為了避免一些不必要的 BUG 和邏輯沖突。
我的建議是:
「少用甚至不用 zIndex被饿,而優(yōu)先使用 siblingIndex 相關(guān)函數(shù)四康。」
?? 聽(tīng)皮皮一句勸狭握,zIndex 的水太深箭养,你把握不住哥牍!
傳送門
更多分享
《Cocos Creator 性能優(yōu)化:DrawCall》
《在 Cocos Creator 里畫個(gè)炫酷的雷達(dá)圖》
《在 Cocos Creator 中優(yōu)雅且高效地管理彈窗》
《Cocos Creator 編輯器擴(kuò)展:Quick Finder》
《Cocos Creator 源碼解讀:引擎啟動(dòng)與主循環(huán)》
公眾號(hào)
菜鳥(niǎo)小棧
?? 我是陳皮皮毕泌,一個(gè)還在不斷學(xué)習(xí)的游戲開(kāi)發(fā)者,一個(gè)熱愛(ài)分享的 Cocos Star Writer嗅辣。
?? 這是我的個(gè)人公眾號(hào)撼泛,專注但不僅限于游戲開(kāi)發(fā)和前端技術(shù)分享。
?? 每一篇原創(chuàng)都非常用心澡谭,你的關(guān)注就是我原創(chuàng)的動(dòng)力愿题!
Input and output.