feat:上传mcguide-开发指南部份
819
mcguide/20-玩法开发/15-自定义游戏内容/3-自定义生物/01-自定义基础生物.md
Normal file
@@ -0,0 +1,819 @@
|
||||
---
|
||||
front:
|
||||
hard: 入门
|
||||
time: 分钟
|
||||
---
|
||||
|
||||
# 自定义生物
|
||||
|
||||
## 1.概述
|
||||
|
||||
自定义生物涉及材质(material)、贴图(texture)、模型(model)、几何建模(geometry)、动画(animation)、动画控制器(animation controller)和渲染控制器(render controller)等概念,在阅读本文档时希望你对这些专业名词有所了解。
|
||||
|
||||
开发者可以通过在addon中配置json来添加自定义生物,添加的自定义生物支持“MOD SDK文档”中与生物/实体相关的所有事件与接口。
|
||||
|
||||
下面将通过定义一个松鼠(squirrel)来展现如何定义一个生物。(详见示例[CustomEntityMod](../../13-模组SDK编程/60-Demo示例.md#CustomEntityMod))
|
||||
|
||||
<img src="./picture/customentity/squirrel_entity.png" alt="zombie" style="zoom:100%;" />
|
||||
|
||||
自定义的松鼠包括以下json文件:
|
||||
|
||||
* behavior_pack/entities/squirrel.json 服务端实体定义
|
||||
* resource_pack/entity/squirrel.entity.json 客户端实体定义
|
||||
* resource_pack/animations/squirrel.animation.json 动画定义
|
||||
* resource_pack/animation_controllers/squirrel.animation_controllers.json 动画控制器定义
|
||||
* resource_pack/models/entity/squirrel.geo.json 模型定义
|
||||
* resource_pack/render_controllers/squirrel.render_controllers.json 渲染控制器定义
|
||||
* resource_pack/textures/entity/squirrel/red.png 贴图
|
||||
* resource_pack/textures/entity/squirrel/gray.png 贴图
|
||||
* resource_pack/materials/entity.material 材质
|
||||
|
||||
下图是上述文件之间的关系图:
|
||||
|
||||
<img src="./picture/customentity/squirrel.png" alt="zombie" style="zoom:100%;" />
|
||||
|
||||
|
||||
|
||||
## 2. 行为包实体定义
|
||||
|
||||
### 2.1 示例
|
||||
|
||||
在行为包behavior_pack/entities目录下增加squirrel.json
|
||||
|
||||
```json
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"minecraft:entity": {
|
||||
"description": {
|
||||
"identifier": "netease:squirrel", # 实体标识
|
||||
"is_summonable": true, # 是否可以使用命令召唤
|
||||
"is_spawnable": true, # 该实体可不可以使用创造模式界面的刷怪蛋生成
|
||||
"runtime_identifier": "minecraft:squirrel" # 基于此构建自定义的entity
|
||||
},
|
||||
"component_groups": {
|
||||
"minecraft:color_red": {
|
||||
"minecraft:type_family": {
|
||||
"family": [
|
||||
"red_squirrel",
|
||||
"squirrel"
|
||||
]
|
||||
},
|
||||
# 定义一个变量,该变量在render_controller中选择不同的贴图和材质
|
||||
"minecraft:variant": {
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"minecraft:color_gray": {
|
||||
"minecraft:type_family": {
|
||||
"family": [
|
||||
"gray_squirrel",
|
||||
"squirrel"
|
||||
]
|
||||
},
|
||||
"minecraft:variant": {
|
||||
"value": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
...
|
||||
},
|
||||
"events": {
|
||||
"minecraft:entity_spawned": {
|
||||
"sequence": [
|
||||
{
|
||||
"randomize": [
|
||||
{
|
||||
"weight": 1, # 权重
|
||||
"add": {
|
||||
"component_groups": [
|
||||
"minecraft:color_red"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"weight": 1, # 权重
|
||||
"add": {
|
||||
"component_groups": [
|
||||
"minecraft:color_gray"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
创建松鼠时有50%的概率生成红色松鼠,另外50%的概率生成灰色松鼠。
|
||||
|
||||
### 2.2 components
|
||||
|
||||
定义每一种实体独立的行为特性,如minecraft:identitier和minecraft:type_family等。
|
||||
|
||||
更多的组件介绍请请查阅微软文档(https://minecraft-zh.gamepedia.com/基岩版实体组件文档)
|
||||
|
||||
**注:在2.2以及之后的版本,我们对自定义生物的移动流量进行了优化,距离玩家较远的生物会出现瞬移的情况,如果感觉效果较差,可在components手动添加netease:ban_bandwidth_optimization:{}组件来主动关闭此优化**
|
||||
|
||||
|
||||
|
||||
### 2.3 component_groups
|
||||
|
||||
将多个components放在一个集合内,便于增加和删除多个components,比如实体的boby和adult两个不同的阶段,很多属性不同,那么就可以在合适的事件中增加或移除对应阶段的component group。
|
||||
|
||||
在本例子中,定义了红色松鼠(minecraft:color_red)与灰色松鼠(minecraft:color_gray)两个分组,并且在创建生物进行添加。
|
||||
|
||||
|
||||
|
||||
### 2.4 事件events
|
||||
|
||||
#### minecraft:entity_spawned
|
||||
|
||||
触发时机:当entity被放置在地图中时
|
||||
|
||||
#### minecraft:entity_transformed
|
||||
|
||||
触发时机:当entity转化为另外一个entity时
|
||||
|
||||
#### minecraft:entity_born
|
||||
|
||||
触发时机:当entity繁殖时
|
||||
|
||||
#### minecraft:on_prime
|
||||
|
||||
触发时机:当entity被点燃将要爆发时
|
||||
|
||||
|
||||
|
||||
## 3.自定义材质
|
||||
|
||||
### 3.1 示例
|
||||
|
||||
#### 3.1.1 原生材质
|
||||
|
||||
MC原生的材质定义都在"/data/resource_packs/vanilla/materials"下,生物的材质都在这个目录下的"entity.material"文件中。
|
||||
|
||||
材质可通过继承达到复用的效果,原生材质中,常被继承的基础生物材质entity定义如下:
|
||||
|
||||
```json
|
||||
"entity:entity_static": { # 继承材质entity_static的材质entity,entity_static的定义可在上述"entity.material"文件中找到
|
||||
"+defines": [ "USE_OVERLAY" ], # 渲染时添加USE_OVERLAY宏定义
|
||||
"msaaSupport": "Both" # 使用MSAA抗锯齿技术
|
||||
},
|
||||
```
|
||||
|
||||
#### 3.1.2 添加自定义材质
|
||||
|
||||
在资源包resource_pack/materials目录下创建json文件:entity.material。
|
||||
|
||||
```json
|
||||
{
|
||||
"materials": {
|
||||
"version": "1.0.0",
|
||||
"custom_entity1:entity": { # 继承原生材质entity的自定义材质custom_entity1
|
||||
"+defines": [ "USE_ONLY_EMISSIVE", "USE_UV_ANIM"] # 渲染时添加USE_ONLY_EMISSIVE和USE_UV_ANIM宏定义
|
||||
"-defines": [ "USE_OVERLAY" ], # 因为原生的entity材质在"+defines"中添加了USE_OVERLAY宏定义,在这里可以使用"-defines"去掉USE_OVERLAY宏定义,原生的entity材质已在3.1.1中列出
|
||||
"msaaSupport": "NonMSAA" # 不使用MSAA抗锯齿技术
|
||||
},
|
||||
"custom_entity2:custom_entity1": { # 继承自定义材质custom_entity1的自定义材质custom_entity2
|
||||
"msaaSupport": "Both" # 使用MSAA抗锯齿技术
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
在同一目录resource_pack/materials下创建common.json,将上面文件路径填入。common.json列出的文件才会被正确读取作为自定义材质。
|
||||
|
||||
```python
|
||||
[
|
||||
{"path":"materials/entity.material"}
|
||||
]
|
||||
```
|
||||
|
||||
在自定义生物的资源包实体定义中添加以下字段使用上述自定义材质。
|
||||
|
||||
```json
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"minecraft:client_entity": {
|
||||
"description": {
|
||||
"identifier": "netease:squirrel",
|
||||
"min_engine_version": "1.8.0",
|
||||
"materials": {
|
||||
"default": "custom_entity1", # 默认材质
|
||||
"charged": "custom_entity2" # charged状态时使用的材质,类似闪电苦力怕与普通苦力怕使用了两套材质,SDK暂不支持设置该状态,一般使用一套default材质即可。(见下注)
|
||||
},
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
注:
|
||||
- 生物默认使用key值为default的材质,因此在需要修改生物材质时,使用类似如下的接口:
|
||||
```
|
||||
# 把松鼠的渲染材质修改为custom_entity2
|
||||
import mod.client.extraClientApi as clientApi
|
||||
comp = clientApi.GetEngineCompFactory().CreateActorRender(levelId)
|
||||
comp.AddActorRenderMaterial('netease:squirrel', 'default', 'custom_entity2')
|
||||
comp.RebuildActorRender('netease:squirrel')
|
||||
```
|
||||
- 目前SDK暂不支持设置生物的材质key值,如"把key值从default修改为charged",因此,一般使用default字段即可
|
||||
|
||||
### 3.2 字段说明
|
||||
|
||||
#### 3.2.1 宏定义(defines)
|
||||
|
||||
MC渲染器在不同的宏定义下会采取不同的策略,因此这些宏定义类似开关式的配置选项。通过"+defines","-defines"可在继承的材质的基础上添加或者去掉对应的宏定义,支持的宏定义如下:
|
||||
|
||||
```
|
||||
ALPHA_TEST
|
||||
COLOR_SECOND_TEXTURE
|
||||
COLOR_BASED
|
||||
DISABLE_TINTING
|
||||
FANCY
|
||||
ENABLE_FOG
|
||||
ENABLE_LIGHT
|
||||
GLINT
|
||||
ITEM_IN_HAND
|
||||
MULTI_COLOR_TINT
|
||||
MULTIPLICATIVE_TINT
|
||||
NO_TEXTURE
|
||||
TINTED_ALPHA_TEST
|
||||
UI_ENTITY
|
||||
USE_COLOR_MASK
|
||||
USE_EMISSIVE
|
||||
USE_MULTITEXTURE
|
||||
MASKED_MULTITEXTURE
|
||||
USE_ONLY_EMISSIVE
|
||||
USE_OVERLAY
|
||||
USE_SKINNING
|
||||
USE_UV_ANIM
|
||||
```
|
||||
|
||||
#### 3.2.2 其他字段
|
||||
|
||||
材质除了宏定义这类开关形式的配置外,还支持其他如字符串形式的配置,如示例中的”msaaSupport“,可在“NonMSAA”,“MSAA”,“Both”选择一个作为配置的值。自定义材质支持的各种配置如下:
|
||||
|
||||
| 字段名 | 待选值 | 描述 |
|
||||
| ---------------- | ------------------------------------------------------------ | ------------- |
|
||||
| msaaSupport | NonMSAA,MSAA,Both | MSAA抗锯齿 |
|
||||
| depthFunc | Always,Equal,NotEqual,Less,Greater,GreaterEqual,LessEqual | 深度测试 |
|
||||
| blendSrc | DestColor,SourceColor,Zero,One,OneMinusDestColor,OneMinusSrcColor,SourceAlpha,DestAlpha,OneMinusSrcAlpha | blend混合模式 |
|
||||
| blendDst | 同上 | blend混合模式 |
|
||||
| vertexShader | 一般使用“shaders/entity_hide.vertex”即可 | 顶点着色器 |
|
||||
| vrGeometryShader | 一般使用“shaders/entity.geometry”即可 | 几何着色器 |
|
||||
| fragmentShader | 一般使用“shaders/entity_hide.fragment“即可 | 片元着色器 |
|
||||
|
||||
## 4. 自定义动画
|
||||
|
||||
自定义的动画应该放在resource_pack根目录下的animations文件夹内。
|
||||
|
||||
动画是基于旋转角度、位置和大小的变化的帧动画。
|
||||
|
||||
开发者可以引用vanilla的动画或者创建自定义的动画。
|
||||
|
||||
可以通过blockbench制作动画。
|
||||
|
||||
#### 4.1 示例
|
||||
|
||||
resource_pack/animations/squirrel.animation.json
|
||||
|
||||
```python
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.squirrel.idle": {
|
||||
"loop": true,
|
||||
"animation_length": 2,
|
||||
"bones": {
|
||||
"rearFootLeft": {
|
||||
"rotation": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.4833": [15, 0, 0],
|
||||
"1.6": [10, 0, 0],
|
||||
"1.8833": [-10, 0, 0],
|
||||
"2.0": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
...
|
||||
}
|
||||
},
|
||||
"animation.squirrel.move": {
|
||||
"loop": true,
|
||||
"animation_length": 0.48,
|
||||
"bones": {
|
||||
"rearFootLeft": {
|
||||
"rotation": {
|
||||
"0.0": [5, 0, 0],
|
||||
"0.1667": [125, 0, 0],
|
||||
"0.4333": [5, 0, 0]
|
||||
}
|
||||
},
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.2 说明
|
||||
|
||||
该动画有2种动作,分别是空闲(idle)、移动(move)
|
||||
|
||||
|
||||
|
||||
## 5. 自定义动画控制器
|
||||
|
||||
自定义动画控制器应该放在resource_pack/animation_controllers目录下。
|
||||
|
||||
动画控制器被用来控制动画如何转换,何时进行转换。每一个动画控制器包含多个状态(states),每一个state播放一个或者多个动画。
|
||||
|
||||
自定义的动画控制器可以引用vanilla中的动画,如示例中的look_at_target。
|
||||
|
||||
#### 5.1 示例
|
||||
|
||||
resource_pack/animation_controllers/squirrel.animation_controllers.json
|
||||
|
||||
```json
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animation_controllers": {
|
||||
"controller.animation.squirrel.general": {
|
||||
"initial_state" : "default",
|
||||
"states": {
|
||||
"default": {
|
||||
"parameters": [ "query.ground_speed" ],
|
||||
"animations": [
|
||||
...
|
||||
],
|
||||
"transitions": [
|
||||
{ "move": "query.mod.is_moving" }
|
||||
]
|
||||
},
|
||||
"move": {
|
||||
"parameters": [ "query.ground_speed" ],
|
||||
"animations": [
|
||||
...
|
||||
],
|
||||
"transitions": [
|
||||
{ "default": "!query.mod.is_moving" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
默认动画为default,default中使用idle和look_at_target动画,其中look_at_target为vanilla定义的动画。
|
||||
|
||||
transitions为动画转移条件,当query.mod.is_moving为True时,从default转移到move,反之从move转移到default。query.mod.is_moving的使用[后面](#molang_node)会讲到。
|
||||
|
||||
## 6. 自定义模型
|
||||
|
||||
模型定义了实体的几何形状,自定义的模型放在resource_pack/models/entity目录下。
|
||||
|
||||
可以通过blockbench制作模型。
|
||||
|
||||
### 6.1 示例
|
||||
|
||||
resource_pack/models/entity/squirrel.geo.json
|
||||
|
||||
```json
|
||||
{
|
||||
"format_version": "1.12.0",
|
||||
"minecraft:geometry": [
|
||||
{
|
||||
"description": {
|
||||
"identifier": "geometry.squirrel",
|
||||
"texture_width": 64,
|
||||
"texture_height": 64,
|
||||
"visible_bounds_width": 4,
|
||||
"visible_bounds_height": 1,
|
||||
"visible_bounds_offset": [0, 0.5, 0]
|
||||
},
|
||||
"bones": [
|
||||
{
|
||||
"name": "body",
|
||||
"pivot": [0, 5, 8],
|
||||
"rotation": [-20, 0, 0],
|
||||
"mirror": true,
|
||||
"cubes": [
|
||||
{"origin": [-3, 2, -2], "size": [6, 5, 10], "uv": [0, 0], "mirror": false},
|
||||
{"origin": [-3, 7, 1], "size": [6, 1, 7], "uv": [22, 0], "mirror": false}
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 定位器(locators)
|
||||
|
||||
定位器偏移在模块空间中指定。
|
||||
|
||||
定位器的例子有 "lead“;定位器用于显示指引将附加到何处。
|
||||
|
||||
```json
|
||||
"locators": {
|
||||
"lead": {
|
||||
"head": [ 0.0, 14.0, -6.0 ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 7. 自定义渲染控制器
|
||||
|
||||
渲染控制器负责生物实体的渲染控制流程,包括使用的材质、贴图、几何模型等。
|
||||
|
||||
### 7.1 示例
|
||||
|
||||
资源包resource_pack/render_controllers目录下增加squirrel.render_controllers.json
|
||||
|
||||
```json
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"render_controllers": {
|
||||
"controller.render.squirrel": {
|
||||
"arrays": {
|
||||
"textures": {
|
||||
"Array.base": [
|
||||
"Texture.red",
|
||||
"Texture.gray"
|
||||
]
|
||||
},
|
||||
"materials": {
|
||||
"Array.skin": [
|
||||
"Material.red",
|
||||
"Material.gray"
|
||||
]
|
||||
}
|
||||
},
|
||||
"geometry": "Geometry.default",
|
||||
"materials": [ { "*": "Array.skin[query.variant]" }],
|
||||
"textures": ["Array.base[query.variant]"]
|
||||
},
|
||||
"controller.render.squirrel_more": {
|
||||
"materials": [ { "*": "query.mod.is_enchanted ? Material.gray : Material.red" } ],
|
||||
},
|
||||
"controller.render.squirrel_multi": {
|
||||
"materials": [
|
||||
{ "*": "Material.gray" },
|
||||
{ "head": "Material.red" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
1)在controller.render.squirrel_more中,对于材质的选用,使用python的变量[query.mod.is_enchanted](#molang_node)进行了控制,注意Material.gray必须在资源包minecraft:client_entity中进行声明,否则渲染时会找不到对应的material。
|
||||
|
||||
2)在controller.render.squirrel_multi中:
|
||||
|
||||
首先对模型的所有部件使用材质Material.gray;
|
||||
|
||||
然后对模型中的head部件使用Material.red
|
||||
|
||||
3)更多用法请参考微软官方文档
|
||||
|
||||
|
||||
|
||||
**注意:如果存在多个渲染控制器,其中的渲染顺序并不保证顺序。**
|
||||
|
||||
|
||||
|
||||
### 7.2 玩家渲染控制器
|
||||
|
||||
下面通过举例vanilla玩家的渲染控制器说明渲染控制器。
|
||||
|
||||
首先我们看player.entity.json下面一段json:
|
||||
|
||||
```json
|
||||
"render_controllers": [
|
||||
{ "controller.render.player.first_person": "variable.is_first_person" },
|
||||
{ "controller.render.player.third_person": "!variable.is_first_person && !variable.map_face_icon" },
|
||||
{ "controller.render.player.map": "variable.map_face_icon" },
|
||||
{ "controller.render.player.first_person_bloom": "variable.is_first_person" },
|
||||
{ "controller.render.player.third_person_bloom": "!variable.is_first_person && !variable.map_face_icon" }
|
||||
],
|
||||
```
|
||||
|
||||
在render_controllers数组中,玩家存在五个渲染控制器。
|
||||
|
||||
| 渲染控制器名称 | 渲染控制器应用条件 | 说明 |
|
||||
| ------------------------------------------- | ---------------------------------------------------- | -------------------------------- |
|
||||
| controller.render.player.first_person | variable.is_first_person | 第一人称时该渲染控制器生效 |
|
||||
| controller.render.player.third_person | !variable.is_first_person && !variable.map_face_icon | 非第一人称下同时非地图图标下生效 |
|
||||
| controller.render.player.map | variable.map_face_icon | 地图图标模式下生效 |
|
||||
| controller.render.player.first_person_bloom | variable.is_first_person | 第一人称时该渲染控制器生效 |
|
||||
| controller.render.player.third_person_bloom | !variable.is_first_person && !variable.map_face_icon | 非第一人称下同时非地图图标下生效 |
|
||||
|
||||
**其中,以上五个渲染控制器在渲染过程中并不保证顺序。**
|
||||
|
||||
|
||||
|
||||
## 8.资源包实体定义
|
||||
|
||||
### 8.1 概述
|
||||
|
||||
客户端实体(client_entity)的定义在resource_pack当中。
|
||||
|
||||
在resource_pack目录下创建文件夹“entity”,然后在该文件夹中创建json文件,如squirrel.entity.json,此json文件需要一个“format_version”和“minecraft:client_entity”的信息。
|
||||
|
||||
其中“minecraft:client_entity”部分只包含一个节点description,description下包含一些实体的详细定义,一般而言都会包括材质、贴图、动画、几何、渲染控制器等部分。
|
||||
|
||||
|
||||
|
||||
### 8.2 示例
|
||||
|
||||
resource_pack/entity/squirrel.entity.json
|
||||
|
||||
```json
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"minecraft:client_entity": {
|
||||
"description": {
|
||||
"identifier": "netease:squirrel",
|
||||
"spawn_egg":{
|
||||
"base_color":"#1778D2",
|
||||
"overlay_color":"#1778D2"
|
||||
},
|
||||
"render_controllers": [
|
||||
"controller.render.squirrel"
|
||||
],
|
||||
"geometry": {
|
||||
"default": "geometry.squirrel"
|
||||
},
|
||||
"textures": {
|
||||
"red": "textures/entity/squirrel/red",
|
||||
"gray": "textures/entity/squirrel/gray"
|
||||
},
|
||||
"materials": {
|
||||
"red": "entity_alphatest",
|
||||
"gray": "custom_entity"
|
||||
},
|
||||
"animations": {
|
||||
"move": "animation.squirrel.move",
|
||||
"idle": "animation.squirrel.idle",
|
||||
"look_at_target": "animation.common.look_at_target"
|
||||
},
|
||||
"animation_controllers": [
|
||||
{ "general": "controller.animation.squirrel.general"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### 说明
|
||||
|
||||
##### animations
|
||||
|
||||
对应于resource_pack/animations/squirrel.animation.json
|
||||
|
||||
##### animation_controllers
|
||||
|
||||
对应于resource_pack/animation_controllers/squirrel.animation_controllers.json
|
||||
|
||||
##### render_controllers
|
||||
|
||||
对应于resource_pack/render_controllers/squirrel.render_controllers.json
|
||||
|
||||
##### 贴图
|
||||
|
||||
资源包resource_pack/textures/entity目录下增加squirrel贴图,包括red.png和gray.png
|
||||
|
||||
|
||||
|
||||
### 8.3 Spawn Egg
|
||||
|
||||
用于设置实体刷怪蛋的颜色或者纹理。
|
||||
|
||||
当一个文件中包含多张纹理时,可以使用texture_index指定(默认为0),如:
|
||||
|
||||
```json
|
||||
"spawn_egg": {
|
||||
"texture": "spawn_egg",
|
||||
"texture_index": 2
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
另外也可以指定刷怪蛋的颜色,如:
|
||||
|
||||
```json
|
||||
"spawn_egg": {
|
||||
"base_color": "#53443E",
|
||||
"overlay_color": "#2E6854"
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### 8.4 enable_attachables
|
||||
|
||||
指定实体是否可以穿戴装备,这允许实体渲染盔甲,如:
|
||||
|
||||
```json
|
||||
"enable_attachables": true
|
||||
|
||||
```
|
||||
|
||||
### 8.5 脚本
|
||||
|
||||
脚本允许开发者使用*MoLang*来计算和存储数据,该数据可以被重复利用而不是不断重复地计算。
|
||||
|
||||
目前,脚本支持初始化(initialize)、设置父实体(parent_setup)、预动画(pre_animation)、动画(animate)、放大缩小(scale),后续将会支持更多。
|
||||
|
||||
我们简单通过如下示例来了解一下:
|
||||
|
||||
|
||||
|
||||
**示例1(史莱姆):**
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"pre_animation": [
|
||||
"variable.squish_factor = (query.previous_squish_value + (query.current_squish_value - query.previous_squish_value) * query.frame_alpha);",
|
||||
"variable.bounce = 1 / ((variable.squish_factor / (query.variant * 0.5 + 1)) + 1);",
|
||||
"variable.horizontal_scale_amount = variable.bounce * query.variant;",
|
||||
"variable.vertical_scale_amount = (1 / variable.bounce) * query.variant;"
|
||||
],
|
||||
"scaleX": "variable.horizontal_scale_amount",
|
||||
"scaleY": "variable.vertical_scale_amount",
|
||||
"scaleZ": "variable.horizontal_scale_amount"
|
||||
},
|
||||
|
||||
```
|
||||
|
||||
**示例2(羊):**
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"animate": [
|
||||
"setup",
|
||||
"look_at_target",
|
||||
"move",
|
||||
{ "baby_transform": "query.is_baby" }
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 9 创建自定义生物
|
||||
|
||||
```python
|
||||
self.CreateEngineEntityByTypeStr("netease:squirrel", pos, rot)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 10 脚本注册驱动节点<span id="molang_node"/>
|
||||
|
||||
```python
|
||||
import mod.client.extraClientApi as clientApi
|
||||
ClientSystem = clientApi.GetClientSystemCls()
|
||||
|
||||
class AnimationTestClientSystem(ClientSystem):
|
||||
def __init__(self, namespace, systemName):
|
||||
ClientSystem.__init__(self, namespace, systemName)
|
||||
self.mRotating = False # 脚本状态
|
||||
# 这里注册了"query.mod.is_moving"的计算节点,调用self.UpdateScriptVariable更新状态值
|
||||
self.queryVariableName = 'query.mod.is_moving'
|
||||
comp = self.CreateComponent('', "Minecraft", "queryVariable")
|
||||
result = comp.Register(self.queryVariableName, 0.0)
|
||||
|
||||
def UpdateScriptVariable(self):
|
||||
comp = self.CreateComponent('', "Minecraft", "queryVariable")
|
||||
result = comp.Set(self.queryVariableName, 1.0)
|
||||
```
|
||||
|
||||
## 11 自定义生物行为<span id="molang_node"/>
|
||||
### 11.1 概述
|
||||
开发者通过配置behaviorpack\entities中生物json的behavior,增加自定义behavior节点,并在python实现对应节点的逻辑,以实现自定义的生物行为。以下逐步讲解如何实现squirrel使用tnt攻击玩家的行为
|
||||
|
||||
### 11.2 behaviorpack\entities的生物json中配置behavior
|
||||
CustomEntityMod_behavior/entities/squirrel.json
|
||||
```json
|
||||
...
|
||||
"minecraft:behavior.python_custom:avoid_tnt": {
|
||||
"priority": 2,
|
||||
"module_path": "customEntityModScripts.avoidTntGoal",
|
||||
"class_name": "AvoidTntGoal",
|
||||
"arg_dict": {},
|
||||
"control_flags": [ "move"]
|
||||
},
|
||||
"minecraft:behavior.python_custom:place_tnt_to_target": {
|
||||
"priority": 3,
|
||||
"module_path": "customEntityModScripts.placeTntToTarget",
|
||||
"class_name": "PlaceTntToTarget",
|
||||
"control_flags": [ "move"]
|
||||
},
|
||||
...
|
||||
```
|
||||
格式说明:
|
||||
behaviorName:{
|
||||
"priority":int
|
||||
"module_path":string
|
||||
"class_name":string
|
||||
"arg_dict":dict
|
||||
}
|
||||
**其中behaviorName必须以 minecraft:behavior.python_custom: 为前缀**
|
||||
|
||||
字段说明:
|
||||
| 字段名 | 类型 | 必填项| 描述 |
|
||||
| ----------- | ------------ | -- | ------------- |
|
||||
| priority | int | 是 |行为的优先级 |
|
||||
| module_path | string | 是 | 行为的python模块路径,以 "." 分隔 |
|
||||
| class_name | string | 是 | 行为的python类名 |
|
||||
| arg_dict | dict | 否 | 行为的参数,会被传至python实例中 |
|
||||
| control_flags | list(string) | 否 | 控制标志,包含相同控制标志的行为被为冲突,**同一时刻下冲突的行为最多只有一个会被执行**。可用的标志有move, look, jump |
|
||||
|
||||
### 11.3 mod的scripts脚本中实现生物自定义行为的逻辑
|
||||
CustomEntityMod_behavior/customEntityModScripts/placeTntToTarget.py - 生物向目标放置tnt
|
||||
CustomEntityMod_behavior/customEntityModScripts/avoidTntGoal.py - 生物远离tnt
|
||||
以placeTntToTarget.py为例:
|
||||
|
||||
```python
|
||||
import mod.server.extraServerApi as serverApi
|
||||
CustomGoalCls = serverApi.GetCustomGoalCls()
|
||||
class PlaceTntToTarget(CustomGoalCls):
|
||||
def __init__(self, entityId, argsJson):
|
||||
CustomGoalCls.__init__(self, entityId, argsJson)
|
||||
print "PlaceTntToTarget init, entityId:", self.GetEntityId()
|
||||
print "PlaceTntToTarget init, args:", self.GetArgs()
|
||||
|
||||
def CanUse(self):
|
||||
# return True or False
|
||||
pass
|
||||
|
||||
def CanContinueToUse(self):
|
||||
# return True or False
|
||||
pass
|
||||
|
||||
def CanBeInterrupted(self):
|
||||
# return True or False
|
||||
pass
|
||||
|
||||
def Start(self):
|
||||
pass
|
||||
|
||||
def Stop(self):
|
||||
pass
|
||||
|
||||
def Tick(self):
|
||||
pass
|
||||
```
|
||||
函数说明:
|
||||
| 函数名 | 返回值 | 描述 |
|
||||
| ----------- | ------------- | ---------- |
|
||||
| CanUse | bool | 行为能否使用,行为未被执行时,引擎每帧调用。返回True时,若没有其他低优先级值的冲突行为且正在执行的高优先级值行为能被打断时,则开始执行此行为,调用Start函数 |
|
||||
| CanContinueToUse | bool |行为能否被继续使用,行为被执行时,每帧判断。是行为是否能继续使用的判断条件之一 |
|
||||
| CanBeInterrupted | bool | 行为能否被其他行为打断,行为在执行状态时,引擎每帧调用。运行时不能动态修改返回值,必须一直返回True或False |
|
||||
| Start | 无 |行为开始时执行的函数 |
|
||||
| Stop | 无 |行为停止时执行的函数 |
|
||||
| Tick | 无 |行为执行状态下,每秒执行最多20次,机器性能差时会降频 |
|
||||
**注意:**
|
||||
1)文件路径(即模块路径)必须与json配置中的**module_path**匹配
|
||||
2)自定义行为的类名必须与json中配置的**class_name**匹配
|
||||
3)自定义行为的类必须继承自**serverApi.GetCustomGoalCls()**, 并调用父类的__init__函数
|
||||
4)所有函数,均在**服务器线程(server)**调用
|
||||
|
||||
### 11.4 自定义AI执行流程图
|
||||
|
||||
<img src="./picture/customentity/custom_AI.png" alt="zombie" style="zoom:100%;" />
|
||||
|
||||
### 11.5 自定义AI代码流程图
|
||||
|
||||
<img src="./picture/customentity/custom_AI_code.png" alt="zombie" style="zoom:100%;" />
|
||||
|
||||
**注意:**
|
||||
|
||||
1)若两个CanUse的行为不冲突,且正在执行的高优先级值行为能被打断时,两个行为同时执行
|
||||
|
||||
2)生物的行为通道有两条,一条为普通行为通道,一条为敌对对象选择通道,两条通道可同时存在,每条通道仅可执行一种行为组件,目前存在七个选择对象的行为组件:
|
||||
|
||||
minecraft:behavior.defend_village_target
|
||||
|
||||
minecraft:behavior.owner_hurt_by_target
|
||||
|
||||
minecraft:behavior.vex_copy_owner_target
|
||||
|
||||
minecraft:behavior.hurt_by_target
|
||||
|
||||
minecraft:behavior.nearest_attackable_target
|
||||
|
||||
minecraft:behavior.wither_target_highest_damage
|
||||
132
mcguide/20-玩法开发/15-自定义游戏内容/3-自定义生物/02-重写原版生物.md
Normal file
@@ -0,0 +1,132 @@
|
||||
---
|
||||
front:
|
||||
hard: 入门
|
||||
time: 分钟
|
||||
---
|
||||
|
||||
# 重写原版生物
|
||||
|
||||
我们可以通过自定义与原版生物一样的identifier来重写原版生物的行为与外观。
|
||||
|
||||
请结合示例[CustomEntityMod](../../13-模组SDK编程/60-Demo示例.md#CustomEntityMod)来阅读该文档。
|
||||
|
||||
|
||||
|
||||
## 1. 重写生物行为
|
||||
|
||||
如示例[CustomEntityMod](../../13-模组SDK编程/60-Demo示例.md#CustomEntityMod)中,在behavior_pack/entities下添加custom_pig.json,identifier依然为minecraft:pig,然后加上了**苦力怕**的攻击组件minecraft:nearest_attackable_target和minecraft:target_nearby_sensor,以及爆炸事件,使得它会攻击玩家并且爆炸消失。
|
||||
|
||||
|
||||
|
||||
## 2. 重写生物外观
|
||||
|
||||
重写生物外观有两种方式:
|
||||
|
||||
* **重写客户端实体的定义(resource_pack/entity下),改方式为纯配置json的方式**
|
||||
|
||||
与重写生物行为一样,我们可以通过重写资源包下的entity定义、贴图、动画、模型、渲染控制器等json文件来重写生物的外观,如示例[CustomEntityMod](../../13-模组SDK编程/60-Demo示例.md#CustomEntityMod)中,猪穿上了屠夫的贴图。
|
||||
|
||||
```json
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"minecraft:client_entity": {
|
||||
"description": {
|
||||
"identifier": "minecraft:pig",
|
||||
"materials": { "default": "custom_entity" },
|
||||
"textures": {
|
||||
"default": "textures/entity/custom_pig", # 修改此贴图
|
||||
"saddled": "textures/entity/custom_pig_saddle" # 修改此贴图
|
||||
},
|
||||
"geometry": {
|
||||
"default": "geometry.pig"
|
||||
},
|
||||
"animations": {
|
||||
"setup": "animation.pig.setup.v1.0",
|
||||
"walk": "animation.quadruped.walk",
|
||||
"look_at_target": "animation.common.look_at_target",
|
||||
"baby_transform": "animation.pig.baby_transform"
|
||||
},
|
||||
"scripts": {
|
||||
"animate": [
|
||||
"setup",
|
||||
{ "walk": "query.modified_move_speed" },
|
||||
"look_at_target",
|
||||
{ "baby_transform": "query.is_baby" }
|
||||
]
|
||||
},
|
||||
"render_controllers": [ "controller.render.custom_pig" ],
|
||||
"spawn_egg": {
|
||||
"texture": "spawn_egg",
|
||||
"texture_index": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
并在textures/entity目录下增加贴图custom_pig.png和custom_pig_saddle.png
|
||||
|
||||
|
||||
|
||||
## 3. 关于重写玩家的客户端实体定义
|
||||
|
||||
**对玩家客户端定义的修改,都应该基于`data\resource_packs\vanilla_netease\entity\player.entity.json`进行,而非vanilla或其他的原版资源包。**
|
||||
|
||||
引擎支持玩家皮肤时,会对player的render_controllers进行硬编码的修改:
|
||||
|
||||
1. 根据玩家是否使用拥有自发光的会员皮肤,移除controller.render.player.first_person_bloom及controller.render.player.third_person_bloom,或者controller.render.player.first_person及controller.render.player.third_person。因为为了兼容自发光,请同时保留以上4个render controller。
|
||||
|
||||
2. 若玩家使用了个性化搭配,则会添加controller.render.persona_animated_face.third_person。
|
||||
|
||||
这会导致当开发者想完全重写player的外观时,例如:
|
||||
|
||||
```json
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"minecraft:client_entity": {
|
||||
"description": {
|
||||
"identifier": "minecraft:player",
|
||||
"materials": {
|
||||
"MC_default": "entity"
|
||||
},
|
||||
"textures": {
|
||||
"MC_default": "textures/entity/penguin/penguin"
|
||||
},
|
||||
"geometry": {
|
||||
"MC_default": "geometry.penguin"
|
||||
},
|
||||
"animations": {
|
||||
...
|
||||
},
|
||||
"scripts": {
|
||||
...
|
||||
},
|
||||
"render_controllers": [ "controller.render.penguin" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
那么当玩家使用了个性化搭配时,会多出一个render controller。
|
||||
|
||||
为了解决这种情况,可以在description中添加netease_override_persona属性。当该属性为true时,引擎不会对player的render_controllers作任何修改。例如:
|
||||
|
||||
```json
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"minecraft:client_entity": {
|
||||
"description": {
|
||||
"identifier": "minecraft:player",
|
||||
"netease_override_persona": true,
|
||||
...
|
||||
"render_controllers": [ "controller.render.penguin" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
90
mcguide/20-玩法开发/15-自定义游戏内容/3-自定义生物/03-生物位置绑定.md
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
front:
|
||||
hard: 入门
|
||||
time: 分钟
|
||||
---
|
||||
|
||||
# 实体位置绑定
|
||||
|
||||
开发者也可以在entity json中增加位置组件来增加可以骑乘的位置,该组件以 `minecraft:rideable` 开头,以**minecraft:boat**:
|
||||
|
||||
```json
|
||||
"format_version": "1.13.0",
|
||||
"minecraft:entity": {
|
||||
"description": {
|
||||
"identifier": "minecraft:boat",
|
||||
"is_spawnable": false,
|
||||
"is_summonable": true,
|
||||
"is_experimental": false
|
||||
},
|
||||
|
||||
"components": {
|
||||
//省略不关注的组件
|
||||
"minecraft:rideable": {
|
||||
"seat_count": 2,
|
||||
"interact_text": "action.interact.ride.boat",
|
||||
"pull_in_entities": true,
|
||||
|
||||
"seats": [
|
||||
{
|
||||
"position": [ 0.0, -0.2, 0.0 ],
|
||||
"min_rider_count": 0,
|
||||
"max_rider_count": 1,
|
||||
|
||||
"rotate_rider_by": -90,
|
||||
"lock_rider_rotation": 90
|
||||
},
|
||||
{
|
||||
"position": [ 0.2, -0.2, 0.0 ],
|
||||
"min_rider_count": 2,
|
||||
"max_rider_count": 2,
|
||||
|
||||
"rotate_rider_by": -90,
|
||||
"lock_rider_rotation": 90
|
||||
},
|
||||
{
|
||||
"position": [ -0.6, -0.2, 0.0 ],
|
||||
"min_rider_count": 2,
|
||||
"max_rider_count": 2,
|
||||
"lock_rider_rotation": 90
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**minecraft:horse_wild**:
|
||||
|
||||
```
|
||||
"minecraft:rideable": {
|
||||
"seat_count": 1,
|
||||
"family_types": [
|
||||
"player",
|
||||
"zombie"
|
||||
],
|
||||
"interact_text": "action.interact.mount",
|
||||
"seats": {
|
||||
"position": [ 0.0, 1.1, -0.2 ]
|
||||
}
|
||||
|
||||
},
|
||||
```
|
||||
|
||||
**参数解释**:
|
||||
|
||||
- seat_count:默认值 1, 改生物拥有的骑乘位置数目
|
||||
- crouching_skip_interact:默认值 true,为true时,如果与该实体互动的实体蹲伏,则无法与该实体互动
|
||||
- interact_text:默认值“” ,与玩家交互时显示的UI按钮上的文本内容
|
||||
- family_types:默认值 ”“,能够骑乘该实体的实体种类
|
||||
- controlling_seat:默认值 0, 控制该实体的位置index
|
||||
- pull_in_entities:默认值 false,如果为true,则此实体会将正确family_type的实体拉入任何可用的座位
|
||||
- rider_can_interact:默认值 false,如果为true,则由骑手查看时将选择此实体
|
||||
- seats: 默认值 “”,位置的详细内容:
|
||||
- position:默认值 [0.0,0.0,0.0],该座位的位置相对于该实体的位置
|
||||
- min_rider_count:默认值 0, 定义在可以使用此座位之前必须乘坐此实体的最少乘客数量
|
||||
- max_rider_count:默认值 0,定义在可以使用此座位之前必须乘坐此实体的最大乘客数量
|
||||
- rotate_rider_by:默认值 0.0,骑乘者旋转角度
|
||||
- lock_rider_rotation:默认值 181.0,允许骑乘者在旋转此实体时旋转的角度(以度为单位),忽略此设置时则无限制。
|
||||
152
mcguide/20-玩法开发/15-自定义游戏内容/3-自定义生物/04-使用API修改玩家表现.md
Normal file
@@ -0,0 +1,152 @@
|
||||
---
|
||||
front:
|
||||
hard: 入门
|
||||
time: 分钟
|
||||
---
|
||||
|
||||
# 使用API修改玩家表现
|
||||
|
||||
下面结合示例CustomEntityMod说明如何通过接口动态修改玩家模型与动作。
|
||||
|
||||
## 修改材质
|
||||
|
||||
### 接口
|
||||
|
||||
<a href="../../../../mcdocs/1-ModAPI/接口/玩家/渲染.html#addplayerrendermaterial" rel="noopenner"> AddPlayerRenderMaterial </a>
|
||||
|
||||
### 示例
|
||||
|
||||
```python
|
||||
actorRenderComp = self.CreateComponent(entityId, "Minecraft", "actorRender")
|
||||
actorRenderComp.AddPlayerRenderMaterial("default", "custom_entity")
|
||||
actorRenderComp.RebuildPlayerRender()
|
||||
def reset():
|
||||
actorRenderComp.AddPlayerRenderMaterial("default", "entity_alphatest")
|
||||
actorRenderComp.RebuildPlayerRender()
|
||||
self.ShowMsg("恢复默认玩家渲染材质")
|
||||
comp = clientApi.CreateComponent(clientApi.GetLevelId(), "Minecraft", "game")
|
||||
comp.AddTimer(3.0, reset)
|
||||
self.mIsTranform = True
|
||||
self.ShowMsg("切换玩家渲染材质中")
|
||||
```
|
||||
|
||||
### 说明
|
||||
|
||||
玩家的默认渲染材质为entity_alphatest,首先先修改为自定义材质custom_entity,然后定时3s恢复默认值。
|
||||
|
||||
### 效果
|
||||
|
||||
<img src="./picture/customentity/change_material.png" style="zoom:100%;" />
|
||||
|
||||
左边:custom_entity
|
||||
|
||||
右边:entity_alphatest
|
||||
|
||||
## 修改几何体与贴图
|
||||
|
||||
### 接口
|
||||
|
||||
<a href="../../../../mcdocs/1-ModAPI/接口/玩家/渲染.html#addplayergeometry" rel="noopenner"> AddPlayerGeometry </a>
|
||||
|
||||
<a href="../../../../mcdocs/1-ModAPI/接口/玩家/渲染.html#addplayertexture" rel="noopenner"> AddPlayerTexture </a>
|
||||
|
||||
### 示例
|
||||
|
||||
```python
|
||||
actorRenderComp = self.CreateComponent(entityId, "Minecraft", "actorRender")
|
||||
actorRenderComp.AddPlayerGeometry("default", "geometry.zombie.v1.8")
|
||||
actorRenderComp.AddPlayerTexture("default", "textures/entity/zombie/zombie")
|
||||
actorRenderComp.RebuildPlayerRender()
|
||||
def reset():
|
||||
actorRenderComp.AddPlayerGeometry("default", "geometry.humanoid.custom")
|
||||
actorRenderComp.AddPlayerTexture("default", "textures/entity/steve")
|
||||
actorRenderComp.RebuildPlayerRender()
|
||||
self.ShowMsg("恢复默认玩家渲染几何体")
|
||||
|
||||
comp = clientApi.CreateComponent(clientApi.GetLevelId(), "Minecraft", "game")
|
||||
comp.AddTimer(3.0, reset)
|
||||
```
|
||||
|
||||
### 说明
|
||||
|
||||
玩家的默认渲染几何体为geometry.humanoid.custom
|
||||
|
||||
玩家的默认渲染贴图为textures/entity/steve
|
||||
|
||||
首先把玩家默认渲染几何体改为geometry.zombie.v1.8,默认渲染贴图改为textures/entity/zombie/zombie,然后定时3s恢复默认值。
|
||||
|
||||
### 效果
|
||||
|
||||
<img src="./picture/customentity/change_geometry.png" style="zoom:100%;" />
|
||||
|
||||
左边:默认
|
||||
|
||||
右边:修改后的僵尸几何体以及贴图
|
||||
|
||||
**备注:修改几何体还会涉及到贴图以及动画,如果只是修改几何体,会出现动画无法正常播放等问题**
|
||||
|
||||
## 修改动画
|
||||
|
||||
### 接口
|
||||
|
||||
<a href="../../../../mcdocs/1-ModAPI/接口/玩家/渲染.html#addplayeranimation" rel="noopenner"> AddPlayerAnimation </a>
|
||||
|
||||
### 示例-修改动作
|
||||
|
||||
新增动作定义
|
||||
|
||||
```json
|
||||
"animation.player.custom.move.arms" : {
|
||||
"loop" : true,
|
||||
"bones" : {
|
||||
"leftarm" : {
|
||||
"rotation" : [ "variable.tcos0 + 30", 0.0, 0.0 ]
|
||||
},
|
||||
"rightarm" : {
|
||||
"rotation" : [ "-variable.tcos0 + 30", 0.0, 0.0 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
接口增加动画
|
||||
|
||||
```python
|
||||
actorRenderComp = self.CreateComponent(entityId, "Minecraft", "actorRender")
|
||||
actorRenderComp.AddPlayerAnimation("move.arms", "animation.player.custom.move.arms")
|
||||
```
|
||||
|
||||
说明:对原版move.arms动作进行调整,leftarm和rightarm的rotation各增加30,然后使用接口覆盖原版的定义。
|
||||
|
||||
### 示例-控制动画
|
||||
|
||||
move.arms和move.legs分别为玩家手部和腿部摆动的动画。在原版中,此两种动画没有任何条件限制,只要走动就会计算出两者的旋转角度。
|
||||
|
||||
在此,我们通过简单queryVariable组件定义的变量来控制这两个动画。
|
||||
|
||||
```json
|
||||
{
|
||||
"move.arms": "query.mod.rn_anim_index > 0"
|
||||
},
|
||||
{
|
||||
"move.legs": "query.mod.rn_anim_index > 1"
|
||||
}
|
||||
```
|
||||
|
||||
脚本控制如下:
|
||||
|
||||
```python
|
||||
comp = self.CreateComponent(entityId, "Minecraft", "queryVariable")
|
||||
comp.Register("query.mod.rn_anim_index", 0)
|
||||
comp.Set("query.mod.rn_anim_index", 1)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 修改动画控制器
|
||||
|
||||
### 接口
|
||||
|
||||
<a href="../../../../mcdocs/1-ModAPI/接口/玩家/渲染.html#addplayeranimationcontroller" rel="noopenner"> AddPlayerAnimationController </a>
|
||||
|
||||
可以通过自定义动画控制器后,使用该接口添加到玩家。
|
||||
200
mcguide/20-玩法开发/15-自定义游戏内容/3-自定义生物/05-使用API自定义坐骑.md
Normal file
@@ -0,0 +1,200 @@
|
||||
# 使用坐骑拓展接口
|
||||
## 概述
|
||||
|
||||
通过API控制坐骑的骑乘者和座位,开发者可指定骑乘者坐到任意座位,并且能够对坐骑上的座位进行动态的修改
|
||||
|
||||
## 前置知识
|
||||
|
||||
在新增自定义坐骑的时候,需要在json文件中为实体添加`minecraft:rideable`组件。以游戏中的船为例,下面是船的`minecraft:rideable`组件定义,忽略了该组件的一些参数:
|
||||
|
||||
```json
|
||||
"minecraft:rideable": {
|
||||
"seat_count": 2,
|
||||
"seats": [
|
||||
{
|
||||
"position": [ 0.0, -0.2, 0.0 ],
|
||||
"min_rider_count": 0,
|
||||
"max_rider_count": 1,
|
||||
|
||||
"rotate_rider_by": -90,
|
||||
"lock_rider_rotation": 90
|
||||
},
|
||||
{
|
||||
"position": [ 0.2, -0.2, 0.0 ],
|
||||
"min_rider_count": 2,
|
||||
"max_rider_count": 2,
|
||||
|
||||
"rotate_rider_by": -90,
|
||||
"lock_rider_rotation": 90
|
||||
},
|
||||
{
|
||||
"position": [ -0.6, -0.2, 0.0 ],
|
||||
"min_rider_count": 2,
|
||||
"max_rider_count": 2,
|
||||
"lock_rider_rotation": 90
|
||||
}
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
**参数解释**
|
||||
|
||||
- seat_count:表示同时能有多少个骑乘者在这个坐骑上,默认为1
|
||||
- seats:座位的定义,包含如下内容
|
||||
- position:该座位相对于坐骑的位置,默认为 [0, 0, 0]
|
||||
- rotate_rider_by:该座位上的骑乘者相对于坐骑的转向,默认为0
|
||||
- lock_rider_rotation:在该座位上的骑乘者视角允许转动的角度,默认为181,不设置即不限制角度
|
||||
- min_rider_count:定义该座位在骑乘者最少有多少个的时候启用,默认为0
|
||||
- max_rider_count:定义该座位在骑乘者最多有多少个的时候启用,默认为seat_count
|
||||
- controlling_seat:默认为0,一般不需要修改,即默认`riderIndex`为0的骑乘者来控制坐骑,`riderIndex`的含义见下文
|
||||
|
||||
**座位与乘客队列**
|
||||
|
||||
可以看到,原版的船定义了三个座位,并且最多只能有两个骑乘者同时在船上,为了便于理解,可以将座位与骑乘者看成两个独立的队列来理解
|
||||
|
||||
当第一个骑乘者上船时,当前的骑乘者数量变为1,依次检查`seats`参数中的座位是否满足条件。第二个和第三个座位因为不满足`min_rider_count`需要为2的条件,所以不会启用。骑乘者上船以后,会让船上所有的骑乘者依次寻找启用的座位
|
||||
|
||||

|
||||
|
||||
于是第一个骑乘者就坐到了一号位上,表现上就是骑乘者坐在了船的正中间
|
||||
|
||||

|
||||
|
||||
当第二个骑乘者上船时,当前的骑乘者数量变为2,依次检查`seats`参数中的座位是否满足条件。第一个座位因为不满足`max_rider_count`需要为1的条件,所以不会启用。骑乘者上船以后,会让船上所有的骑乘者依次寻找启用的座位
|
||||
|
||||

|
||||
|
||||
于是第一个骑乘者就坐到了二号位上,新加入的第二个骑乘者就坐到了三号位上,表现上就是两个骑乘者坐在了船的前后两边
|
||||
|
||||

|
||||
|
||||
**自定义坐骑**
|
||||
|
||||
在定义自定义坐骑的过程中,如果没有特殊的需求,一般不需要定义座位的`min_rider_count`和`max_rider_count`,即任何座位的启用条件都是默认值0~`seat_count`个,在这种情况下骑乘者和座位其实是一一对应的,也就是第一个乘客会坐到一号位,第二个乘客会坐到二号位
|
||||
|
||||

|
||||
|
||||
但为了适应原版的特性,在接口里仍然对这两个部分进行分开处理,分别用`seatIndex`和`riderIndex`表示座位的序号和骑乘者的序号,但大部分情况这两者是相同的。
|
||||
|
||||

|
||||
|
||||
## 使用
|
||||
|
||||
**获取坐骑上所有骑乘者的信息**
|
||||
|
||||
使用<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#getriders" rel="noopenner">GetRiders</a>接口来获取坐骑上所有骑乘者的信息,包括实体ID、在骑乘者队列中所处的位置以及当前的座位编号
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
import mod.server.extraServerApi as serverApi
|
||||
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
|
||||
riders = comp.GetRiders()
|
||||
```
|
||||
|
||||
### 骑乘者相关
|
||||
|
||||
**锁定坐骑上骑乘者队列,骑乘者上下坐骑不会影响其他骑乘者**
|
||||
|
||||
在原版坐骑中,当一个骑乘者离开坐骑时,后面的所有骑乘者会往前移动一位,使用<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#setentitylockriders" rel="noopenner">SetEntityLockRider</a>可以屏蔽这种逻辑,当一个骑乘者离开时不会变动坐骑上已有乘客的骑乘者序号。利用该接口可以实现类似车辆载具的效果,驾驶位上的司机下车以后,副驾驶的玩家依旧在原来的位置上
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
坐骑锁定后,实体骑乘坐骑的逻辑将发生变化(前提是未通过接口指定实体成为第n个骑乘者,下方会介绍):
|
||||
|
||||
**开始骑乘**
|
||||
|
||||
- **情况A-坐骑被锁定**:实体将在骑乘者者队列中从队首开始寻找是否有空的位置,如果有则成为该位置的骑乘者;如果没有则插入队尾,成为当前骑乘者队列中最后一位
|
||||
- **情况B-坐骑未锁定**:坐骑首先会将骑乘者队列中的所有空位删除,然后按照原版的逻辑来执行添加骑乘者操作
|
||||
- 如果当前待骑乘的实体是玩家,则会检测队列中第一个实体是否为玩家,如果不是玩家则会将待骑乘的玩家插到队首,成为队列中第一个骑乘者,否则插入队尾
|
||||
- 如果当前待骑乘的实体不是玩家,则插入队尾,成为当前骑乘者队列中的最后一位
|
||||
|
||||
**结束骑乘**
|
||||
|
||||
- **情况A-坐骑被锁定**:实体离开坐骑,实体原先在骑乘者队列中的位置将会变为空,当前坐骑上所有其他的骑乘者在骑乘者队列中的位置不会发生变化
|
||||
- **情况B-坐骑未锁定**:实体离开坐骑,在该坐骑的骑乘者队列中,位于该实体后面的所有骑乘者,在骑乘者队列中的位置往前移动一位
|
||||
|
||||
**注意**:如果坐骑未锁定,则重载存档后空的位置将被删除,并且坐骑上如果有玩家,同原版逻辑一样玩家会移动到最前面
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
import mod.server.extraServerApi as serverApi
|
||||
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
|
||||
comp.SetEntityLockRider(True)
|
||||
```
|
||||
|
||||
**让玩家或实体骑乘坐骑并且成为队列中指定序号的骑乘者(建议搭配锁定骑乘者接口使用)**
|
||||
|
||||
在<a href="../../../../mcdocs/1-ModAPI/接口/玩家/行为.html#setplayerrideentity" rel="noopenner">SetPlayerRideEntity</a>或<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#setriderrideentity" rel="noopenner">SetRiderRideEntity</a>接口中可以通过参数`riderIndex`设定玩家或实体在骑乘时直接成为骑乘者队列中指定序号的骑乘者,不会受到实体是否通过接口<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#setentitylockriders" rel="noopenner">SetEntityLockRider</a>锁定的影响
|
||||
|
||||
若玩家或实体当前已处在另一个坐骑上,则会先离开当前的坐骑并骑乘到目标坐骑上。注意,目标坐骑指定的序号必须没有骑乘者
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
import mod.server.extraServerApi as serverApi
|
||||
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
|
||||
comp.SetRiderRideEntity(playerId,rideEntityId,1)
|
||||
```
|
||||
|
||||
设定以后玩家或实体会成为队列中第二个骑乘者,于是该骑乘者会找到坐骑上第二个可以坐的位置,此时坐骑的情况如下:
|
||||
|
||||

|
||||
|
||||
**改变坐骑上骑乘者在队列中的所处的位置(建议搭配锁定骑乘者接口使用)**
|
||||
|
||||
接口<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#changeriderseat" rel="noopenner">ChangeRiderSeat</a>可以改变骑乘者的`riderIndex`,若指定的`riderIndex`上已经有骑乘者,则交换两个骑乘者的位置。注意,该接口需要对应的实体已经在骑乘状态下才能使用
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
import mod.server.extraServerApi as serverApi
|
||||
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
|
||||
comp.ChangeRiderSeat(1)
|
||||
```
|
||||
|
||||
### 座位相关
|
||||
|
||||
**增加坐骑上的座位**
|
||||
|
||||
接口<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#addentityseat" rel="noopenner">AddEntitySeat</a>可以在坐骑上增加一个座位,并设定座位的位置和转向。该接口同时也会使`minecraft:rideable`组件中的`seat_count`变量+1,新增的座位默认的`min_rider_count`和`max_rider_count`默认为0和新的`seat_count`,即表示该新增的座位不管坐骑上的骑乘者有几人都会处于启用状态
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
import mod.server.extraServerApi as serverApi
|
||||
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
|
||||
seatIndex = comp.AddEntitySeat((1.0, 1.0, 1.0), 90.0, 90.0)
|
||||
```
|
||||
|
||||
**修改坐骑上的座位**
|
||||
|
||||
接口<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#setentityseat" rel="noopenner">SetEntitySeat</a>可以修改一个已有座位的位置、转向以及玩家可旋转角度范围,处在该位置上的玩家在接口调用后也会移动到修改后的位置
|
||||
|
||||
**注意**:只能修改通过接口添加的座位
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
import mod.server.extraServerApi as serverApi
|
||||
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
|
||||
comp.SetEntitySeat(3, (1.0, 1.0, 1.0), 90.0, 90.0)
|
||||
```
|
||||
|
||||
**删除坐骑上的座位**
|
||||
|
||||
接口<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#deleteentityseat" rel="noopenner">DeleteEntitySeat</a>可以删除一个已有座位,处于该座位上的骑乘者会被强制离开坐骑
|
||||
|
||||
**注意**:只能删除通过接口添加的座位
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
import mod.server.extraServerApi as serverApi
|
||||
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
|
||||
comp.DeleteEntitySeat(3)
|
||||
```
|
||||
|
||||
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 193 KiB |
|
After Width: | Height: | Size: 295 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
BIN
mcguide/20-玩法开发/15-自定义游戏内容/3-自定义生物/picture/customride/index.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 229 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 158 KiB |