骑马与砍杀中文站论坛

 找回密码
 注册(Register!)

QQ登录

只需一步,快速开始

搜索
购买CDKEY 小黑盒加速器
查看: 1437|回复: 7

[经验与教程] 爬行飞鸟各生物及飞行器装甲车大炮等对象运动行为控制特性的联系与区别方法论

[复制链接]

202

主题

984

回帖

986

积分

子爵[版主]

Rank: 7Rank: 7Rank: 7

UID
2893127
第纳尔
14521
精华
0
互助
90
荣誉
18
贡献
325
魅力
775
注册时间
2017-11-5
鲜花(428) 鸡蛋(0)
发表于 2023-1-10 09:37:32 | 显示全部楼层 |阅读模式
本帖最后由 vegetto 于 2023-1-10 14:02 编辑

首先是到人场景物各系统的运动行为控制总章https://bbs.mountblade.com.cn/thread-2094109-1-1.html先看一下各系统运动控制的基础用法。本贴作为其中一个具体应用大类特别拎出来讲下。

关于骑砍中模拟人、马、各种动物包括地上跑的水里游的天上飞的、飞机坦克战舰及其同类机械载具、以及不同对象的配合活动比如马车以及坦克要载人这种。并没有把其中很多对象的运动和其他使之像个“活体”的行为处理到尽善尽美或者存在技术瓶颈,或者玩家还行ai有些僵了等等情况。
并且大多数时候,我们把这些不同对象的处理到程序时,持一种分开研究的观念。实际上我们要先联系去对待不同运动对象的各种行为控制,因为人和其他生物都是一个祖先演化的,机械工具也是根据各种生物启发而作为人类器官的功能延申,所以他们都有一种共性的地方然后部分进行条件限制产生分化。
可以先看看我的顶点动画控制系统https://bbs.mountblade.com.cn/thread-2096174-1-1.html,以上不同生物机械对象可以采用不同系统换皮比如人、马、场景物这些具备位移和其他行为的代码控制的系统来模拟。对于要场景物控制的,如果还要借助其动画,其实就跟用正常游戏引擎一样,要在一穷二白的基础上写人物的移动这些基本控制,因为你们大多习惯了mod这种沿用系统本身托管的运动机制,所以熟悉下,如果你在引擎裸奔的情况下,怎么把一个死物处理成一个活物。

看完之后对以下几个不同的生物机械对象的运动及其他行为控制特性和方法展开分析:


研究对象选择:【 (人)、 (马、坦克)】、【(鸟、直升机)、飞机】、【(鱼、潜艇)、船】、炮


看我这样的写法,用(【对这些对象进行了一下运动特性相似程度的分类。

一、首先是对各类对象可以采用的模拟系统:
1、对于正常生活的普通人可采用的系统机制及组合:
(1)纯agent机制(固有机制+模型换皮
(2)场景物机制(像基础引擎一样从0开始写位移动画等事件,需要制作并控制顶点动画)
(3)agent(辅)与场景物(主)联动机制可以隐藏目标agent形态,以场景物的模型外形代表整体的样子,保留利用agent的位移和其他ai行为指导场景物跟随运动、播放顶点动画、攻击等等,这种就看我顶点动画控制章节贴对于我魔兽争霸mod人物的控制例


2、对于马等陆地动物及坦克、鱼、船可采用的系统机制及组合:
(1)纯马机制(多用于与马四肢爬行动物差别较小的对象,固有机制+模型换皮,特殊动物或车类微调骨骼动画,有时结合no dynamic阉割固有机制位移或放开z轴位移限制)
(2)纯agent机制(与马四肢爬行动物差别较大的对象,调整骨骼或微调动画的,有时结合no dynamic阉割固有机制位移或放开z轴位移限制
(3)场景物机制(像基础引擎一样从0开始写位移动画等事件,需要制作并控制顶点动画
(4)agent或马(辅)与场景物(主)联动机制可以隐藏目标agent或马的形态,以场景物的模型外形代表整体控制对象的样子,保留利用agent的位移和其他ai行为指导场景物跟随运动、播放顶点动画等等
(5)agent或马(主)与场景物(辅,多以碰撞形式)联动机制(基本原理和纯agent和纯马机制类似,但是给予碰撞体跟随包裹,比如给马换皮的坦克提供collision类型的真实碰撞体
以上多用于单体模拟,如果是载具含人的多人模拟,还有如下两种机制:
(6)agent或马与场景物多重联动机制(agent或马和场景物在外观显示和运动等机制方面存在一对多,多对一,多对多的混合控制,难分主次,每个部分共同完成对象机制的一部分功能,比如我先用影身的agent控制出坦克/飞机一样的位移行为,再套上一个场景物坦克/飞机的模型,在场景物坦克/飞机的相对位置套上一些副驾驶;或者我纯粹从0编写坦克/飞机移动ai不依靠agent的运动等ai机制,然后再绑定多个agent骑手分工;以及坦克/飞机存在多个可动的零配件等情况

(7)多个agent的多重联动机制(比如https://bbs.mountblade.com.cn/thread-2096142-1-1.html我的骨骼拼接理论,男上加男思想,假如agent拟化为其他生物,再利用dynamic状态控制3d空间运动来构造人骑人或人用人的情况,然后将其中一个人骨骼特殊化为其他生物或武器工具)

3、对于适应不同题材的人可采用的系统机制及组合:
对于真实生活的普通人位移行为比较有限,但是存在于小说影视剧的人位移行为可以说能够囊括
(马、坦克)、【(鸟、直升机)、飞机】、【(鱼、潜艇)、船】、炮这些,进而按照第2点的(1)-(7)思路编写相关位移功能,因为科幻魔幻题材中你作为人可以飞,作为人鱼或者水性好的人可以像船一样水面游也可以潜入深海像鱼像潜艇更可以水上漂直接脚踩步行于水面,然后修仙者的飞行等等空中移动行为,以及允许取消一些正常碰撞判定的限制进行遁地术穿墙术等等。

4.然后对于以上的不同对象不同机制,如何把各个系统对模拟各种对象的运动机制搞好,我们主要的需要掌握的几个代码类控制要点是:


(1)agent与场景物的无障碍运动控制,简称主动运动控制:即move/Rotate的平移旋转与set /animate pos的位移设置,不同dynamic状态对场景物/agent的重力即Z轴运动的限制,agent自身特殊的scripted_destination强制目的地和ai行为的综合,需要掌握各种操作最适宜的场合。


(2)障碍物对agent与场景物运动反馈控制,简称碰撞判定修正运动:即参考对象运动到障碍物是停止还是撞击毁灭还是反弹还是左右上下磨蹭错开出去,以及在地面行走时是像人一样保持与世界oxy平面垂直还是像车一样平行于地面坡面。就像我这个自定义图案阵型系统https://bbs.mountblade.com.cn/thread-2094179-1-1.html提过的,碰撞检测的几种手段之一,除了胶囊的op判断,坐标点集合的距离判断,castray的射线判断,in sight视线范围或者屏幕坐标超出屏幕范围的视线模糊判断,特殊的对地形的高度值ground level获取判断,需要掌握各种操作最适宜的场合。 然后你要记住,碰撞判断是为了干啥的,要么是为了影响运动,要么是为了判断打击范围,所以对于运动修正来说,你需要参考生活实际和你自己的想法,比如人按W键前进蹭到墙上,产生的碰撞判断条件是阻止W键的前进位移量,还是会产生类似AD的左右位移量辅助人物把自己挤出来,还是你的人会飞檐走壁,自动产生z轴向上的位移量,等等。也就是以碰撞判断的条件去改变主动位移控制,加入其他方向的被动位移分量去消弱增强或消失wasd这种主动位移控制的基础效果。
  
(3)最后是一切你觉得这个运动对象应该具备的ai行为对运动的影响:比如攻击开炮是否需要停止位移,攻击行为是自己从0基础重写机制根据位置角度时间计算,还是借助已有agent的ai获取行为指导(类似场景物和agent的视角是否存在关系,是否用agent需要攻击的倾向来触发场景物的add missle或其他行为)等等等等






二、对不同类运动研究对象的动画动作行为对运动的影响分析:
首先对于一切要动起来的对象,基本事件就像我顶点动画系统控制写的那样,无非是idle(待机发呆型动作)、walk/RUN/fly(基础移动类动作)、attack(攻击类动作)、skill(可以是技能也可以是一些技巧动作)、under attack(受到攻击的动作)、death(死亡动作)。
每个基础动作可以一个(比较少)也可以是多个并列级的随机或根据一定条件选择。

运动首先离不开动作和行为事件(有动画的动作是具体的动作,而一些抽象的行为事件引发运动是抽象的动作事件,为什么这么说,你们玩过魔兽争霸编辑器可能就知道,魔兽争霸的触发器就是时间-条件-动作,也就是执行什么行为都叫动作行为,所以对动作这个概念我们也要广义的理解,比如理解为广义的怎么行动。),所以对不同动作事件与运动即位移行为的关联作出分析:


1、对于idle待机动作是很多游戏的对象单体动画动作之起始和中转,无论如何都少不了的动作,就是我在顶点动画控制写的,如果非idle动作的条件结束不能支持其继续执行这个动作行为,那最终会播放完当前动作后会回归idle的循环动作,比如你想想你人攻击后停止按左键以及走路突然不按wasd,是不是就开始自动播放idle站立备战或叉腰类型的等待动作,马也是。这时候idle动作下就会终止研究对象的位移行为。



对于如何主动和被动的终止各种对象的位移,比如人和马这种agent系统,且对于玩家自身的agent控制来讲,按照原有系统你不按wasd或没有障碍物推你或没有跳楼自由落体,你就不会位移。但是如果我要主动控制,某个条件下你在四周开阔脚落地的情况下按了wasd也不准动。这时候你可以靠 agent_set_no_dynamics, ":var_1", 1),这种操作,还有次一点的使用高频的agent_set_scripted_destination和agent set position,但一般不可取,因为agent set position由于人主动转向的系统ai行为与之高频联合运用有的时候会鬼畜原地晃动并影响人碰撞hitbox的判断,agent_set_scripted_destination因为是让ai自由在自己和目的地之间的路径跑,没有强制立即停止自身位移,并且可以被攻击和障碍物再次打退当前位置。
至于为什么我要人和马这种agent系统主动在本应该移动的时候停止移动呢,这种运用场合比较多,比如我要要ai做特定行为时需要保持原位不受wasd按键干扰,以及换皮,没错,就是比如说马换皮坦克,或者马和人影身后设置一个坦克飞机伴随运动时,偷个懒不完全重写ai移动,部分借助agent的运动机制时,根据表象对象即我们需要展示的坦克和内核对象我们辅助运动的agent,之间运动的差别来进行位移阉割,目的是为了屏蔽系统托管的位移控制,加入自己编写的部分新位移控制。这个具体我在下面run动作行为中再展开说。


2. 对于RUN基础移动类动作,虽然上面几个研究对象有海陆空位移能力都占或部分占的,但是如果用主动类位移控制代码来,都大同小异。
对于上下左右前后六向位移来说:

路上跑的最常见,控制最轻巧,且要和
天上飞的对象联系起来看,因为陆地走的和天上飞的两类研究对象最基本的运动特性差别就是向下向上的位移受限的程度,是agent机制的对象想要自由被代码主动控制六向移动可以靠agent_set_no_dynamics操作的dynamic状态+碰撞判定终止一些条件下的位移,如果是场景物机制的对象六向位移本身自由+碰撞判定(包含地面判定,对不会飞的物体)终止一些条件下的位移,比如水里游的,你就是海平面线上wasd等按键控制水平或有限竖直范围(河底到水面)的位移,所以关键是获取水面基础高度或者你可以构造一个prop碰撞面与水面基准重合辅助判定。


但是对对象的位移再次细分,
人和马的基础位移有什么差别:你自己控制时感受感受,人wasd时多数情况速度可以保持差不多,as侧移时不晃动鼠标可以基本保持面向向前的模型姿态来左右移动,而马as侧移的时候你会发现,身体模型需要向侧移的方向有较大幅度的转动,再比对坦克装甲车这种,左右侧移时也不会让它出现保持面向朝前然后左右平移的这种运动,而是要使得整个面向向侧移方向同时旋转运动。并且对于马和车来说运动感受的惯性效果比较明显,以及后退的速度(或后退起步阶段)明显慢于前进时。
所以说为什么要分析这些不同类对象的运动差异,就是本身这些对象在选取agent还是场景物prop系统以及进行换皮组合即以人或马的皮套另一个人或马的运动控制内核,人或马皮套场景物prop的运动控制内核,场景物prop皮套人或马的运动控制内核这三种换皮情况时,怎么考虑屏蔽该运动控制内核默认支持的会导致人不像人、马不像马、车不像车、鸟不像鸟的位移操作,并保留仿人像人、仿马像马、仿车像车、仿鸟像鸟的位移操作。
接下来先进入基础运动控制代码实例分析环节,
对【 (人)、 (马、坦克)】、【(鸟、直升机)、飞机】、【(鱼、潜艇)、船】、炮进行运动代码基础和后续分化的各阶段讲解,因为idle和run,即代表静止和运动的行为,我们学物理都知道,静止是运动的一种特殊状态,运动停了就是静止,所以基础的运动控制必须把运动和静止的关联条件触发写清。
首先研究对象均以prop来模拟这些生物,为什么,因为prop是控制最自由的,默认不会受到碰撞阻力重力作用,所以用prop写出各种对象的运动特征,那么agent运动控制也不再话下,所以下面就算是agent的人我也要夺舍用prop模拟一遍运动控制给你们看看:


首先把我运动总章https://bbs.mountblade.com.cn/thread-2094109-1-1.html贴的第一回复楼的实例2代码拎出来看看,以下是让场景物不受碰撞重力阻力动画控制等限制前提下,可以根据wasd r ctrl这六个按键并结合鼠标晃动的视角转向进行前左右后上下六个方向的匀速位移。然后我示范一下对里面怎么改动,可以把整个代码区分成分别运动行为相似于
【 (人)、 (马、坦克)】、【(鸟、直升机)、飞机】、【(鱼、潜艇)、船】、炮这些不同对象:

  (0.000000, 0.000000, 0.000000,
    [
    ],
    [
  
(get_player_agent_no, ":var_0"),                                #知道为什么都场景物运动了,我还要获取玩家干什么,看下面两个copy rotation了解我的目的
(agent_get_position, pos1, ":var_0"),                     #玩家的坐标,实时获取
(scene_prop_get_num_instances, ":var_10", "spr_dragon"),   #判断spr_dragon这个要控制的场景物有几个,对应下面的只控制刷一个
(try_begin),
    (eq, ":var_10", 0),  
    (set_spawn_position, pos1),
    (spawn_scene_prop, "spr_dragon"),   #以上意思就是spr_dragon数量为0就在玩家的位置pos1刷一个出来,主要就是场景物如果没有事先放置,你就要给刷一个,数量就是控制执行一次的条件。
(try_end),
(eq, ":var_10", 1),  
(scene_prop_get_instance, ":var_1", "spr_dragon", 0),     #飞行的对象就是spr_dragon这个场景物
(prop_instance_get_position, pos2, ":var_1"),     #场景物的坐标,实时获取
#(agent_set_no_dynamics, ":var_0", 1),   #引申做法1: 也就是我前面讲的把agent和prop的运动优势结合。把深蓝字体的#注释去掉,通过场景物影其形,只留其运动控制与agent人之形结合。 这样prop物的自由六向控制就嫁接给了agent人。
#(scene_prop_set_visibility, ":var_1", 0),  #场景物影身
#(agent_set_position, ":var_0", pos2),     #agent和prop位置协同
(try_begin),
    (this_or_next|key_is_down, key_w),
    (this_or_next|key_is_down, key_a),
    (this_or_next|key_is_down, key_s),
    (this_or_next|key_is_down, key_d),
    (this_or_next|key_is_down, key_v),
    (key_is_down, key_left_control),
    (agent_get_look_position, pos4, ":var_0"),
    (position_copy_rotation, pos1, pos4),
(else_try),
    (position_copy_rotation, pos1, pos2),
(try_end),                                                                 #上面这段要配合下面镜头控制前的copy_rotation看,你们玩游戏有没有注意一个细节,就是玩家打人移动时镜头是视角方向,但是如果玩家站立不同,晃动鼠标旋转可以上下查看周身
(try_begin),
    (key_is_down, key_w),                     
    (position_move_y, pos2, 80),         
(else_try),
    (key_is_down, key_a),
    (position_move_x, pos2, -80),
(else_try),
    (key_is_down, key_s),
    (position_move_y, pos2, -80),
(else_try),
    (key_is_down, key_d),
    (position_move_x, pos2, 80),
(else_try),
    (key_is_down, key_r),
    (position_move_z, pos2, 80),
(else_try),
    (key_is_down, key_left_control),
    (position_move_z, pos2, -80),
(try_end),                              #以上是为了让玩家在按r ctrl adws,上下左右前后将场景物的坐标按此方向移动80,但是首先运动时基准角度是玩家的视角方向,这样可以进行俯冲仰冲等等360度无死角自由的多向移动。所以涉及到运动旋转转弯的时候,巧用    (position_copy_rotation, 移动坐标, 视角坐标),的坐标复制十分便捷
(prop_instance_animate_to_position, ":var_1", 2, 5),    最后一个参数速度随你们调,不过我一般直接不写,因为我现在是高频触发,animate的运动效果的均匀化对我前面的位移控制影响不大,但是会降低移动速度,也就是animate不写参数和setpos还是有区别的,不写因为系统0.000触发还有微弱时间间隔。
(try_begin),
    (neg|key_is_down, key_w),
    (neg|key_is_down, key_a),
    (neg|key_is_down, key_s),
    (neg|key_is_down, key_d),
    (neg|key_is_down, key_r),
    (neg|key_is_down, key_left_control),
    (agent_get_look_position, pos3, ":var_0"),
    (position_copy_rotation, pos2, pos3),
(try_end),                                                #这个就是我上面解释的,为了保证玩家运动时镜头平行视角能360度自由飞行,静止时可以晃动鼠标查看周身。
(try_begin),
# (scene_prop_set_visibility, ":var_1", 0),  #将场景物影身
    (position_rotate_x, pos2, 10),      #引申应用2: 游戏摄像机镜头控制功能,假如把深蓝色字体的位移修正代码用#注释禁用,再把浅蓝色的字体代码#注释符号拿掉启用,在场景物的pos2设置摄像机,则场景物位置即为摄像机位置,如果场景物影身或者本身就定义成不具备外表的空模型,那么控制场景物便是控制摄像机镜头
    (position_rotate_z, pos2, -15),
    (position_move_y, pos2, -125),   #数值根据场景物的体型和性质调整
    (position_move_z, pos2, -10),   #数值根据场景物的体型和性质调整
    (position_move_x, pos2, -15),
    (mission_cam_set_mode, 1),   #设为1摄像机将像agent场景物一样自由控制位置,否则就是你们常见的固定在肩部。后面我建议如果该场景物具备飞行和着陆条件,镜头位置应该分开写,因为着陆后的视野会窄一点。
    (mission_cam_set_position, pos2),     #这个是镜头调整,将摄像机调整到主动控制运动的物体身后的某个位置,也就是你希望镜头以第一/三人称观察哪个运动对象,就以哪个运动对象的pos调,最好你们自己重调,因为我后面涉及到这些的mod改太复杂了,应用的对象五花八门不是人,所以这个参数按场景物自身体型大小来调整,一般就是y坐标往后拉,这样可以展现物体整个后部,然后Z上调一点,因为一般物体的pos在自己脚下,比如这个物体是个龙,你至少z要调脑袋高,然后为什么我上面还涉及到旋转呢,因为我这个格斗游戏启发,因为格斗游戏人物身体会侧移,然后呢,空中生物最好视角往身体下方转一下,再左侧转一下,展现生物的部分侧面模型,不然正对后背,飞起来就会感觉有一种固定视角的贴图感觉
(try_end),
    ]),
以上是不考虑碰撞等问题的基础场景物六向位移控制代码,下面根据不同研究对象,对于迫使基础运动状态改变(如被动运动和迫使静止)的条件,对上面代码进行分化改写:



(1),对【 (人)、 (马、坦克)】、【(鸟、直升机)、飞机】、【(鱼、潜艇)、船】、炮 基于地面碰撞和Z轴运动特性进行代码控制条件分化:

i)对于正常的人来说,不应该有Z轴的自由运动(跳跃另行分析先不考虑,可以看作持续时间较短,z轴上下单次简谐运动):
将原始基础控制代码中的:


(try_begin),
    (key_is_down, key_w),                     
    (position_move_y, pos2, 80),         
(else_try),
    (key_is_down, key_a),
    (position_move_x, pos2, -80),
(else_try),
    (key_is_down, key_s),
    (position_move_y, pos2, -80),
(else_try),
    (key_is_down, key_d),
    (position_move_x, pos2, 80),
(else_try),
    (key_is_down, key_r),
    (position_move_z, pos2, 80),
(else_try),
    (key_is_down, key_left_control),
    (position_move_z, pos2, -80),
(try_end),   
(prop_instance_animate_to_position, ":var_1", 2, 5),  
改成为
(try_begin),
    (key_is_down, key_w),                     
    (position_move_y, pos2, 80),         
(else_try),
    (key_is_down, key_a),
    (position_move_x, pos2, -80),
(else_try),
    (key_is_down, key_s),
    (position_move_y, pos2, -80),
(else_try),
    (key_is_down, key_d),
    (position_move_x, pos2, 80),
(try_end),   
  (position_copy_rotation, pos2, pos1),   #pos1在主代码写了是玩家agent的位置,我们要知道对agent的pos来说,获取的坐标其位置始终是平行于OXY世界坐标系平面的,所以对于受重力限制z运动的拟人场景物来说,采用pos2复制一下pos1的角度。或者在我上面主体代码内把复制look pos即视角的copy rotation那句直接替换为复制agent pos的角度
  (copy_position, pos10, pos2),             #我们为了防止可能pos2位移控制坐标被其他判断类位移变换干扰,需要复制一个相同的pos10出来 ,也就是用于判断操作的pos和用于位移操作的pos,最好分开写。            
  (position_get_distance_to_ground_level, ":var_300", pos10),      #获取对象场景物即将运动到的pos地面高度:var_300
(try_begin),
    (ge, ":var_300", 200),                      #如果对象场景物在大于200的高度,即明显悬空,则强制场景物垂直方向向下位移80,模拟自由落体
    (position_move_z, pos2, -80),
(else_try),
  (position_move_z, pos2, 500),     #因为运动延迟或地形建筑等障碍物复杂的碰撞综合条件,要把z往上抬高一点再获取射影到地面的坐标,否则有时意外到地下或者卡在其他碰撞里找ground_level的射影点会干扰位移。
  (position_set_z_to_ground_level, pos2),   #也就是靠近地面高度200以内即没有明显悬空时,强制位移的坐标贴合地面ground_level
try_end),   
(prop_instance_animate_to_position, ":var_1", 2, 5),  

也就是场景物模拟重制的“人”不应该有z轴的自由位移,要让控制自身位置变化形成位移的pos2始终保持在地面上即ground_level。


ii)对于飞机等飞行器以及鸟类等飞行生物以及修仙可以飞的人来说,可以有Z轴的自由运动,但是因为要有落地走动的行为,所以要以一个变量如slot条件来控制飞行和步行的状态切换:
首先不同飞行物的六向位移的平移旋转处理是不同的,比如修仙的人飞行可以像步行一样保持身体和面向都朝北,因为修仙的人不用遵循牛顿定律,同时左/右移动时向东/西移动而不改变身体朝向,即朝向与运动方向可以成直角,但是鸟和飞机却不是这样,由于机体构造和惯性受物理定律限制,身体朝北想东/西移动时,必须先向东/西进行旋转运动使得身体朝向东/西,再附加平移位移。再者,还有的飞行对象就是不按wasd这些基础位移按键也要运动,不然会坠毁,比如飞机和直升机的差别,直升机可以空中悬停一定的位置,你客机也行吗?空中不高速前进就等着坠下去。


不过共性的是,对于地面碰撞判断和Z轴运动状态,基本不同对象的处理模式差不多,所以不考虑朝向与运动的关系时,对于这类对象的地面碰撞判定和z轴运动控制,先将如上基础代码进行以下分化改写:
将原始基础控制代码中的:
(try_begin),
    (key_is_down, key_w),                     
    (position_move_y, pos2, 80),         
(else_try),
    (key_is_down, key_a),
    (position_move_x, pos2, -80),
(else_try),
    (key_is_down, key_s),
    (position_move_y, pos2, -80),
(else_try),
    (key_is_down, key_d),
    (position_move_x, pos2, 80),
(else_try),
    (key_is_down, key_r),
    (position_move_z, pos2, 80),
(else_try),
    (key_is_down, key_left_control),
    (position_move_z, pos2, -80),
(try_end),   
(prop_instance_animate_to_position, ":var_1", 2, 5),  
改成为
(try_begin),
    (key_is_down, key_w),
    (position_move_y, pos2, 80),
(else_try),
    (key_is_down, key_a),
    (position_move_x, pos2, -80),
(else_try),
    (key_is_down, key_s),
    (position_move_y, pos2, -80),
(else_try),
    (key_is_down, key_d),
    (position_move_x, pos2, 80),
(else_try),
    (key_is_down, key_r),
    (troop_set_slot, "trp_player", 300, 1),    #想要向上飞时自动根据slot300值自动切换到飞行模式
    (position_move_z, pos2, 80),
(else_try),
    (key_is_down, key_left_control),
    (troop_slot_eq, "trp_player", 300, 1),  #想要向下飞时自动根据slot300值必须为飞行模式才能使用,否则步行时用了下移会遁地
    (position_move_z, pos2, -80),
(try_end),
  (copy_position, pos10, pos2),                               #我们为了防止可能pos2位移控制坐标被其他判断类位移变换干扰,需要复制一个相同的pos10出来 ,也就是用于判断操作的pos和用于位移操作的pos,最好分开写。            
(position_get_distance_to_ground_level, ":var_300", pos10),      #获取对象场景物即将运动到的pos地面高度:var_300
(try_begin),
    (troop_slot_eq, "trp_player", 300, 0),                         #如果slot300值切到步行模式条件的0值,那么如果对象场景物仍然在大于200的高度,则强制场景物垂直方向向下位移,模拟自由落体
    (ge, ":var_300", 200),
   (position_copy_rotation, pos2, pos1),                           #pos1在主代码写了是玩家agent的位置,我们要知道对agent的pos来说,获取的坐标其位置始终是平行于OXY世界坐标系平面的,所以对于模拟重力垂直下落的运动,采用pos2复制一下pos1的角度。
    (position_move_z, pos2, -80),
(else_try),
    (troop_slot_eq, "trp_player", 300, 1),      #如果slot300值切到飞行模式条件的1值
    (neg|ge, ":var_300", 200),                      #如果距离地面的高度为200,也就是飞行状态非常靠近地面时,   
  (neg|key_is_down, key_r),                    #排除在按上飞位移键R键,为什么?因为如果你结合下面靠近地面200时强制贴着地面运动自动切回步行模式,那么导致我上面写按了按R键可以自动切换飞行模式的条件变成冲突的废物条件了。      
    (position_copy_rotation, pos2, pos1),       #pos1在主代码写了是玩家agent的位置,我们要知道对agent的pos来说,获取的坐标其位置始终是平行于OXY世界坐标系平面的,所以对于受重力限制z轴的步行运动,采用pos2复制一下pos1的角度。
    (position_move_z, pos2, 500),                   #与前面讲的作用一样,防止碰撞条件复杂的时候,用于地面射影位置获取的pos被穿到碰撞体里面,影响判断
    (position_set_z_to_ground_level, pos2),         #得到对象场景物基于自身位置变换的即将到的位移位置pos2,对于地面的射影位置,然后下面控制animate运动时保证此条件下贴着地面运动。
    (troop_set_slot, "trp_player", 300, 0),        #使得靠地面过近但是却没有按上飞R 键的条件下,slot300值切到步行模式条件的0值
(try_end),
(prop_instance_animate_to_position, ":var_1", 2, 5),


所以说对于陆地走的和天上飞的,地面碰撞判断和Z轴运动状态的控制,也就是降落步行和飞天的状态切换控制。

iii)至于不同生物机械在前后左右移动上的的平移旋转模式差异,只需要按照我们的生活观察的常识变动一下按键或其他条件控制的六向基础位移条件:
比如对于爬行动物和鸟之类的左右移动模式可以这样调整;

原始基础控制代码中的:
(else_try),
    (key_is_down, key_a),
    (position_move_x, pos2, -80),

改为
(else_try),
    (key_is_down, key_a),
    (position_rotate_x, pos2, -15),   

    (position_move_y, pos2, 40),     #即按A键将边旋转15度后,边向面向的方向前进40的复合位移,也就是边转动身子边朝面向前进一点点,这种飞行运动时就比较符合鸟,飞机的左右运动模式,步行运动也符合坦克,四只脚的走兽的大部分模式(当然比如老虎不奔跑,慢慢的左右脚交叉左右移动打量猎物时,也是可以做到保持面向和运动方向为直角的情况的),也就是说,也就我们人类行为比较变态,可以保持面向朝前的情况下左右侧移。


又或者飞机的客机类,不像直升机和鸟,你就算不按WASD R ctrl,你已经飞到高空了,就不可以悬停同一个位置不动,也不可能按S键倒着飞行,就必须给一个无位移按键判断即可触发的position move y的基础位移速度,以及屏蔽S键的后退位移行为,然后WS这种前后位移按键只是为了给你的基础飞行速度加速或者减速来用。
等等类似的处理。


iV)此外对于坦克战车这种底盘特别大,不能像人一样直接垂直OXY世界坐标系平面,必须平行于实际地面坡度的,要进行地面坡度检测修正场景物实时放置的位置,一般是这么考虑的,假设按照我前面代码的写法,按照水平位移加set z to ground_level去强制修正位移坐标贴着地形,此时将底盘的大致范围表示出来,假如对于坦克,底盘范围抽象为一个长方形,那么对长方形的四个角点的坐标进行获取得到四个坐标pos,然后方便对四个pos获取与地面ground_level的高差,然后求角度,将角度根据一定运动时间进行除法,得到角运动速度,然后对整个场景物运动的pos,也就是场景物运动后设置自身位置的pos进行修正,比如你前面的地形角度为45度,那么我基础位移代码后面加上修正反向旋转(45度/一定变换时间),以一定变换角速度来修正调控。

V)然后关于水里游的,我们只需要参考陆地走的和天上飞的控制方式,因为水里游的比如像很多船只能底部一定距离贴着水面移动,这个就像人在贴着地面步行一样,只要找到水面的参考高度,参考步行运动处理即可,而对于一些鱼、美人鱼、潜泳以及潜艇来说,可以按照飞行物的飞行控制来模拟,把河床或者你人为设定的最大潜水深度对应的平面为“类比地面”,正常水面运动时浸没深度作为运动对象的“脚部”位置,然后“类比地面”以上到水面的距离类比“飞行高度范围”,然后对河岸以及其他船体礁石等障碍物进行碰撞检测判定修正运动即可。
Vi)对于大炮这种受迫运动(被人推或者被车拉)或者大部分使用的时候只需要旋转角度开火的,主要是一般这种属于多对象复合控制,也就是基本会有agent和其他prop与大炮prop的运动复合影响,所以后面与同类的运动对象一起开一个要点另行分析(或者本贴可以不写,因为这个用例是最多的)

------------------------------------------
未完待续,后面避免帖子过长,,写回复楼层里,然后对于我贴的代码实例,部分数据不一定准确,你们自身试验,因为我mod里的代码功能太集中写了,不方便从里面剥离单个功能出来,所以就在txt里随手写了下,像这个速度多少合适,镜头放在什么位置好这种xyz的取值,这个你们要根据具体的对象试验的时候反复调调,怎么顺眼怎么来。















评分

参与人数 2荣誉 +1 第纳尔 +70 互助 +2 魅力 +20 收起 理由
Aomine Daiki + 50 + 20 您的帖子很有价值!
muyiboy + 1 + 20 + 2 原创内容,值得鼓励!

查看全部评分

202

主题

984

回帖

986

积分

子爵[版主]

Rank: 7Rank: 7Rank: 7

UID
2893127
第纳尔
14521
精华
0
互助
90
荣誉
18
贡献
325
魅力
775
注册时间
2017-11-5
鲜花(428) 鸡蛋(0)
 楼主| 发表于 2023-1-10 09:38:46 | 显示全部楼层
本帖最后由 vegetto 于 2023-1-12 09:32 编辑

------------------------------
(2),对【 (人)、 (马、坦克)】、【(鸟、直升机)、飞机】、【(鱼、潜艇)、船】、炮 基于非地面地形类的场景物类型生成的障碍物的碰撞检测对运动的影响修正进行代码控制条件分化:
对于我们第(1)的地面碰撞检测来说,基本可以满足在野战场景里没有其他场景物类型的障碍物的运动,但是你既然用了场景物运动控制,就保不齐场景里有带碰撞体的场景物ai在运动比如战车坦克飞机,以及带场景物碰撞的其他军事障碍物比如堡垒沙包工事,以及战团原生的比较大的树木和石头。再者如果去攻城呢,又是大量建筑物,所以,对于碰撞判定对运动控制的影响及修正,我们仅仅来判断地面检测是不够的,还需要进行常规的障碍物碰撞判定。所以本要点(2)的内容就是对各种运动研究对象基于我上面的基础运动控制代码进行常规的障碍物碰撞判定的分化改写。
未完待续,最近贴发太多有点写累了,毕竟我要讲的很多不是常规mod要用的东西。你们先看下我下面两个帖子的实例,了解最通用的非地形碰撞检测判定方法
场景物运动辅助及碰撞的妙用之制作自动生成复杂图案阵型系统https://bbs.mountblade.com.cn/thread-2094179-1-1.html


