修改游戏对象
阅读本文大概需要 15 分钟。
上一章节介绍了口袋方舟中的游戏对象,本章节我们就来学习一下如何控制、修改它们吧!
1. 优先加载与动态下载
在口袋方舟编辑器中,资源库中所有对象全部存储在云端(也就是服务器上)。只有当我们使用它的时候编辑器才会下载它到本地,这样不但节约了开发者打包项目的时间,而且减少了游戏包体大小。
因为这个设计,所有动态生成的资源(摆放在场景中的不需要),全部都会先下载然后再生成( AsyncSpawn 函数),下载操作是编辑器自动进行的,因为下载需要一定的时间,所以有些资源会在第一次使用的时延后一点时间才生成出来。
如果游戏中存在一些在玩家刚刚进入游戏就马上要生成、不能接受第一次延迟出现的对象,比如玩家手中的道具、玩家释放的技能特效等,我们就可以将它们放在 优先加载列表中,在这个列表中的游戏对象会在打开游戏过程中进行下载,且必须要等这些资源下载完毕后,才会进入游戏。所以会略微减慢游戏启动速度。
所以优先加载中的资源太多会使游戏启动变慢,增加进入游戏的时长,对于什么资源要放进去开发者需要仔细斟酌。
关于动态加载资源详情可以查阅产品手册:使用与动态加载资源 | 产品手册 (ark.online)
关于优先加载
优先加载中的资源太多会显著加大游戏进入时长,对于什么资源要放进去开发者需要仔细斟酌。
1.1 使用优先加载
使用优先加载相当简单,只要将需要加载的资源拖动到对象管理器的 优先加载 下即可。如视频,这里我将正方体拖到优先加载中:
1.2 使用代码动态下载
我们可以在合适的时机使用函数AssetUtil.assetLoaded
对资源进行判断,检查资源是否已经被下载到本地,如果没有就使用函数 AssetUtil.asyncDownloadAsset
来对资源进行下载:
typescript
@Component
export default class AssetExample extends Script {
protected onStart(): void {
const cubeAssetId = "197386";
if (AssetUtil.assetLoaded(cubeAssetId)) {
console.log("正方体资源已经下载!");
} else {
console.log("正方体资源没有下载,现在启动下载...");
AssetUtil.asyncDownloadAsset(cubeAssetId).then(() => {
console.log("正方体资源已经下载!");
});
}
}
}
@Component
export default class AssetExample extends Script {
protected onStart(): void {
const cubeAssetId = "197386";
if (AssetUtil.assetLoaded(cubeAssetId)) {
console.log("正方体资源已经下载!");
} else {
console.log("正方体资源没有下载,现在启动下载...");
AssetUtil.asyncDownloadAsset(cubeAssetId).then(() => {
console.log("正方体资源已经下载!");
});
}
}
}
2. 脚本动态创建游戏对象
游戏开发中,我们常常需要通过脚本动态的进行游戏对象的创建,这里我们选择一个正方体(asset Id: 197386)进行动态创建。
创建并在场景当中挂载一个脚本,脚本代码如下。这里我们主要使用 GameObject.asyncSpawn
对资源进行了异步创建操作。
创建游戏对象,还可以使用同步创建函数 GameObject.spawn
函数,要注意的是使用同步函数编辑器将不会自动下载资源,需要手动调用下载函数或是将物体拖拽到优先加载中。
typescript
@Component
export default class GameStart extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
//这里创建一个双端的圆柱,所以我们需要在服务端创建,所有客户端也会自动同步创建
if (SystemUtil.isServer()) {
//创建圆柱模型
GameObject.asyncSpawn("197397");
}
}
}
@Component
export default class GameStart extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
//这里创建一个双端的圆柱,所以我们需要在服务端创建,所有客户端也会自动同步创建
if (SystemUtil.isServer()) {
//创建圆柱模型
GameObject.asyncSpawn("197397");
}
}
}
运行游戏,可以看到该物体被动态创建出来了。
Spawn 资源注意事项
双端预制体只能在服务端创建,客户端预制体只能在客户端创建。
普通资源在服务端创建后为双端物体,在客户端创建为单端物体。
关于游戏对象的网络类型会在后续章节介绍,这里只需要大概了解即可。客户端与服务端 | 教程 (ark.online)
除了模型,特效、声音、预制体等都可以使用该脚本方式动态创建出来。
3. 更改游戏对象属性
上文中我们在常见属性中讲到了游戏对象的变换属性,这个属性决定了游戏对象的位置、旋转、缩放。游戏开发中,我们经常需要修改这个属性用以实现各类游戏功能,举个例子,我们可以通过在每一帧调整小球的缩放、位置和旋转参数,来实现一个弹跳移动的小球。这种频繁的属性修改是游戏开发中常见且重要的操作之一。
3.1 将游戏对象转为指定类型
在上一章节中我们讲过,编辑器中所有的物体都继承自游戏对象基类(GameObject),使用 GameObject.spawn
函数创建出来的对象默认类型为 GameObject 类型,如果我们想要使用某些专属于某个类型对象的函数,就需要手动指定创建出来的游戏对象的类型了。
比如 Model
类型才可以设置碰撞属性、Trigger
类型才可以设置进入触发器事件。
在TypeScript中,as
关键字用于类型断言。它允许我们手动设置变量的数据类型,并防止编译器自行推断它。类型断言通常用于将任何类型视为特定类型,例如我们将生成出的游戏对象(圆柱体),转换为 Model 类型:
typescript
@Component
export default class Test extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
//这里创建一个双端的圆柱,所以我们需要在服务端创建,所有客户端也会自动同步创建
if (SystemUtil.isServer()) {
//创建圆柱模型
const cylinder = GameObject.spawn("197397") as Model;
//转换为模型后就可以设置模型的碰撞了
cylinder.setCollision(CollisionStatus.Off);
}
}
}
@Component
export default class Test extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
//这里创建一个双端的圆柱,所以我们需要在服务端创建,所有客户端也会自动同步创建
if (SystemUtil.isServer()) {
//创建圆柱模型
const cylinder = GameObject.spawn("197397") as Model;
//转换为模型后就可以设置模型的碰撞了
cylinder.setCollision(CollisionStatus.Off);
}
}
}
上文中只是演示了 as
的一种转换方式,我们通常声明一个新的变量,然后将转换后的游戏对象赋值给它:
typescript
@Component
export default class Test extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
//这里创建一个双端的圆柱,所以我们需要在服务端创建,所有客户端也会自动同步创建
if (SystemUtil.isServer()) {
//创建游戏对象
const gameObject = GameObject.spawn("197397");
//声明一个变量 将游戏对象转换为模型类型
const cylinder = gameObject as Model;
//转换为模型后就可以设置模型的碰撞了
cylinder.setCollision(CollisionStatus.Off);
}
}
}
@Component
export default class Test extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
//这里创建一个双端的圆柱,所以我们需要在服务端创建,所有客户端也会自动同步创建
if (SystemUtil.isServer()) {
//创建游戏对象
const gameObject = GameObject.spawn("197397");
//声明一个变量 将游戏对象转换为模型类型
const cylinder = gameObject as Model;
//转换为模型后就可以设置模型的碰撞了
cylinder.setCollision(CollisionStatus.Off);
}
}
}
3.2 使用代码修改对象变换
除了直接在对象管理器中修改以外,我们还可以使用代码或运动器来动态修改物体的变换。
位置(Position):变换属性中的位置确定了游戏对象在游戏世界中的空间坐标。
旋转(Rotation):变换属性中的旋转决定了游戏对象的朝向和角度。
缩放(Scale):变换属性中的缩放用于调整游戏对象的大小。
typescript
@Component
export default class TransformExp extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
//这里创建一个双端的圆柱,所以我们需要在服务端创建,所有客户端也会自动同步创建
if (SystemUtil.isServer()) {
//创建圆柱对象
const object = await GameObject.asyncSpawn("197397");
//设置对象位置到 Vector(500,500,100)的位置
object.worldTransform.position = new Vector(500, 500, 100);
//设置对象缩放为 Vector(10,10,10)
object.worldTransform.scale = new Vector(10, 10, 10);
//设置对象旋转为 Rotation(10,2,2)
object.worldTransform.rotation = new Rotation(10, 2, 2);
}
}
}
@Component
export default class TransformExp extends Script {
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
//这里创建一个双端的圆柱,所以我们需要在服务端创建,所有客户端也会自动同步创建
if (SystemUtil.isServer()) {
//创建圆柱对象
const object = await GameObject.asyncSpawn("197397");
//设置对象位置到 Vector(500,500,100)的位置
object.worldTransform.position = new Vector(500, 500, 100);
//设置对象缩放为 Vector(10,10,10)
object.worldTransform.scale = new Vector(10, 10, 10);
//设置对象旋转为 Rotation(10,2,2)
object.worldTransform.rotation = new Rotation(10, 2, 2);
}
}
}
3.3 使用运动器修改对象变换
实现简单的运动如直线运动、简谐运动、圆周运动等,我们可以无需代码直接使用编辑器封装好的 运动功能对象:运动器 来实现。
在资源库中拖一个正方体到场景上,然后在运动功能对象中拖一个 运动器 到正方体上使其成为正方体子物体:
接下来选中运动器,在它的属性面板上就可以设置各种常见运动方式的参数了。设置参数后在对象管理器中选中运动器,可以在主视口中看到预览线,更方便大家设计关卡:
设置好之后勾选启用,接下来运行游戏就可以看到效果了!
关于运动器详细教程可以查阅:运动器教程
4. 更改游戏对象颜色及透明度
选中要修改颜色的对象,找到材质插槽:
透明度滑动即可调节,也可以手动输入,不透明度为0时为完全透明,为1时为完全不透明:
更改颜色,先点击材质插槽颜色里面的色块,然后点击取色器即可选择想要的颜色。
5. 更改游戏对象材质
物体的显示是基于材质的,而我们可以对材质进行颜色或者其他设置的修改,例如我们可以创建一个红色的材质,然后将这个材质应用于椅子、窗户等物体,那么我们就会拥有一个同样红色的椅子和一个同样红色的窗户了。
那么我们来创建一个材质,选择需要更改材质的物体,在属性中单击该按钮,如图:
这时候会在重新弹出一个材质编辑窗口,我们在这里选择 "基础属性" ,然后就可以通过 "漫反射颜色" 选项修改材质的颜色,修改好颜色后,点击 "确认" ,最后再进行保存。
保存后,回到主界面,就可以看到场景上的方块颜色发生改变了,它被运用了我们新建的材质,如图:
如果其他物体也想改成这种颜色,那么直接使用我们这个材质就可以了,如图: