骑马与砍杀中文站论坛

 找回密码
 注册(Register!)

QQ登录

只需一步,快速开始

搜索
查看: 896|回复: 4

[经验与教程] 【战团】【探究】关于动态AI网格的实现

[复制链接]

23

主题

335

回帖

267

积分

见习骑士

Rank: 3

UID
3189500
第纳尔
2549
精华
0
互助
24
荣誉
4
贡献
10
魅力
235
注册时间
2020-6-13
鲜花(66) 鸡蛋(0)
发表于 2023-9-18 17:21:49 | 显示全部楼层 |阅读模式
本帖最后由 武安apk43 于 2023-9-26 15:50 编辑

我想实现一些比较有意思的功能,比如攻城的闸门、吊桥、可破坏的城墙等等,但无奈于AI网格是场景编辑时定好的,就算做了这些,AI不会正确寻路也白搭。这也是为什么一些动态场景在联机比较常见,而单机就几乎没有,最大的问题就是AI寻路问题。


单机里默认module.ini把can_use_scene_props_in_single_player设为0,禁用了可移动场景道具的交互。如果把这个启用就会发现,战团原版里的几乎所有城堡的闸门都是可以控制开关的,因为触发器代码都是写好的。

比如攻城塔,AI网格都是按照攻城塔终点位置来铺的,在攻城塔未到达终点之前,脚本里默认是让所有人坚守,然后到了终点命令所有人冲锋。如果在未到达终点之前玩家手动命令所有人冲锋,AI就会傻乎乎按照AI网格往前走,不管有没有路。

为了让AI能够根据场景变动而改变寻路,我受Unity的Nav Mesh Obstacle的启发,想到了动态AI网格的方案。这个方案的好处在于,无需用脚本控制AI目的地,更别提用脚本重写寻路算法。
于是在wse2作者k700的启发下,了解了这个战团自带OP:
ai_mesh_face_group_show_hide          = 1805  # (ai_mesh_face_group_show_hide, <group_no>, <value>), # 1 for enable, 0 for disable
                                              # Debug -- Draws the selected index of triangles/quads from the navigation graph on-screen.
这个group_no就是AI网格的id,以面为单位。而经过尝试后就又遇到了棘手的问题,详细请看这个帖:
【探究】关于AI网格纹理消失的原因和解决方案 - MOD制作技术区 - 骑马与砍杀中文站论坛 - Powered by Discuz! (mountblade.com.cn)

在修复这个问题之前,我尝试用这个op代码来测试是否有效,结果铺好网格后,无论是否显示、隐藏,AI都能通过指定的AI网格面,并且由于显示不出AI网格的面,也无法判断AI网格的状态。
在通过修复字体之后,神奇的事发生了,op生效了。

方法比较简单:
在能正确显示AI网格面的纹理的情况下,选定需要动态变化的网格,编辑AI网格时设定一个特殊id(默认创建的都是0),
(点击展开 / 收起)


然后在脚本里用ai_mesh_face_group_show_hide控制指定ID的AI网格的显示和隐藏。

加勒比海盗那个独立游戏的MS系统里还有一个ai_mesh_face_group_translate更加灵活,可以移动AI网格。。。

(点击展开 / 收起)



以城堡闸门为例:
在编辑模式下铺好AI网格,并让闸门下方的网格设定一个AI mesh id(只要不为0,不与其他AI网格重复就行),然后
这个是闸门开关的触发器在scene_props.py里:


  1. ("winch_b",sokf_moveable|spr_use_time(5),"winch_b","bo_winch", [
  2.    (ti_on_scene_prop_use,
  3.     [
  4.       (store_trigger_param_1, ":agent_id"),
  5.       (store_trigger_param_2, ":instance_id"),

  6.       #for only server itself-----------------------------------------------------------------------------------------------
  7.       (call_script, "script_use_item", ":instance_id", ":agent_id"),
  8.       #for only server itself-----------------------------------------------------------------------------------------------
  9.       (get_max_players, ":num_players"),                              
  10.       (try_for_range, ":player_no", 1, ":num_players"), #0 is server so starting from 1
  11.         (player_is_active, ":player_no"),
  12.         (multiplayer_send_2_int_to_player, ":player_no", multiplayer_event_use_item, ":instance_id", ":agent_id"),
  13.       (try_end),
  14.     ]),
  15.   ]),
复制代码