场景物运动控制模拟技能案例--混沌陨石(代码):https://bbs.mountblade.com.cn/thread-2096150-1-1.html

就比如我阵型系统回复层写的:最后给你们总结的是:几种思维和处理方法。
1.注重模型手段和程序手段的结合。
2.借助场景物运动控制的便利,可以辅助agent人和particle粒子等其他系统进行更平滑更好的位移控制,并且我们记录坐标并不一定要知道XYZ值,像人和场景物都有自己的位置坐标,并且可以通过自身的位移来表达位置坐标的改变,这时候我们就可以化抽象为具体,将抽象的xyz值的坐标以场景物人等等的实物形式来持久保留和实时平稳控制。
3.碰撞检测的几种手段之一,除了胶囊的op判断,坐标点集合的距离判断,castray的射线判断,in sight视线范围或者屏幕坐标超出屏幕范围的视线模糊判断,特殊的对地形的高度值获取判断,还有就是利用:
(position_get_distance_to_ground_level, ":var_19", pos2),      #判断位置点下方的高度,此高度是计算下方的场景物碰撞点为高度h=0点
                    (position_get_distance_to_terrain, ":var_20", pos2),                  #判断位置点下方的高度,但是此高度是不计算下方的场景物碰撞点,以随机地形网格生成的最高地形点为高度h=0点
                    (store_sub, ":var_21", ":var_20", ":var_19"),                #将两个高度值作差值
