--- front: https://nie.res.netease.com/r/pic/20211104/69055361-2e7a-452f-8b1a-f23e1262a03a.jpg hard: 高级 time: 15分钟 --- # 了解自定义特征规则 在第六章中,我们已经初步学期了如何通过编辑器制作一个**特征规则**(**Feature Rule**,又译**地物规则**)。在本节中,我们将从JSON的层面更详细地了解特征规则。 ## 了解特征规则文件 我们先来查看我们之前使用编辑器制作的那个特征规则的代码: ```json { "format_version": "1.14.0", "minecraft:feature_rules": { "description": { "identifier": "tutorial_demo:demo_feature_rules", "places_feature": "tutorial_demo:demo_feature" }, "conditions": { "placement_pass": "surface_pass" }, "distribution": { "coordinate_eval_order": "xzy", "iterations": 1, "scatter_chance": 10, "x": { "distribution": "uniform", "extent": [ 0, 16 ] }, "y": "query.get_height_at(variable.originx,variable.originz)-3", "z": { "distribution": "uniform", "extent": [ 0, 16 ] } } } } ``` 我们可以看到,特征规则是可以放在`netease_feature_rules`文件夹中的,使用的模式标识符皆为`minecraft:feature_rules`,并且在这里我们使用的是`1.14.0`的格式版本。事实上,我们也可以使用`1.13.0`和`1.16.0`的格式版本。 在模式标识符下有三个字段,分别是`description`、`conditions`和`distribution`,分别是该特征规则的描述、条件和分布。其中,我们可以看到分布对象`distribution`中的内容非常地熟悉。没错,这里和散植特征的格式是完全一致的。其实,每一个已定义的特征规则都会在游戏生成生物群系的不同阶段上**逐区块**地执行一次类似于散植特征的逻辑。简单地说,在每个区块上,特征规则都会随机选取一个点,然后以该点为起始点做一次散植,因此,我们可以在`distribution`对象中定义一套与散植特征相同格式的字段。唯一的不同是,散植特征中的`places_feature`字段在这里被移动到了描述对象`description`中。 条件对象`conditions`则用于定义特征规则放置特征的条件,其中`placement_pass`便是我们之前在第六章中便接触过的特征**放置阶段**(**Placement Pass**)的定义。这里我们使用了`surface_pass`来代表在生成器生成地形中的地表阶段放置。 在我们这个示例中,三个轴向的坐标的串演算顺序为`xzy`。同时,我们可以看到`y`字段中使用了获得X轴和Z轴起始点处的世界高度的Molang查询函数。如果Y轴先于X、Z轴演算,则我们无法通过变量得到X和Z轴的起始点坐标。那么我们目前的逻辑就会失效,这也是为什么我们将串演算顺序调整成了`xzy`的原因。 我们再来看一个原版特征规则的示例: ```json { "format_version": "1.13.0", "minecraft:feature_rules": { "description": { "identifier": "minecraft:bamboo_jungle_after_surface_bamboo_feature", "places_feature": "minecraft:bamboo_then_podzol_feature" }, "conditions": { "placement_pass": "after_surface_pass", "minecraft:biome_filter": [ { "test": "has_biome_tag", "operator": "==", "value": "bamboo" }, { "test": "has_biome_tag", "operator": "==", "value": "jungle" } ] }, "distribution": { "iterations": "math.clamp(math.trunc(math.ceil((query.noise(math.trunc(variable.originx / 80), math.trunc(variable.originz / 80)) + 0.3) * 160)), 15, 160)", "x": { "distribution": "uniform", "extent": [ 0, 16 ] }, "y": "query.heightmap(variable.worldx, variable.worldz)", "z": { "distribution": "uniform", "extent": [ 0, 16 ] } } } } ``` 这里我们可以看到,`conditions`字段下多了一个`minecraft:biome_filter`条件。这个条件是用于过滤生物群系的。通过一个或多个过滤器的线性排列或逻辑组合,我们可以使特征规则仅在特定的生物群系下放置特征,这实现了规则驱动的特征放置,这样放置出的特征也正是我们先前所说的**自动型特征**(**Automatic Feature**,又译**自动型地物**),即**隐式特征**(**Implicit Feature**,又译**隐式地物**)。 所以,从宏观上看,我们有两种放置特征的方式,一种是通过特征规则通过条件自动控制放置的隐式特征,另一种是通过生物群系的定义强制放置的显式特征。 至此,我们便基本学习了特征和特征规则的写法。接下来的几个小节,我们一起通过各种演示亲自操作,将各种特征的定义与生成的编写落到实处。