最近用Laya2.0.2制作了3D【瘋狂怪獸車】的跑酷 + 射擊彈幕類微信小游戲項(xiàng)目审胸,在做的過程中躺了不少次坑卓缰,最終還是躺過了蛛株,在這里分享一下我的一些躺坑經(jīng)驗(yàn)和解決方案抓半,同時(shí)也順便瘋狂打個(gè)廣告2333333扔字。
Laya客戶端
微信小游戲性能優(yōu)化
- 同屏物理組件個(gè)數(shù)超過10個(gè)性能會(huì)嚴(yán)重降低囊嘉,測(cè)試3-5個(gè)沒問題。如果是做飛行彈幕游戲類型的話革为,或許用距離 + 碰撞盒大小來判斷是否擊中扭粱,這種方案處理還比較理想;
- 相同音效同時(shí)播放超過5個(gè)性能會(huì)降低震檩,必須限制播放個(gè)數(shù)琢蛤;
- 粒子數(shù)量也要控制,同個(gè)粒子限制生成次數(shù)抛虏,間隔多久才能生成博其;
- 美術(shù)處理的汽車模型,為了能做好動(dòng)畫將模型分成了若干部件迂猴,導(dǎo)致每臺(tái)車的dc都有5個(gè)慕淡,同屏出現(xiàn)多臺(tái)汽車,DC會(huì)爆炸沸毁。最后我廢除了敵人汽車動(dòng)畫峰髓,并且偷偷用unity的MeshBaker合并了敵人汽車,將敵人汽車的DC降到只有1息尺;
- 美術(shù)提供的道路模型都是在unity里面用不同的物件擺出來的携兵,個(gè)體都很分散,而且不利于合并搂誉,合并解決有兩種方案:
一種是用Laya自帶的靜態(tài)合并方法Laya.StaticBatchManager.combine()徐紧,不過要將物體勾選static選項(xiàng)。另外一種是用unity插件MeshBaker來進(jìn)行合并。這兩種方法都可以達(dá)到合并的效果并级,個(gè)人覺得直接用unity插件合并更爽拂檩; - 根據(jù)實(shí)際需求減少模型的層次結(jié)構(gòu),這樣可以直接優(yōu)化Laya的繪制Sprite次數(shù)死遭,我最多放3層广恢,之前用Laya2.0的時(shí)候,Laya引擎多加了一層root呀潭,其實(shí)我也不知道為啥钉迷,但是Laya2.0.2減少了這一層,確實(shí)對(duì)性能會(huì)好點(diǎn)钠署;
- 模型面數(shù)的控制糠聪,還是按照手游那套,由于后面同屏物體比較多谐鼎,敵人汽車模型控制500-800三角面舰蟆,主角的面數(shù)盡量1500-2000左右;其實(shí)感覺在微信上狸棍,同屏面數(shù)10W估計(jì)都能跑得起身害,雖然沒測(cè)試過2333。
- 部分粒子效果最好能轉(zhuǎn)為序列幀動(dòng)畫來表現(xiàn)效果草戈,并且注意序列幀的位圖大兴臁;
- 子彈可以直接用面片和透貼來制作唐片,控制同屏數(shù)量20個(gè)左右丙猬,應(yīng)該都是沒問題的;
物理系統(tǒng)(后面優(yōu)化移除掉用物理檢測(cè)了费韭,只有主角車和boss車才有物理)
- 移除正在運(yùn)動(dòng)的物理會(huì)報(bào)錯(cuò)茧球,可以先暫停移除或者暴力判斷Laya物理為空的出錯(cuò)代碼(缺少截圖);
粒子制作
-
需要遵循Laya的粒子規(guī)則來制作粒子
-
注意Color over LifeTime的漸變色塊不要超過4個(gè)星持,否則會(huì)有問題
插件導(dǎo)出
可使用unity2018.3.8.0f1, Laya2.0.2導(dǎo)出插件
導(dǎo)出管理
考慮到模型會(huì)有很多抢埋,我將要導(dǎo)出的資源分了多個(gè)場(chǎng)景來管理,這樣的好處是可以減少導(dǎo)出時(shí)間并且能更好維護(hù)文件目錄钉汗。
例如瘋狂怪獸車中羹令,我將角色汽車模型分到一個(gè)場(chǎng)景,道路一個(gè)場(chǎng)景损痰,粒子場(chǎng)景,子彈效果場(chǎng)景酒来,此時(shí)場(chǎng)景有4個(gè)可以分別導(dǎo)出管理lh模型卢未,如下圖
導(dǎo)出參數(shù)如下,以汽車模型為例:
最終導(dǎo)出到Laya客戶端的效果:
LayaNative
突然收到要制作原生安卓包并對(duì)接渠道,頓時(shí)懵逼了的感覺辽社,畢竟安卓沒怎么寫過伟墙,但有挑戰(zhàn)才能有進(jìn)步,還是硬著頭皮上了滴铅。喵了一下Java的語(yǔ)法有點(diǎn)類似C#戳葵,突然心就安樂了。
音樂
- 原生只支持ogg和wav格式汉匙;
- 用Laya的SoundManager播放背景音樂會(huì)卡線程拱烁,需要等待3-4秒才能恢復(fù);
- PlayMusic() 后并馬上設(shè)置MusicMuted為停止噩翠,實(shí)測(cè)音樂不會(huì)停止播放戏自;
- 如果先設(shè)置MusicMuted再PlayMusic(),音樂不執(zhí)行播放伤锚;
原生和Laya2.0互相通訊
Laya的類必須要導(dǎo)出window靜態(tài)類擅笔,并且要暴露靜態(tài)方法給原生調(diào)用,如下JaveCallback.ts代碼屯援,必須要注意最后那個(gè)if語(yǔ)句猛们,如果不寫就會(huì)報(bào)undefine。
export default class JaveCallback {
public static CallbackTest() {
alert("Java 調(diào)用 Laya");
}
}
if (Laya.Browser.window) {
Laya.Browser.window.JaveCallback = JaveCallback;
}
仿效微信的onShow和onHide方法
游戲中有一個(gè)需求是當(dāng)app進(jìn)入后臺(tái)或前臺(tái)需要關(guān)閉或開啟音效狞洋,如果直接執(zhí)行回調(diào)onShow和onHide弯淘,是會(huì)報(bào)錯(cuò)的,因?yàn)榇藭r(shí)游戲還沒初始化完成徘铝,調(diào)用就會(huì)報(bào)undefine耳胎。
所以暫時(shí)想到了一個(gè)解決方案:Laya進(jìn)入游戲后先通知原生初始化,然后原生記錄初始化標(biāo)記后再執(zhí)行回調(diào)onShow和onHide函數(shù)惕它,這樣才能避免一開始就報(bào)錯(cuò)怕午。具體代碼如下:
Laya端的代碼
export default class JaveCallback {
private static readonly conchIOS: string = "Conch-ios";
private static readonly conchAndroid: string = "Conch-android";
private static os: string = "";
private static bridge: Laya.IPlatformClass = null;
public static onShow() {
alert("Java 調(diào)用 Laya onShow()");
}
public static onHide() {
alert("Java 調(diào)用 Laya onHide()");
}
//進(jìn)入游戲后,執(zhí)行init函數(shù)
public static init(){
if (Laya.Browser.window.conch) {
this.os = conchConfig.getOS();
if (this.os == JaveCallback.conchIOS) {
this.bridge = Laya.PlatformClass.createClass("JSBridge");
this.bridge.call("initGame:");
}
else if (this.os == JaveCallback.conchAndroid) {
this.bridge = Laya.PlatformClass.createClass("demo.JSBridge");
this.bridge.call("initGame");
}
}
}
}
if (Laya.Browser.window) {
Laya.Browser.window.JaveCallback = JaveCallback;
}
android studio端的代碼
先找到Laya的JSBridge代碼淹魄,增加一個(gè)Init屬性郁惜,并增加一個(gè)initGame方法給Laya調(diào)用
public class JSBridge {
public static Handler m_Handler = new Handler(Looper.getMainLooper());
public static Activity mMainActivity = null;
public static Boolean Init = false;
public static void initGame(){
Init = true;
}
//后面省略..........
//一堆代碼..........
//后面省略..........
//一堆代碼..........
}
找到Laya的MainActivity代碼,然后找到onPause和onResume方法.
在onPause方法除插入
if(JSBridge.Init == true) {
ConchJNI.RunJS("JaveCallback.onHide()");
}
在onResume方法除插入
if(JSBridge.Init == true){
ConchJNI.RunJS("JaveCallback.onShow()");
}
最終代碼如下:
protected void onPause()
{
super.onPause();
if(isLoad){
if(JSBridge.Init == true) {
ConchJNI.RunJS("JaveCallback.onHide()");
}
mPlugin.game_plugin_onPause();
}
}
protected void onResume()
{
super.onResume();
if(isLoad){
mPlugin.game_plugin_onResume();
if(JSBridge.Init == true){
ConchJNI.RunJS("JaveCallback.onShow()");
}
}
}
Laya2.0打安卓原生包
按文檔處理即可正常發(fā)包
Laya1.0打包安卓后gradle報(bào)錯(cuò)
需要修改Gradle Script里面的build.gradle甲锡,并將下面兩行代碼增加到里面
google()
jcenter()
buildscript {
repositories {
mavenLocal()
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
}
}
然后修改 compileSdkVersion 26 和 targetSdkVersion 26兆蕉,最后升級(jí)一下SDK即發(fā)布APK包
遺留問題
- 發(fā)熱問題
- 蘋果打包