这种方式求差值,了解高空同一点下方是否存在prop的collision形式的碰撞体,这样比如差值是十几米,可能碰撞体在野战就是坦克,差值几十米,可能在攻城战就是 城墙,这样对不复杂场景做复杂场景物运动功能时进行一个高效不卡相对模糊快速的碰撞判定,然后做出相应的碰撞后运动反应。
这些经验。
因为碰撞是一个情况比较多的东西,如果你假设周边碰撞都是固定不动的平面,那么最直接的方法,可以cast ray判定一定距离有碰撞,然后对wasd按键的位移条件进行屏蔽或者加一个可以避开碰撞的位移,
但是实际上遇到的碰撞体样式是多种多样,可静可动的。
比如你的碰撞是一个网状的格栅(一般这种碰撞体做的时候会做成平面也不会有什么影响)或碰撞体中间带大孔洞的比如涵洞,那么cast ray对精度要求上来需要多向多射线,否则直接穿孔测不到碰撞。
胶囊的op判断即prop_instance_intersects_with_prop_instance,对碰撞体的形状有要求,所以注定不是通用的判定手段,一般用于两个特定具有运动能力的对象。
而in sight视线类用法也会有局限且性能和精度上不适合通用ai。然后就是碰撞体存在运动时的判断延迟,特别是两个碰撞体相撞运动时互相磨蹭这种情况,对碰撞检测的精度要求更高,以及两个墙形成的90度夹出的墙角,顶部带突出的屋檐类碰撞外形,等等等等,导致你碰撞判定的时候,你不仅要考虑对当前位移方向即将遇到的碰撞产生的位移影响,还要根据影响位移去规避绕开碰撞后的复合运动去判断可能强制改向后的碰撞检测方向的调整,就需要各种综合条件综合手段去判断,否则在一个形状不是方方正正的、竖立面此起彼伏具有空洞或被碰撞体环绕的空间内、以及多个运动类物体碰撞遇到一起(比如8辆车同时像花瓣一样头部顶到一起,互相之间怎么让)等等复杂的场景环境,就免不了突然穿墙的可能。


其次,场景物自身是否含有较大碰撞体以及自身的尺寸大小也是对此类代码编写的复杂程度的影响因素之一,比如人这种运动特征的小型生物,碰撞检测就比较简单,就像我上面地面检测一样,因为人的运动位置点可以等效一个点,而坦克之类的机械需要等效一个平面;人的横向尺寸较小对周边障碍物检测时可以等效半径较小的圆柱体去考虑,这样对形体周边的任意检测点可以近似相等,但坦克这些庞然大物却要考虑自身复杂的多边形外形碰撞,以及选取合适的模型中心(即prop instance get pos以模型上哪个点为参考)(比如你坦克的pos在openbrf里是两个前轮的中心为原点还是两个后轮中心还是底盘中心,这个中心点选取,不仅对碰撞,对你的运动该怎么平移旋转修正都是有影响的),这个中心点pos和其碰撞外形各边角点的不同距离都会让你在判断不同方向上运动时的碰撞检测时需要分别分析设置合理的位移修正数值。以及部分碰撞判定手段还有对检测到的环境碰撞会不会可能是自身的情况做出判定和规避,就像我混沌陨石代码里写的,你用ground level还是cast ray,对于自身拥有坦克船体一样大的物体来说,有时你不能保证你检测到的碰撞是不是就是自己的,因而采用这种碰撞手段时就要考虑把碰撞检测的参考位置移到有效形体碰撞的边缘外,所以这也是形体大小的影响。
当然形体大小对碰撞检测精度的影响,并不是要求我们完全不穿模,而是不无限制的“穿墙”,穿模这种东西在骑砍2也不能避免,这个根据不同对象的形体大小和不同的制作者,有个穿模的最大容忍度即可,比如人就是比较小的生物,手稍微穿到墙里不要紧,最怕身体运动时陷到墙内1/3以上,甚至发生大穿模现象时,向碰撞内运动已经突破碰撞检测的条件,继续穿直至穿出碰撞面。或者坦克,我稍微一点板甲陷入墙里蹭到短时间不要紧,因为一个运动的碰撞面和凹凸不平的碰撞面来回挤压本身对检测精度较高,除非检测距离拉长,让坦克远远的距离障碍物就禁止再往障碍物方向移动。所以考虑时,一般你可以考虑是否需要一个安全保护距离,对周围障碍物有明显靠近的距离时就阻止这个方向的位移。比如飞机,按道理你撞墙和山会撞毁,所以这时候,你的设定可以考虑你明知道前面有山,还是按W前进,那直接撞毁吧,或者内定一个安全保护距离,假如按W前进时,前面检测到100米有个大山,那么你按W一般情况产生的move y位移就自动修正,加上如rotate x的位移,添加系统辅助帮助玩家傻瓜式自动规避碰撞。

所以一个完美的基于场景物制作的机械类生物类运动对象,目前应用的均不是尽善尽美,当前少数应用到的mod仅仅只能保持自己在海面野战这种建筑等障碍物场景物不多的情况下编写。


所以就实际应用来说,完美制作应用各类场景的模拟运动的这种一劳永逸的努力方向建议不要进行研究,将特殊机制应用特殊任务的特殊场景化会更好一点,比如飞机坦克特定在某战役场景野战等等,而对于修仙能飞的人这种可以忽略自身碰撞影响的对象来说,可以考虑多场景的通用化,可以agent和prop系统结合起来用,针对不同情形具体分析,比如步行多借助agent系统控制,飞行多借助prop系统控制,这样有合有分的编制手段。


这个具体的用例,我想想,我打算后面给你们两个我的用例作为参考,一个是我魔兽争霸mod的四大种族的飞行单位战车的机制做法(这个是我自己对ai怎么尽可能节省资源去应用顶点动画场景物运动的做法),一个是我刺客伍六七mod的飞檐走壁做法(基本完美适应各种奇形怪状的房子等立面),时间关系先不写,后面未完待续







15

主题

739

回帖

366

积分

子爵[版主]

汉[Han]
联机ID:Han_DongHai

Rank: 7Rank: 7Rank: 7

