遊戲轉場時如何保留節點信息
引擎同時只會運行一個場景,當切換場景時,默認會將場景內所有節點和其他實例銷燬(本句來自Cocos Creator文檔)。
在這一節教程中,我們將討論下如何在場景切換時保留下必要的節點信息。 其實Cocos Creator文檔已經給我們提供了三種方法:
- 使用常駐節點
- 使用全局變量
- 使用模塊訪問
筆者在這一節中會再加一個:使用本地存儲。現在我們通過實例來進行演示。
Cocos Creator版本:2.2.2
後臺回覆"保留節點信息",獲取該項目完整文件:
使用常駐節點
我們知道在切換場景後,背景音樂會從頭開始播放。那如果要讓音樂繼續播放的話,我們就可以利用常駐節點來實現。在這一小點中筆者將通過一個背景音樂播放例子來演示如何使用常駐節點。
首先筆者在資源管理器中創建了兩個Scene:
- 在常駐節點場景中我們實現相關邏輯。
- 跳轉到測試結果場景後,我們再次跳轉回常駐節點,檢查音樂是否停下。
常駐節點場景內容:
- Bg Music是一個空節點,上面掛有Music.js腳本。注意一定要放在Canvas節點外。如果放在Canvas節點裏面,那麼從其他場景跳回來時,會重新生成一個Bg Music,而之前的Bg Music又沒有消失,所以會導致有多個背景音樂同時在播放的情況。
- New Button就是一個按鈕節點,用於場景切換。
Music.js內容如下:
// Music.js
cc.Class({
extends: cc.Component,
properties: {
bgAudio: {
default: null,
type: cc.AudioClip
}
},
// LIFE-CYCLE CALLBACKS:
onLoad () {
cc.game.addPersistRootNode(this.node); // 將該節點添加爲常駐節點
cc.audioEngine.playEffect(this.bgAudio); // 播放背景音樂
},
});
這裏最重要的代碼就是 cc.game.addPersistRootNode(this.node); 這一行代碼可以讓當前腳本所在節點變爲常駐節點,也就是說場景切換時,該節點不會被銷燬,那麼背景音樂自然也就會一直播放了。
再創建一個Button.js,掛到New Button節點上,內容如下:
// Button.js
cc.Class({
extends: cc.Component,
changeScene () {
cc.director.loadScene('測試結果'); // 切換場景
}
});
changeScene就是按鈕的點擊事件函數。注意不能在常駐節點中編寫這類函數,否則按鈕會不起作用。
測試結果場景內容:
非常簡單,就一個Label和按鈕節點,按鈕用於跳回常駐節點場景。Canvas節點上掛有Test.js腳本,內容如下:
// Test.js
cc.Class({
extends: cc.Component,
properties: {
},
persisitentNodeScene () {
cc.director.loadScene('常駐節點'); // 回到常駐節點場景
}
});
現在回到常駐節點場景,然後運行下,就會發現背景音樂是繼續播放的。
注:用於演示的背景音樂素材是從愛給網上下載的。
使用全局變量
我們通過在不同場景間傳遞一個字符串來演示下如何使用全局變量來保存節點信息。
首先創建一個新的場景,命名爲全局變量:
全局變量場景內容如下:
- New Label節點上的文本內容就是我們要在場景間傳遞的信息。
- New Button節點用於跳轉到測試結果場景。
接着創建兩個腳本文件:Global.js和NewScript.js,內容如下:
// Global.js
window.Global = {
labelStr: null
}
// NewScript.js
cc.Class({
extends: cc.Component,
properties: {
label: cc.Label,
},
// LIFE-CYCLE CALLBACKS:
onLoad () {
Global.labelStr = this.label.string;
},
changeScene () {
cc.director.loadScene('測試結果'); // 切換場景
}
});
很簡單,就是先在Global.js中創建一個全局變量,然後在NewScript.js中將文本內容保存到該變量中。
測試場景內容如下:
我們現在往Test.js腳本中添加一些內容:
// Test.js
cc.Class({
extends: cc.Component,
properties: {
label: cc.Label
},
onLoad () {
if (Global.labelStr) { // 增加代碼
this.label.string = Global.labelStr;
}
},
persisitentNodeScene () {
cc.director.loadScene('常駐節點'); // 回到常駐節點場景
}
});
如果Global全局變量的labelStr鍵有值的話,那我們就將測試結果場景中的文本標籤設爲labelStr的值。
現在回到全局變量場景,運行然後跳轉到測試場景,就會發現文本內容被傳過來了:
官方還給了通過模塊訪問的例子,大家可以去看下,筆者這裏就不再用實例進行演示。
使用本地存儲
其實用本地存儲來保存信息跟用全局變量來保存的道理是類似的。不過前者的主要作用不是在轉場時保存節點信息,而是用於實現存檔功能。如果你遊戲的某些數據不僅需要在轉場時進行保存,而且在下次啓動時還需要再次讀取。那麼筆者建議使用本地存儲而不是全局變量。
比方說《守護魚乾》這款微信小遊戲,遊戲需要記錄玩家採集的小草、石頭和金幣數,因爲這些材料可以拿來在商店中換取一些貓咪玩具。所以在跳轉到商店場景中時,我們需要保存在主場景中已經擁有的小草、石頭和金幣數。
不僅如此,玩家下次啓動時,這些材料的數量也要跟上次退出遊戲時的材料數一樣。
現在來看下如何使用。
首先創建一個本地存儲場景,內容如下:
- New Label節點的文本內容就是我們要保存到本地的信息。
- New Button節點用於跳轉到測試結果場景。
現在新建一個LocalStorage.js腳本,掛到Canvas節點上,內容如下:
// LocalStorage.js
cc.Class({
extends: cc.Component,
properties: {
label: cc.Label
},
// LIFE-CYCLE CALLBACKS:
onLoad () {
let name = this.label.string;
cc.sys.localStorage.setItem('name', name);
},
changeScene () {
cc.director.loadScene('測試結果'); // 切換場景
}
});
將文本內容直接存儲到本地中,鍵名爲name,值爲this.label.string。
測試場景內容如下:
我們在層級管理器中新增一個Label節點:
該節點將用於顯示之前保存到本地存儲中的內容。Test.js修改如下:
// Test.js
cc.Class({
extends: cc.Component,
properties: {
label: cc.Label,
label2: cc.Label
},
onLoad () {
if (Global.labelStr) {
this.label.string = Global.labelStr;
}
let name = cc.sys.localStorage.getItem('name'); // 增加代碼
this.label2.string = name;
},
persisitentNodeScene () {
cc.director.loadScene('常駐節點'); // 回到常駐節點場景
}
});
就是用本地存儲中讀取name鍵的值,然後顯示到label2上。
現在回到本地存儲場景,運行並跳轉到測試結果場景,就會發現傳值成功了:
注:必須先運行本地存儲場景,否則本地存儲中會沒有name鍵。
好,那本節教程就到這,希望大家有所收穫~