攒劲的节目
此贴可引导js项目升级至3.3,并保留js文件来降低升级风险,线上中大项目一两个bug带来的损失都是难以估量的
(对于小游戏开发者、新人及编程习惯不成形的开发者,仍然建议手动升级js文件为ts)
此贴的升级方式尽可能的保护项目原内容,减少工作量,能保留js内容也让大型项目升级3.3成为可能。
3.3优秀在哪里?
相信大多数人看了直播里对3.3的各项优点介绍,很明显,3D的提升是巨大的,引擎团队基本将所有的精力都放在了3D上面,尽管直播时没有低端机甚至中端机的性能表现,但未来可期。一个是ts直接转译c++的大饼,还有一个是引擎团队许诺近期版本都将对性能着重优化。
要不要升级?基于升级风险,做以下分析建议
if(你是独立开发者){
if(小游戏){
if(纯2D游戏){
无升级必要,3.3的2d性能并没有多大的提升,如果体量较小,可尝试升级,无所谓
}else{
//3D游戏
升吧,代码也不多,工作量可控
//2D游戏但有加入3D内容的想法
根据游戏内容和未来计划决定升级时间
}
}else{
//中大型
笔者就属于此情况,而且游戏当前是纯2D手游。
为什么要升级,是因为3D游戏优秀的代入感,独立开发者做手游,整个人都是绑在这个游戏上的,策划、开发、美工、运维、客服等等,而且笔者有长期运维游戏的打算,十年八年的,时刻出新的引擎是跟上节奏的保证
}
}else if(你是公司员工){
在升级过程中,基本上新的开发内容都是暂停的,这在大多数公司都是无法接受的,而且升级过程中的协作问题也很麻烦。公司的项目很多都是流水线作品,2D项目无升级的必要,而且引擎团队对2.x提供两年的持续维护。
对于3.3,更多的是考虑3D,这是主要衡量点。
就算项目是2.x的纯3D内容,也要有个衡量,api有大量的变动,不过2.x的大型3D游戏不太多,具体情况就请具体分析了。
}
step1
如果你当前低于2.4.6,先升级至2.4.6,因为3.3的升级导入插件对2.4.6兼容。2.x->2.4.6工作量并不多,这一步也可以当作试炼,如果这一步就遇到了问题且解决起来找不到头绪,就不要向下尝试了。
step2
将升级后的2.4.6项目备份,如果升级3.3失败,2.4.6的项目也可以拿来作为主力版本。
新建3.3项目,下载修改后的导入插件,修改版取消了插件对 js->ts 自动转换,插件的js转ts功能就像一坨shit,而且基本所有的js文件都不能顺利转换,而且作者会很贴心的提醒你:我转不了,但我把你以前的代码都注释了,你自己转吧 [微笑]
https://pan.baidu.com/s/138mYH55vXs6XyHAakhicsg
a2n4
插件准备就绪后关闭编辑器
step3
找到3.3项目的package.json文件,将type:3d 改为 type:module [重要!这将直接影响编辑器能否将js文件识别为模块]
step4
使用编辑器打开项目,设置插件为启用状态 (扩展-管理器-项目|全局)
使用插件导入2.4.6项目
此时编辑器的报错很多,不要着急,慢慢来
修改所有require为import,如果对import和export不太熟练,请恶补es6相关内容
导入js的语句需带有js文件格式,而ts不用,官方对模块的说明中有提及
import * as TD_Match_Scripts from "../../UISubLayer/TD_Match_Scripts";
import * as GameScripts from "../../UILayer/UI_PVPTDScripts.js"
js文件ccclass修改为如下形式
举例
2.x写法
cc.Class({
extends: cc.Component,properties: { nameLabel:cc.Label, timeLabel:cc.Label, countLabel:cc.Label, mainSP:cc.Sprite, itemID:null, }, initCell:function (itemID,timeText,CountText) { let self = this; self.itemID = itemID; //巴拉巴拉 }, itemClick:function(){}, onBtnDetail:function(){ var self = this; cc.ll.mainGameView.showInfo(cc.ll.gameData.getItemHelp(cc.ll.gameData.getItemTypeID(self.itemID))) },
});
3.x写法
import * as cc from “cc”;
const {
ccclass,
property
} = cc._decorator;
@ccclass
export default class extends cc.Component {@property(cc.Label) nameLabel = null; @property(cc.Label) timeLabel = null; @property(cc.Label) countLabel = null; @property(cc.Sprite) mainSP = null; itemID = null; initCell(itemID, timeText, CountText) { let self = this; self.itemID = itemID; //巴拉巴拉 } itemClick() { } onBtnDetail() { var self = this; cc.ll.mainGameView.showInfo(cc.ll.gameData.getItemHelp(cc.ll.gameData.getItemTypeID(self.itemID))) }
}
在此附上主要改动代码,供复制粘贴使用
import * as cc from “cc”; //此语句大幅减少代码修改量,四处的cc.,那无处不在的青春
const {ccclass,property} = cc._decorator;
@ccclass
export default class test extends cc.Component {
//将ccclass里的内容复制在此,props做修改,方法全部替换即可,多写几次就会很快了
}
常用组件声明
@property(cc.Label)
@property(cc.Button)
@property(cc.ScrollView)
@property(cc.Prefab)
@property(cc.Node)
@property(cc.SpriteAtlas)
@property(cc.Sprite)
@property(cc.Font)
@property(cc.EditBox)
@property(List)
@property(cc.RichText)
@property(cc.SpriteFrame)
@property(cc.ProgressBar)
@property(cc.Toggle)
@property(cc.Slider)
在修改完一个以后,在编辑器添加组件,在自定义组件出现了你的ccclass才算成功,此时打开绑定了脚本组件的prefab | node,查看之前在2.x的绑定是否还在,如下图
(赞一下写这一块的引擎组成员,变量绑定不会丢失,这也是升级的关键所在)
至此js文件模块的支持就完成了。
step5
effect的升级
直接拿我升级后的effect为大家做对比演示
2.x
//流光shader
CCEffect %{
techniques:
- passes:
- vert: vs
frag: fs
blendState:
targets:
- blend: true
rasterizerState:
cullMode: none
properties:
texture: { value: white }
u_fluxayTexture: { value: white }
u_fluxaySpeed: { value: 1 }
u_startPos: { value: -0.6 }
u_UVoffset: { value: [1,0,0,1] }
u_rotated: { value: 0 }
u_time: { value: 0 }
}%CCProgram vs { #include <cc-global> precision highp float; in vec3 a_position; in vec2 a_uv0; out vec2 uv0; void main () { gl_Position = cc_matViewProj * vec4(a_position, 1); uv0 = a_uv0; } }
CCProgram fs %{
precision highp float;
in vec2 uv0;
uniform sampler2D texture;
uniform ARGS {
vec4 u_UVoffset;
float u_startPos; //流动的时间
float u_rotated;
float u_time;
float u_fluxaySpeed;
sampler2D u_fluxayTexture; //流光图纹理
}
void main()
{
vec2 UVnormalize;
UVnormalize.x = (uv0.x-u_UVoffset.x)/(u_UVoffset.z-u_UVoffset.x);
UVnormalize.y = (uv0.y-u_UVoffset.y)/(u_UVoffset.w-u_UVoffset.y);
if(u_rotated > 0.5)
{
float temp = UVnormalize.x;
UVnormalize.x = UVnormalize.y;
UVnormalize.y = 1.0 - temp;
}vec4 src_color = texture2D(texture, uv0).rgba; //调整第二张图的UV,调整其x使其产生流动效果 vec2 flow_uv = vec2(UVnormalize.x,UVnormalize.y); flow_uv.x -= (u_time*u_fluxaySpeed)+u_startPos; vec4 src_color1 = texture2D(u_fluxayTexture, flow_uv).rgba; //根据底图是否有颜色来判断是否显示流光 if(src_color.a >= 1.0) { gl_FragColor = src_color+src_color1; } else { gl_FragColor = src_color; } }
}%
3.3
//流光shader
CCEffect %{
techniques:
- passes:
- vert: unlit-vs
frag: unlit-fs:frag
blendState:
targets:
- blend: true
rasterizerState:
cullMode: none
properties:
u_fluxayTexture: { value: white }
u_fluxaySpeed: { value: 1 }
u_startPos: { value: -0.6 }
u_UVofunlit_fset: { value: [1,0,0,1] }
u_rotated: { value: 0 }
u_time: { value: 0 }
}%CCProgram unlit-vs { #include <cc-global> precision highp float; in vec3 a_position; in vec2 a_texCoord; out vec2 uv0; void main () { gl_Position = cc_matViewProj * vec4(a_position, 1); uv0 = a_texCoord; } }
CCProgram unlit-fs %{
precision highp float;
#include
in vec2 uv0;#pragma builtin(local) layout(set = 2, binding = 10) uniform sampler2D cc_spriteTexture; uniform sampler2D u_fluxayTexture; //流光图纹理 uniform ARGS { vec4 u_UVofunlit_fset; float u_startPos; //流动的时间 float u_rotated; float u_time; float u_fluxaySpeed; }; vec4 frag() { vec2 UVnormalize; UVnormalize.x = (uv0.x-u_UVofunlit_fset.x)/(u_UVofunlit_fset.z-u_UVofunlit_fset.x); UVnormalize.y = (uv0.y-u_UVofunlit_fset.y)/(u_UVofunlit_fset.w-u_UVofunlit_fset.y); if(u_rotated > 0.5) { float temp = UVnormalize.x; UVnormalize.x = UVnormalize.y; UVnormalize.y = 1.0 - temp; } vec4 src_color = texture(cc_spriteTexture, uv0).rgba; //调整第二张图的UV,调整其x使其产生流动效果 vec2 flow_uv = vec2(UVnormalize.x,UVnormalize.y); flow_uv.x -= (u_time*u_fluxaySpeed)+u_startPos; vec4 src_color1 = texture(u_fluxayTexture, flow_uv).rgba; //根据底图是否有颜色来判断是否显示流光 if(src_color.a >= 1.0) { return (src_color+src_color1); } else { return (src_color); } }
}%
Fluxay.effect.zip (1.1 KB)
可以对比寻找改变,圈几个重点吧
1.a_texCoord 2.#include <output> 3.#pragma builtin(local) layout(set = 2, binding = 10) uniform sampler2D cc_spriteTexture; 4.return (src_color);
至于接口的改变,就需要大家一点点的修改了,务必要小心。
踩坑指南
需要注意的是3.3的z轴,详情可查看api文档
1.setposition(v2)在3.3是会导致NODE的_pos为NAN,也就是不生效
2…position返回的是只读v3
个人辅助工具,可将setPosition()统一替换为setPositionEx,减少工作量
cc.Node.prototype.setPositionEx = function () {
let self = this;
if (arguments.length == 1) {
let v = arguments[0];
if (v instanceof cc.Vec2) {
//v2类型
self.setPosition(v.x, v.y, 0)
}
if (v instanceof cc.Vec3) {
//v3类型
if (isNaN(v.z)) v.z = 0;
self.setPosition(v)
}
} else if (arguments.length == 2) {
self.setPosition(arguments[0], arguments[1])
} else if (arguments.length == 3) {
self.setPosition(arguments[0], arguments[1], arguments[2])
}
}
3.setScale(1) 是错误的写法
个人辅助工具
cc.Node.prototype.setScaleEx = function () {
if (arguments.length == 1) {
this.setScale(arguments[0], arguments[0])
} else if (arguments.length == 2) {
this.setScale(arguments[0], arguments[1])
} else if (arguments.length == 3) {
this.setScale(arguments[0], arguments[1], arguments[2])
}
}
4
aa = cc.v2(1,1)
bb = cc.v2(2,2)
let cc = aa.add(bb) 并不会返回新的v2,而是aa变为 (3,3),即addself,加减乘除都是如此,请格外注意少踩坑,3.3正确写法为 let cc = aa.clone().add(bb);
5.jumpto fadeto 等一些action都废弃了
6.addChild的修改,见文档,另外子child被add后,其layer并不会随父节点修改,如果相机视野不对应其layer,会导致看不到child
减少工作量辅助,对应2.x addchild,同时解决layer不随变问题
cc.Node.prototype.addChildEx = function (child, zIndex, name) {
if (typeof zIndex != undefined && zIndex) {
child.zIndex = zIndex;
}
if (typeof name != undefined && name) {
child.name = name;
}
child.layer = this.layer;
this.addChild(child);
}
7.zIndex取消,排序有 UITransform和 * setSiblingIndex
减少工作量辅助
Object.defineProperty(cc.Node.prototype, "zIndex", {
get: function() {
let t = this.getComponent(UITransform)
return t ? t.priority : 0
},
set: function(priority) {
let t = this.getComponent(UITransform)
if(!t) {
t = this.addComponent(UITransform)
}
t.priority = priority
},
enumerable: true,
configurable: true,
})
8.camera的修改,需额外注意Z轴和far属性,screenToWorld传参也需传入v3
9.tween的坑挺多的
持续增加中…
下面的帖子有3.x protobuf,crypto-js
因笔者项目代码量巨多,一个个踩坑导致升级的持续时间较长,且在升级的过程中,线上的游戏也需一些重要的更新,近期没有持续升级,升级中的一些操作可能没想起来,将持续添加。
ps:线上游戏的更新合并到3.3又是痛苦的过程