战团原版把一些交互场景道具都写在了script_use_item里,不难发现scene_prop_open_or_close_slot就是存储一些场景道具的开关状态。其中闸门是spr_portcullis,代码部分



  1. (try_begin),
  2.          (eq, ":effected_object", "spr_portcullis"),
  3.          (scene_prop_get_slot, ":opened_or_closed", ":instance_id", scene_prop_open_or_close_slot),

  4.          (try_begin),
  5.            (eq, ":opened_or_closed", 0), #open gate

  6.            (scene_prop_enable_after_time, ":instance_id", 400), #4 seconds
  7.            (try_begin),
  8.              (this_or_next|multiplayer_is_server),
  9.              (neg|game_in_multiplayer_mode),
  10.              (prop_instance_get_position, pos0, ":effected_object_instance_id"),
  11.              (position_move_z, pos0, 375),
  12.              (prop_instance_animate_to_position, ":effected_object_instance_id", pos0, 400),
  13.            (try_end),
  14.            (scene_prop_set_slot, ":instance_id", scene_prop_open_or_close_slot, 1),

  15.            (try_begin),
  16.              (eq, ":scene_prop_id", "spr_winch_b"),
  17.              (this_or_next|multiplayer_is_server),
  18.              (neg|game_in_multiplayer_mode),
  19.              (prop_instance_get_position, pos1, ":instance_id"),
  20.              (prop_instance_rotate_to_position, ":instance_id", pos1, 400, 72000),
  21.            (try_end),
  22.          (else_try), #close gate
  23.            (scene_prop_enable_after_time, ":instance_id", 400), #4 seconds
  24.            (try_begin),
  25.              (this_or_next|multiplayer_is_server),
  26.              (neg|game_in_multiplayer_mode),
  27.              (prop_instance_get_position, pos0, ":effected_object_instance_id"),
  28.              (position_move_z, pos0, -375),
  29.              (prop_instance_animate_to_position, ":effected_object_instance_id", pos0, 400),
  30.            (try_end),
  31.            (scene_prop_set_slot, ":instance_id", scene_prop_open_or_close_slot, 0),

  32.            (try_begin),
  33.              (eq, ":scene_prop_id", "spr_winch_b"),
  34.              (this_or_next|multiplayer_is_server),
  35.              (neg|game_in_multiplayer_mode),
  36.              (prop_instance_get_position, pos1, ":instance_id"),
  37.              (prop_instance_rotate_to_position, ":instance_id", pos1, 400, -72000),
  38.            (try_end),
  39.          (try_end),
复制代码



所以完全可以在#open gate部分加上 (ai_mesh_face_group_show_hide, <your_mesh_id>, 1),比如在“(scene_prop_set_slot, ":instance_id", scene_prop_open_or_close_slot, 1),”后面加上;
在#close gate部分加上(ai_mesh_face_group_show_hide, <your_mesh_id>, 0),比如在“(scene_prop_set_slot, ":instance_id", scene_prop_open_or_close_slot, 0),”后面加上。

因为城门默认是关闭的,所以可以在winch_b里加上

  (ti_on_scene_prop_hit,
    [
      (ai_mesh_face_group_show_hide, <your_mesh_id>, 0),
   ]),

似乎这个op代码在这里不生效,我推测是先加载场景道具再加载AI网格,所以就在场景开始之后触发一次:

   (3, 0, ti_once, [],
   [
     (ai_mesh_face_group_show_hide, <your_mesh_id>, 0),
   ]),

这样城门打开时AI就能自动进城,关闭时就绕路走了

为了更好记忆场景道具对应的AI Mesh ID,可以在module_constants.py里定义一些常量,比如设定城堡吊闸的AI网格ID设为了10,那么就可以写PORTCULLIS_AI_MESH_ID   =  10 # 吊闸,这样就更方便管理一些,需要用的时候直接用(ai_mesh_face_group_show_hide, PORTCULLIS_AI_MESH_ID, <value>)。






评分

参与人数 1第纳尔 +20 互助 +2 魅力 +6 收起 理由
agjib + 20 + 2 + 6 您的帖子很有价值!

查看全部评分

鲜花鸡蛋

815208129  在2023-9-20 13:08  送朵鲜花  并说:我非常同意你的观点,送朵鲜花鼓励一下
815208129  在2023-9-20 13:08  送朵鲜花  并说:我非常同意你的观点,送朵鲜花鼓励一下
815208129  在2023-9-20 13:08  送朵鲜花  并说:我非常同意你的观点,送朵鲜花鼓励一下
半世尘埃  在2023-9-18 20:22  送朵鲜花  并说:我非常同意你的观点,送朵鲜花鼓励一下
B站个人空间:https://b23.tv/rZhCYpH

31

主题

200

回帖

184

积分

见习骑士

Rank: 3

UID
2462463
第纳尔
1572
精华
0
互助
23
荣誉
0
贡献
0
魅力
80
注册时间
2015-3-3
鲜花(55) 鸡蛋(0)
发表于 2023-9-18 17:40:29 | 显示全部楼层
沙发是我的!!!

43

主题

1159

回帖

441

积分

骑士

Rank: 4Rank: 4

UID
3065189
第纳尔
685
精华
0
互助
16
荣誉
0
贡献
2
魅力
11
注册时间
2019-3-28

骑士美德之英勇勋章[杰出会员活跃勋章]

QQ
鲜花(108) 鸡蛋(0)
发表于 2023-9-18 20:23:01 | 显示全部楼层
赞!!!!!!!!!!!!!!!!!!!!!!!
忠 誠 勇 毅 ,心 系 社 會

23

主题

335

回帖

267

积分

见习骑士

Rank: 3

UID
3189500
第纳尔
2549
精华
0
互助
24
荣誉
4
贡献
10
魅力
235
注册时间
2020-6-13
鲜花(66) 鸡蛋(0)
 楼主| 发表于 2023-9-18 21:38:30 | 显示全部楼层
目前在WSE2是不生效的,预计下版本更新会修复
B站个人空间:https://b23.tv/rZhCYpH

0

主题

22

回帖

7

积分

平民

Rank: 1

UID
3284052
第纳尔
467
精华
0
互助
0
荣誉
0
贡献
0
魅力
0
注册时间
2021-11-3

骑砍中文站APP会员勋章

鲜花(10) 鸡蛋(0)
发表于 2023-9-19 14:57:53 来自手机 | 显示全部楼层
非常好,太厉害了。去试试来自: Android客户端
您需要登录后才可以回帖 登录 | 注册(Register!)

本版积分规则

Archiver|手机版|小黑屋|骑马与砍杀中文站

GMT+8, 2024-5-25 21:34 , Processed in 0.120969 second(s), 28 queries , Gzip On, MemCached On.

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表