UID
3033293
第纳尔
10330
精华
0
互助
24
荣誉
2
贡献
360
魅力
184
注册时间
2018-10-3

第十届战团中国联赛征战勋章汉匈决战正版勋章战团正版勋章霸主正版勋章

QQ
鲜花(37) 鸡蛋(0)
发表于 2023-1-10 10:25:17 | 显示全部楼层
挺好的,老彼得.

0

主题

53

回帖

21

积分

随仆

Rank: 1

UID
3110714
第纳尔
454
精华
0
互助
1
荣誉
0
贡献
0
魅力
0
注册时间
2019-10-8
鲜花(6) 鸡蛋(0)
发表于 2023-1-27 03:21:56 | 显示全部楼层
顶顶顶,整活到底!!

9

主题

70

回帖

24

积分

随仆

Rank: 1

UID
2804669
第纳尔
182
精华
0
互助
0
荣誉
0
贡献
0
魅力
0
注册时间
2017-2-6
鲜花(6) 鸡蛋(0)
发表于 2023-1-29 19:45:18 来自手机 | 显示全部楼层
LZ辛苦了,虽然看不懂还是顶了,问大家个问题,编辑器里的动物用来做啥的,还有角色特性的skin2到skin15是怎么改的,我改了skin.txt但是没效果都是大个头女的。

30

主题

200

回帖

169

积分

见习骑士

Rank: 3

UID
2462463
第纳尔
1472
精华
0
互助
20
荣誉
0
贡献
0
魅力
50
注册时间
2015-3-3
鲜花(43) 鸡蛋(0)
发表于 2023-2-10 16:11:17 | 显示全部楼层
大佬,骑砍能做汽车吗?就把攻城车的模型拿出来,让轮子自己转起来

202

主题

984

回帖

986

积分

子爵[版主]

Rank: 7Rank: 7Rank: 7

UID
2893127
第纳尔
14521
精华
0
互助
90
荣誉
18
贡献
325
魅力
775
注册时间
2017-11-5
鲜花(428) 鸡蛋(0)
 楼主| 发表于 2023-2-10 20:25:54 来自手机 | 显示全部楼层
本帖最后由 vegetto 于 2023-2-10 20:33 编辑
战争傀儡阿格兰 发表于 2023-2-10 16:11
大佬,骑砍能做汽车吗?就把攻城车的模型拿出来,让轮子自己转起来


https://share.mountblade.cn/wap/thread/view-thread/tid/2094063/share_user_id/2893127
我的魔兽争霸mod四大种族战车滚动动画和摧毁动画
20230210202529front1_0_2893127_Fkj3jmQ8wrOD7qC4ALYRkuNgmQnR.gif
20230210202529front1_0_2893127_FqFCf8-k4AoDvqujJ84Wo-2jMAZp.gif
20230210202529front1_0_2893127_FvxZgx55cfjC0ybA0rOeKnaEs-pO.gif
20230210202529front1_0_2893127_FpFWreofoFzuZXvde6_tjxpY19Zw.gif
20230210202530front1_0_2893127_FiLXmQkx18HY4ZNn9ZVwj-6gnskx.gif
20230210202531front1_0_2893127_FjbkW3899tkFZ2R37G7OGE8sHc1W.gif

来自: iPhone客户端

202

主题

984

回帖

986

积分

子爵[版主]

Rank: 7Rank: 7Rank: 7

UID
2893127
第纳尔
14521
精华
0
互助
90
荣誉
18
贡献
325
魅力
775
注册时间
2017-11-5
鲜花(428) 鸡蛋(0)
 楼主| 发表于 2023-2-10 20:39:22 来自手机 | 显示全部楼层
战争傀儡阿格兰 发表于 2023-2-10 16:11
大佬,骑砍能做汽车吗?就把攻城车的模型拿出来,让轮子自己转起来

以及做过变形金刚功能
20230210203906front1_0_2893127_FsEep6v6HcvbfBZJhBDKZDeZV8ds.gif
20230210203903front1_0_2893127_FuUkzl2yJXG-ZByAJXtEhdBc7cEk.gif
20230210203902front1_0_2893127_FjWsmvLijZG59gsKAB7F1oaTYWvK.gif
20230210203903front1_0_2893127_FglAKIFKSfvKr6FR39JbsGeb70jP.gif
20230210203902front1_0_2893127_FrwBYbc7XM8mO64yNjCcdKGzB709.gif
来自: iPhone客户端
您需要登录后才可以回帖 登录 | 注册(Register!)

本版积分规则

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

GMT+8, 2024-4-19 12:18 , Processed in 0.138788 second(s), 29 queries , Gzip On, MemCached On.

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.

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