1.创建img文件夹 将准备好的天空盒六张图片放入其中

2.制作与应用 CubeMap
右键事先建好的cubemaps文件夹 选择新建 CubeMap


3.将六张图片拖入到右侧 如图所示 CubeMap制作完成

4.点击scene 在右侧属性检查器中 skybox — 选中 Enabled 并将制作好的CubeMap 拖入到Envmap中


5. 点击Camera 在属性检查器中 将ClearFlags 选为SKYBOX
让软件开发维护变得更加便捷
1.创建img文件夹 将准备好的天空盒六张图片放入其中

2.制作与应用 CubeMap
右键事先建好的cubemaps文件夹 选择新建 CubeMap


3.将六张图片拖入到右侧 如图所示 CubeMap制作完成

4.点击scene 在右侧属性检查器中 skybox — 选中 Enabled 并将制作好的CubeMap 拖入到Envmap中


5. 点击Camera 在属性检查器中 将ClearFlags 选为SKYBOX
模型文件需要是fbx的格式,贴图文件放在和fbx文件同级的文件夹中,一起发过来。
比如:文件夹model里面有着一个model1.fbx和一个叫model1的文件夹,我们只需要将model拽到cocos cretor3D中的assets里新建的texure文件夹中即可
注意:在cocos creator 3D中的模型最好别用3dmax做,因为3dmax导出的fbx贴图有问题,用maya或者c4d都可以,如果已经用3dmax做完了,就让他们用别的3d软件转一下
如果对模型亮度有要求,最好是让做模型的人调整一下贴图材质,会比cocos creator 3D中打光的效果均匀(因为本人刚接触,关于这方面技术很菜)
贴图中的名称不能有全角和中文,否则拽到cocos3D里贴图贴不上
因为刚接触3D的时候蒙了一天,甚至给自己转的都恶心了,所以还是写一下吧
①、按住鼠标右键移动鼠标,是基于鼠标按住的点进行720°旋转
②、按住鼠标左键+键盘Alt键,移动鼠标,是对画布模型进行旋转
③、滑动鼠标滚轮控制画布放大缩小
④、按住鼠标右键,同时按住键盘的w/a/s/d,分别是平移视角向前/左/后/右
⑤、按住鼠标右键,同时按住键盘的w/a/s/d,再移动鼠标,会根据鼠标移动进行带旋转角度的位移(慎用,容易给自己转晕)
以上几条其实做完这个项目发现常用的就是①②③,这几个基本就够用了
cocos creator 3D学习(二)总是浮在屏幕最前面的操作按钮及其他
cocos creator 3D学习(三)一些常用的声明
cocos creator 3D学习(四)刚体
cocos creator 3D学习(五)射线—点击按钮
cocos creator 3D学习(六)光照+阴影

前面一篇文章,我们讲了【打砖块】游戏中的3D物体的场景布局、材质资源、物理刚体与碰撞组件,接下来本篇文章重点介绍“子弹的发射”与“摄像机移动”,有了这两部分我们的【打砖块】游戏就可以初步玩起来了。

子弹是由 3D 物体 Sphere 球体创建,并将节点改名为 bullet,看下图:

在层级管理器中将 bullet 节点拖动到资源管理器中,将它创建成一个 Prefab 预制体。同时在 bullet 子弹节点上挂载球体碰撞组件(cc.SphereColliderComponent)和刚体组件 (cc.RigidBodyComponent),如下图所示:

有了 bullet 预制体,我们就可以用代码去实例化它,并将他发射出去,创建一个 shoot 的TypeScript 脚本并将它挂载到 Camera 摄像机节点上:
将shoot组件的子弹预制体拖动过去,子弹的移动速度设置为 50,我们通过点击屏幕来进行发射,下面是具体的代码:
import { _decorator, Component, Node, CCObject, Prefab, instantiate, RigidBodyComponent, Vec3 } from "cc";
const { ccclass, property } = _decorator;
@ccclass("shoot")
export class shoot extends Component {
@property(Prefab)
bullet: Prefab;
@property(cc.Float)
speed = 0;
start () {
//注册全局触摸点击事件
cc.systemEvent.on(Node.EventType.TOUCH_END, () => {
this.shoot();
});
}
shoot() {
//实例化 bullet 预制体
let node = instantiate(this.bullet);
node.parent = this.node.parent;
node.position = this.node.position;
//为刚体施加冲量
let bullet:RigidBodyComponent = node.getComponent(RigidBodyComponent);
bullet.applyImpulse(new Vec3(0, 2.29, -1 * this.speed));
}
这里需要注意两点:
cc.systemEvent进行注册的;cp /Applications/CocosCreator3D.app/Contents/Resources/resources/3d/engine/bin/.declarations/cc.d.ts ./
预制体的实例化使用instantiate 与我们在Creator 2D中使用的API完全相同,就不在赘述。这时我们就可以运行预览,通过点击鼠标或触摸屏幕发射子弹了。
在3D游戏中,通常的做法是使用WSAD四个键进行上下左右的移动,其核心是控制摄像机节点的位置。在我们这个游戏中为了简化游戏操作,我们只控制摄像的 x 和 y 方向的移动:

创建一个 movement 的脚本用于控制摄像机的移动,下面是组件的设置:
下面重点分析使用键盘控制摄像机移动的相关代码:
//使用 cc.systemEvent.on 注册全局键盘事件
start() {
cc.systemEvent.on(Node.EventType.KEY_DOWN, this.onKeyDown, this);
cc.systemEvent.on(Node.EventType.KEY_UP, this.onKeyUp, this);
...
}
在按钮下键盘事件 onKeyDown 中标记移动的方向:
onKeyDown(event) {
cc.log(event);
let rotation = this.node.eulerAngles;
let position = this.node.getPosition();
switch(event.keyCode) {
case cc.macro.KEY.w:
this.offset.y = 1;
break;
case cc.macro.KEY.s:
this.offset.y = -1;
break;
case cc.macro.KEY.a:
this.offset.x = -1;
break;
case cc.macro.KEY.d:
this.offset.x = 1;
break;
}
}
当按键松开时,将 offset 变量归 0:
onKeyUp() {
this.offset.x = 0;
this.offset.y = 0;
this.offset.z = 0;
}
重点是在组件的每帧事件 update 中真正控制摄像机节点的移动:
update (deltaTime: number) {
//计算要移动的目标位置
Vec3.add(this.point, this.node.position, this.offset);
//插值计算
Vec3.lerp(this.point, this.node.position, this.point, deltaTime * this.speed);
//移动节点
this.node.setPosition(this.point);
}
为了平滑移动,Shawn这里参考了官方Demo案例中的做法,使用 Vec3.lerp 对当前坐标到要移动的坐标进行插值计算。
1效果预览
前两天有伙伴在 QQ 上询问,如何在 Creator 3D 中切换模型贴图。Shawn 之前也没尝试过,不过根据之前 Cocos Creator 的经验以及这几天对 Creator 3D 的学习,简单尝试了一下,方法可行,在此将它分享给大家。2模型材质资源在 Creator 3D 中,一个 3D 物体主要由 ModelComponent 组件渲染,其中包含两大部分: Mesh 和 Material,而模型的纹理就在材质属性上进行控制。在 Creator3D 编辑中,我们可通过图形化拖动的方式修改材质贴图,如下图:
上图中,先使用引擎内置的无光照的 Effect,它的选项看起来没那么多,可以减少畏惧感,我们将一 ground 的图片拖动到 test.mtl 材质资源上。然后将 test 材质拖动到 Cube 物体的 ModelComponent 组件上:
设置好后你就可以看到 Cube 上的像石头一样的材质表现了。3使用脚本修改材质纹理我这里创建了一个 test.ts 的脚本文件,用于修改材质上的纹理资源,先看下组件属性:
注意 3D 物体上的贴图不是Cocos Creator中的 SpriteFrame,而是 Texture2D 类型,下面是 Texture1、Texture2属性定义:
@ccclass("test")export class test extends Component { @property({type: Texture2D }) texture1: Texture2D = null; @property(Texture2D) texture2: Texture2D = null; }
复杂数据类型需要给 @property 输入一个 type 参数,同时下面一行,需要给变量设置为null,不然在属性面板上不显示。纹理资源已经设置好了,如何通过代码访问或修改材质呢?经过Shawn的一阵摸索,发现还是非常简单的,使用材质对像的getProperty、setProperty就可以搞定:
swithcTextue() { //获取ModelComponent组件 let modelComponent = this.getComponent(ModelComponent); //获取0号材质 let material = modelComponent.materials[0]; //获取纹理 let texture = material.getProperty('mainTexture'); //设置纹理 material.setProperty('mainTexture', texture === this.texture1 ? this.texture2 : this.texture1);}
material.setProperty的参数是Key和Value,分别对应材质面板上的Key与纹理对象,看下图:
用material.setProperty也是同理,如果你是使用的标准Effect,也是用同样的方法:
只需要将材质属性中的属性名,首字母小写就可以了!3小结本篇介绍了使用 material.setProperty API 修改材质纹理。最后我们思考一个问题,如果有两个 3D 物理,使用了同一个材质资源,在编辑器中修改材质贴图你会发现两个物理都会同时发生变化,看下图:
如果我们是用代码,在运行时修改了任意一个 3D 物体上的材质属性,另一个 3D 物体的材质会变吗?Shawn做了一下测试,但并没有变,看下面的效果:
之前 Shawn 在想,如果运行时也会变的话,比如生成一桌子的麻将牌,岂不是要为每一纹理创建一个材质资源,现在好像担心多了!