--- front: https://nie.res.netease.com/r/pic/20211104/69055361-2e7a-452f-8b1a-f23e1262a03a.jpg hard: 进阶 time: 25分钟 --- # 让实体在水中悬浮 我们知道,鸭子都喜欢在水面上游动。鸭子在游动的时候,虽然双脚在水中拍打,但是在水面上却极为平稳。成语“鸭子凫水”便意味着暗地使劲,明面上看不出来的行为。而我们目前的水鸭在水中漂浮时却仅仅是像其他生物一样,一上一下。在本节中,我们将我们的鸭子的行为改为在水面上持续悬浮。 ## 在原版实体中找到对应的组件 我们在原版实体中回忆哪种实体存在悬浮在液体表面的行为。不难发现,赤足兽便是一种可以在熔岩表面悬浮的实体。因此,赤足兽的行为文件中必定存在一种可以用于悬浮的组件。我们打开赤足兽的行为文件来一探究竟。由于在水面漂浮应该是一种AI意向,我们着重关注带有`behavior.`前缀的组件。 ```json "minecraft:behavior.rise_to_liquid_level": { "priority": 0, "liquid_y_offset": 0.25, "rise_delta": 0.01, "sink_delta": 0.01 }, "minecraft:behavior.move_to_lava": { "priority": 7, "search_range": 16, "search_height": 10, "goal_radius": 0.9, "search_count": 30 }, "minecraft:behavior.random_stroll": { "priority": 8, "speed_multiplier": 0.8 }, "minecraft:behavior.look_at_player": { "priority": 9, "look_distance": 6.0, "probability": 0.02 }, "minecraft:behavior.random_look_around": { "priority": 10 }, "minecraft:behavior.panic": { "priority": 3, "speed_multiplier": 1.1, "panic_sound": "panic", "sound_interval": { "range_min": 1.0, "range_max": 3.0 } }, "minecraft:behavior.tempt": { "priority": 5, "speed_multiplier": 1.2, "items": [ "warped_fungus", "warped_fungus_on_a_stick" ], "tempt_sound": "tempt", "sound_interval": { "range_min": 2.0, "range_max": 5.0 } } ``` 很快,我们便能通过其组件名的字面意思定位到`priority`优先级为0的那个组件`minecraft:behavior.rise_to_liquid_level`。事实上,这个确实就是能够使赤足兽悬浮的AI意向。我们将其复制到鸭子中。 ## 实现水鸭的行为 我们稍作修改,然后将其复制到水鸭的行为定义文件中。 ```json "minecraft:behavior.rise_to_liquid_level": { "priority": 0, "liquid_y_offset": -0.5, "rise_delta": 0.01, "sink_delta": 0.01 } ``` 这并没有结束。因为我们知道,水鸭之所以会在水面上上下浮动是因为另一个AI意向也在起作用,那就是`minecraft:behavior.float`。我们删除这个AI意向。 最后,我们更改水鸭的导航组件。因为我们删除了`minecraft:behavior.float`,水鸭的AI便不再要求水鸭持续浮在水面上,所以我们在水鸭的导航组件`minecraft:navigation.walk`中加入`can_sink`并设置为`false`。这样,水鸭在水中便不会下沉。 ```json "minecraft:navigation.walk": { "can_path_over_water": true, "can_sink": false, "avoid_damage_blocks": true } ``` 至此,我们从理论上边实现了水鸭的行为替换。 ```json { "format_version": "1.16.0", "minecraft:entity": { "description": { "identifier": "tutorial_demo:teal", "runtime_identifier": "minecraft:chicken", "is_spawnable": true, "is_summonable": true, "is_experimental": false }, "component_groups": { "minecraft:teal_baby": { "minecraft:is_baby": {}, "minecraft:scale": { "value": 0.5 }, "minecraft:ageable": { "duration": 1200, "feed_items": ["wheat_seeds", "beetroot_seeds", "melon_seeds", "pumpkin_seeds"], "grow_up": { "event": "minecraft:ageable_grow_up", "target": "self" } }, "minecraft:behavior.follow_parent": { "priority": 5, "speed_multiplier": 1.1 } }, "minecraft:teal_adult": { "minecraft:experience_reward": { "on_bred": "Math.Random(1,7)", "on_death": "query.last_hit_by_player?Math.Random(1,3):0" }, "minecraft:loot": { "table": "loot_tables/entities/chicken.json" }, "minecraft:breedable": { "require_tame": false, "breeds_with": { "mate_type": "tutorial_demo:teal", "baby_type": "tutorial_demo:teal", "breed_event": { "event": "minecraft:entity_born", "target": "baby" } }, "breed_items": ["wheat_seeds", "beetroot_seeds", "melon_seeds", "pumpkin_seeds"] }, "minecraft:behavior.breed": { "priority": 3, "speed_multiplier": 1 }, "minecraft:rideable": { "seat_count": 1, "family_types": ["zombie"], "seats": { "position": [0, 0.4, 0] } }, "minecraft:spawn_entity": { "entities": { "min_wait_time": 300, "max_wait_time": 600, "spawn_sound": "plop", "spawn_item": "egg", "filters": { "test": "rider_count", "subject": "self", "operator": "==", "value": 0 } } } } }, "components": { "minecraft:type_family": { "family": ["chicken", "mob"] }, "minecraft:breathable": { "total_supply": 15, "suffocate_time": 0 }, "minecraft:collision_box": { "width": 0.6, "height": 0.8 }, "minecraft:nameable": {}, "minecraft:health": { "value": 4, "max": 4 }, "minecraft:hurt_on_condition": { "damage_conditions": [ { "filters": { "test": "in_lava", "subject": "self", "operator": "==", "value": true }, "cause": "lava", "damage_per_tick": 4 } ] }, "minecraft:movement": { "value": 0.25 }, "minecraft:damage_sensor": { "triggers": { "cause": "fall", "deals_damage": false } }, "minecraft:leashable": { "soft_distance": 4, "hard_distance": 6, "max_distance": 10 }, "minecraft:balloonable": { "mass": 0.5 }, "minecraft:navigation.walk": { "can_path_over_water": true, "can_sink": false, // 添加不会下沉 "avoid_damage_blocks": true }, "minecraft:movement.basic": {}, "minecraft:jump.static": {}, "minecraft:can_climb": {}, "minecraft:despawn": { "despawn_from_distance": {} }, "minecraft:behavior.rise_to_liquid_level": { "priority": 0, "liquid_y_offset": -0.5, "rise_delta": 0.01, "sink_delta": 0.01 }, // 添加赤足兽的悬浮行为 "minecraft:behavior.panic": { "priority": 1, "speed_multiplier": 1.5 }, "minecraft:behavior.mount_pathing": { "priority": 2, "speed_multiplier": 1.5, "target_dist": 0, "track_target": true }, "minecraft:behavior.tempt": { "priority": 4, "speed_multiplier": 1, "items": ["wheat_seeds", "beetroot_seeds", "melon_seeds", "pumpkin_seeds"] }, "minecraft:behavior.random_stroll": { "priority": 6, "speed_multiplier": 1 }, "minecraft:behavior.look_at_player": { "priority": 7, "look_distance": 6, "probability": 0.02 }, "minecraft:behavior.random_look_around": { "priority": 8 }, "minecraft:physics": {}, "minecraft:pushable": { "is_pushable": true, "is_pushable_by_piston": true }, "minecraft:conditional_bandwidth_optimization": {} }, "events": { "from_egg": { "add": { "component_groups": ["minecraft:teal_baby"] } }, "minecraft:entity_spawned": { "randomize": [ { "weight": 95, "trigger": "minecraft:spawn_adult" }, { "weight": 5, "add": { "component_groups": ["minecraft:teal_baby"] } } ] }, "minecraft:entity_born": { "remove": {}, "add": { "component_groups": ["minecraft:teal_baby"] } }, "minecraft:ageable_grow_up": { "remove": { "component_groups": ["minecraft:teal_baby"] }, "add": { "component_groups": ["minecraft:teal_adult"] } }, "minecraft:spawn_adult": { "add": { "component_groups": ["minecraft:teal_adult"] } } } } } ``` 但是事实上,由于某些缺陷,我们当前的水鸭在实际游戏中依旧会无视`minecraft:behavior.rise_to_liquid_level`行为并给自己添加一个`minecraft:behavior.float`行为。这会导致我们的行为替换失败。这是由于我们的水鸭包是Blockbench生成的,使用了微软最新的清单文件格式版本,我们需要将清单文件中格式版本从2改为1才能消除这一隐患。 同样地,我们在资源包中也需要将清单文件的格式版本从2替换为1,否则将因为格式版本的不对应导致水鸭的贴图无法加载。由于格式版本的改变,这将影响到最低引擎版本,所以我们将资源包中的最低引擎版本删除,否则将导致加载失败。 ```json { "format_version": "1.10.0", "minecraft:client_entity": { "description": { "identifier": "tutorial_demo:teal", //"min_engine_version": "1.12.0", "materials": { "default": "chicken", "legs": "chicken_legs" }, "textures": { "default": "textures/entity/teal" }, "geometry": { "default": "geometry.teal" }, "animations": { "move": "animation.teal.move", //"general": "animation.teal.general", "look_at_target": "animation.common.look_at_target", "baby_transform": "animation.teal.baby_transform" }, "scripts": { "animate": [ //"general", { "move": "query.modified_move_speed" }, "look_at_target", { "baby_transform": "query.is_baby" } ] }, "render_controllers": ["controller.render.chicken"], "spawn_egg": { "base_color": "#62c287", "overlay_color": "#87692b" } } } } ``` 同时,我们将`general`动画删除。`general`动画是硬编码的翅膀煽动动画,鸭子在水中或空气中都会播放该动画。但是,众所周知,鸭子游泳时翅膀是不煽动的,所以我们直接删除此动画。 ![](./images/8.6_in-game.gif) 我们进入游戏,可以看到我们鸭子确实拥有了悬浮的AI意向!