“虚拟世界/Vehicles”的版本间的差异
(创建页面,内容为“{{VWScript}} == 概述 == 虽然虚拟世界包含物理引擎,LSL包含许多用于控制对象物理行为的功能,但还是有一个用于控制车辆的…”) |
|||
第1行: | 第1行: | ||
− | {{ | + | {{VWSnav}} |
== 概述 == | == 概述 == |
2024年8月23日 (五) 08:43的最新版本
百科首页 - 3D虚拟世界 - 音乐与人工智能 - 人工智能机器人 - 知识百科 - 关于我们 - 网站首页
脚本首页 | Vehicles | NPC | HTTP | 脚本间通信 | 翻译参考
概述
虽然虚拟世界包含物理引擎,LSL包含许多用于控制对象物理行为的功能,但还是有一个用于控制车辆的独立API。本页将介绍车辆工作原理,描述车辆时使用的术语以及对可用API进行更详尽的说明。此功能足够灵活,可以制作滑动,悬停,飞行和浮动的工具。一些自动化的行为是:
- 线性和角速度偏转到优选的运动轴
- 不对称的线性和角度摩擦
- 盘旋在地形/水上或全球高度
- 轮流上飞行偏转
- 线性和角度电机用于推动和转动
每个脚本对象都可以有一个车辆行为llSetVehicleType,它可以通过llSetVehicleFloatParam,llSetVehicleVectorParam,llSetVehicleRotationParam,llSetVehicleFlags和llRemoveVehicleFlags库调用进行配置。这些API调用在下面更详细地描述,但是需要注意的是,车辆行为具有可以调整以改变车辆处理方式的多个参数。根据所选择的值,车辆可以像小船一样在水中转向,或者像滑轨上的雪橇一样骑行。设置车辆标志允许您对某些默认行为进行例外。其中一些标志仅在启用某些行为时才起作用。例如,VEHICLE_FLAG_HOVER_WATER_ONLY将使车辆忽略地形的高度,但只有在车辆悬停时才会有所不同。
设置车辆类型
- 在可以设置任何车辆参数之前,必须首先启用车辆行为。它通过调用llSetVehicleType和任何VEHICLE_TYPE_ *来启用,除了VEHICLE_TYPE_NONE将禁用车辆。查看当前可用的车辆类型可参照相关API中的llSetVehicleType部分。
- 设置车辆类型对于启用车辆行为是必要的,并将所有参数设置为默认值。对于列出的每种车型,我们提供长格式的相应等效代码。重要的是要认识到,默认值不是任何这些车型的最佳设置,并且它们将来肯定会改变。在指定之前,不要依赖这些值。
- 如果您想制作一辆独特的或实验性的车辆,您仍然必须首先使用其中一种默认类型启用车辆行为,之后您将能够更改允许范围内的任何参数或标志。
- 设置车辆类型后交通工具不会自动控制或移动。但是,如果在物体启用车辆行为后停放在山上时,那么它可能会开始滑落。
线性和角度偏转
- 真实车辆的一个共同特征是它们倾向于沿着一个特定的轴运动。也就是说,由于它们的车轮、机翼、外形或推进方法,这个轴相对于交通工具本身是静止的。这个基本特征定义了一类车辆,在这个类别中包括一个最为普通的“车辆”:它背后有鳍片,如果它在空中翻滚,它最终会调整自身以向前移动 - 我们称这种对齐效应为“角偏转”。轮式飞行器表现出不同的效果:当物体沿某个方向被推动时,它会倾向于将合成运动沿着其自由滚动的方向重定向 - 我们称之为“线性偏转”。
- 因此,典型的虚拟世界车辆是沿着特定的轴呈现线性或角度偏转的物体。默认的运动优先轴是:本地的x- 、y-和z-轴。偏转行为与x轴有关:线性偏转会倾向于旋转它的速度,直到它沿着它的正局部x轴旋转,而角偏转会倾向于使车辆重新定位,使其x轴指向它所移动的方向。其他轴的偏转与后面描述的车辆行为有关,例如试图使车辆的局部z轴指向世界z轴的引力。交通工具的轴可以利用参数VEHICLE_REFERENCE_FRAME来改变物体的本地轴,可参见相关API部分llSetVehicleFloatParam。
- 根据车辆的不同,可能会需要或不需要有大量的线性或角度偏转。通过使用llSetVehicleFloatParam脚本调用设置相关参数来控制偏转的速度。每种偏转都有一个“时间刻度”参数,用于确定发生完全偏转的速度。
- 基本上,时间刻度是指数衰减到完全偏转的时间系数。换句话说,一个时间尺度较小的车辆会迅速转向。例如,典型的车辆可能具有几秒钟的角度偏转时间,但会有几秒钟的线性偏转。 它会在它改变方向之前重新定位自己。要设置车辆的偏转时间时间,您可以使用以下几行:
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 2.0); llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 6.0);
- 每种类型的偏转都有一个“效率”参数,它是介于0.0和1.0之间的滑块。与其他车辆行为的其他效率参数不同,偏转效率不会在“有弹性”和“阻尼”之间滑动,而是从“无偏移”(0)到“最大偏移”(1.0)。也就是说,它们的表现非常像偏转时间标尺,但它们被标准化为0.0到1.0之间的范围。
移动车辆
- 启用车辆后,车辆可以通过外力或脚本调用(如llApplyImpulse)进行推动和旋转,但若是内置了线性和角度电机,可以使运动更轻松,更平滑。车辆的方向可以使用llSetVehicleVectorParam调用来设置。例如,要使车辆沿着其本地x轴(默认的查看方向)以5米/秒的速度移动,可以在脚本中放入以下行:
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <5, 0, 0>);
- 为了防止车辆移动过快,线性电机的大小被限制在不超过30米/秒的范围内。请注意,这主要是因为物理引擎的限制,可能在以后可能会提高。
- 设置电机速度不足以实现所有目标效果的车辆。例如,有些人想要一辆能立即达到他们想要的速度的汽车,而另一些人则想要一艘缓慢上升到最大速度的船。为了控制这种效果,您可以设置VEHICLE_LINEAR_MOTOR_TIMESCALE参数。
- 基本上,电机的“时间尺度”是车辆以指数级加速到全速的时间常数。
- 如果您意外地将车辆的线速度设置为最大可能的速度然后放手,会发生什么情况?它会移动并永不停止?不会这样的,默认建立了一个自动的“电机衰减”机制,以便所有电机在设置后都会逐渐降低其有效性。
- 每次设置线性电机矢量时,其“抓地力”立即开始以VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE确定的时间范围内呈指数衰减,这样在足够的时间之后,电机将不再有任何效果。这种衰减时间尺度有两个目的。首先,由于它不能设置长于120秒,并且始终启用,所以它保证在没有主动控制的情况下(从键盘命令或脚本中的某个逻辑循环),车辆不会永远推动自己。其次,它可以用一个简单的脉冲模型来推动一些车辆。也就是说,不是根据特定的键是按下“down”还是“up”来将电机设置为“on”或“off”,可以将衰减时间刻度设置得较短,而是只要按键将电机设置为“on”就可以实现从“up”到“down”的转换,并允许自动衰减。
- 由于电机的有效性在电机的矢量设置时会被重置,因此将其设置为长度为零的矢量与允许其衰减完全不同。第一种情况会导致车辆试图达到零速度,而第二种情况会使电机无效。
- 两个电机时间尺度名称非常相似,但具有不同的效果,因此请尽量不要让它们混淆。VEHICLE_LINEAR_MOTOR_TIMESCALE是电机“赢”的时间,VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE是电机“有效”向零衰减的时间。如果电机的衰减时间尺度比正常时间尺度短,那么电机矢量的有效幅度将会减小。
驾驶车辆
- 就像直线电机一样,还有一个始终打开的角度电机,其方向和大小可以设置。例如,要使车辆在其本地z轴(上轴)周围以5度/秒旋转,可以将以下几行添加到其脚本中:
vector angular_velocity = <0, 0, 5 * DEG_TO_RAD>; llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_velocity);
- 角度电机的大小被限制在不超过每秒两转(4 * PI弧度/秒)。与线性电机一样,它具有一个效率参数VEHICLE_ANGULAR_MOTOR_TIMESCALE和一个电机衰减参数VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE,默认设置为最大可能值120秒。
- 在驾驶车辆时,您可能不希望它转得很远或很长。有两种方法可以解决。一种是使用角度电机的方法,将衰减时间尺度保持较长,使得大量角度摩擦(当电机关闭时快速减慢车辆速度),然后将角度电机设置为按键,并在释放按键时将其设置为零。另一种方法是,将车辆的角度设置为一个较短的值,并以一种更加脉冲的方法推动车辆,使得电机快速按下按键(并且可选择地将电机设置在按键上的零),依靠自动指数衰减电机的有效性,而不是恒定的角度摩擦。
- 将角度电机设置为零不同于允许其衰减。当电机完全衰减时,不再影响车辆的运动,但将其设置为零将重置车辆的“抓地力”,并使车辆尝试实现零角速度。
- 对于某些车辆,可以使用“倾斜功能”进行转向。“倾斜功能”是飞机和摩托车在转弯时所做的。当一辆倾斜车辆绕其横滚轴旋转时,围绕其偏航轴线产生合力旋转。倾斜功能只有在使用下面描述的“垂直吸引器”时才可用。
引力
- 有些车辆,如船只,应始终保持正面朝上。这可以通过启用“引力”功能来完成,该功能将车辆的本地z轴保持与世界z轴一致。要利用此功能,您可以设置VEHICLE_VERTICAL_ATTRACTION_TIMESCALE来控制引力触发的频率,然后设置VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY来控制阻尼。0.0的效率将导致弹簧绕其平衡摆动,而1.0的效率将导致弹簧达到其指数衰减的平衡。
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 4.0); llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.5);
- 将垂直吸引器的时间尺度设置为大于500秒的时间即可禁用。
- 请注意,默认情况下,引力将禁止车辆潜水和攀爬。因此,如果您想制作飞机,您可能需要通过设置VEHICLE_FLAG_LIMIT_ROLL_ONLY位来开启俯仰轴的引力因子:
llSetVehicleFlags(VEHICLE_FLAG_LIMIT_ROLL_ONLY);
飞行倾斜
- 必须启用引力功能才能使飞行倾斜功能发挥作用。飞行倾斜功能的工作方式是这样的:围绕车辆侧倾轴线的旋转将产生围绕偏航轴线的角速度,导致车辆转弯。偏航效应的大小将与VEHICLE_BANKING_EFFICIENCY(侧倾旋转的角度)成正比,有时会与沿着其首选运动轴线的车辆速度有关。
- 所述VEHICLE_BANKING_EFFICIENCY可以在-1和+1之间变化。当它为正值时,围绕横摇轴线的任何正向旋转(通过右手定则)将在横摆轴线周围产生(负)扭矩,使其转向右侧,即车辆将倾斜进入转向。否定倾斜系数会使车辆倾斜到转弯外。
- 该VEHICLE_BANKING_MIX通过充当相应完全静态(0.0)和完全动态(1.0)的倾斜功能之间的滑块,实现了现实和非现实倾斜功能的组合。通过“静态”我们的意思是倾斜效应只取决于车辆围绕其滚动轴线的旋转,而“倾斜功能”也与其沿滚动轴线的速度成正比。找到“混合物”的最佳值可能需要反复试验。
- 倾斜行为在世界z轴上的达到先前存在的角速度所需的时间由VEHICLE_BANKING_TIMESCALE确定。因此,如果你希望车辆能够快速倾斜,那么可以给它一个约1秒钟或更短的倾斜时间表,否则你可以通过给它一个几秒钟的时间尺度来制造一辆呆滞的车辆。
摩擦时间尺度
- VEHICLE_LINEAR_FRICTION_TIMESCALE是一个矢量参数,用于定义车辆沿车辆参考系的三个局部轴完全停止的时间标尺。沿着每个轴的时间尺度与其他时间尺度无关。例如,滑动的地面车辆可能沿着其x轴和z轴具有非常小的摩擦(因此它可以容易地向前滑动并且向下滑动),而沿着其y轴通常会存在显着的摩擦:
llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1000, 3, 1000>);
- 请记住,较长的时间尺度对应于较弱的摩擦,因此要有效地禁用所有线性摩擦,您需要将所有时间尺度设置为较大的值。
- 将线性摩擦设置为标量是允许的,并且具有将所有时间标度设置为相同值的效果。下面的两个代码片段都是等效的,并且两者都使得摩擦可以忽略不计:
// set all linear friction timescales to 1000 llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1000, 1000, 1000>); // same as above, but fewer characters llSetVehicleFloatParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, 1000);
- VEHICLE_ANGULAR_FRICTION_TIMESCALE是定义为车辆停止绕x轴,y轴和z轴的时间尺度一个向量参数,同线性摩擦力一样,以相同的方式进行设置与和禁用行为。
浮力
- 车辆具有独立于llSetBuoyancy的内置浮力功能。建议不要混淆两者!为了使车辆能够漂浮,请将VEHICLE_BUOYANCY参数设置为0.0(无浮力)和1.0(完全反重力)之间的某个值。
- 使用VEHICLE_FLAG_HOVER_UP_ONLY标志时,浮力行为不独立于悬停。当浮力、悬停和VEHICLE_FLAG_HOVER_UP_ONLY一起使用时,当车辆高于悬停高度时,浮力效果消失。也就是说,你期望车辆在悬停高度以上漂浮,但事实并非如此。这不是在设计上,而是一个长期存在的bug,它不能再被改变——它会破坏大量无意中依赖这种行为的内容。
- 您可以将车辆浮力与llSetBuoyancy脚本调用混合使用,这是一项独立的功能。在某些情况下,您可能会得到大于1的净浮力效果,并且您将有一个物体在不停止的情况下加速。试验需要您自担风险。
悬停
- 通过将VEHICLE_HOVER_TIMESCALE设置为小于300秒的值来启用悬停行为,更大的时间尺度将完全禁用它。大多数车辆设置在几秒或更短时间的悬停时间工作效果最佳。时间范围越短,车辆越快达到目标高度。请注意,VEHICLE_LINEAR_FRICTION_TIMESCALE的值可能会影响悬停的速度。
- 悬停与浮力无关,但VEHICLE_BUOYANCY应设置为1.0,否则车辆将不会从地面抬起,直到VEHICLE_HOVER_HEIGHT大到足以抵消重力加速度,并且车辆永远不会浮动到其目标高度。
- VEHICLE_HOVER_EFFICIENCY可以被认为是控制悬停效率有弹性的(0.0)和平滑(1.0)之间的滑块。当在有弹性范围内时,车辆将倾向于稍微低于其目标高度,并且VEHICLE_HOVER_TIMESCALE将近似于反弹的振动周期(实际周期将倾向于比时间刻度稍长)。
- 出于性能方面的原因,车辆只能悬停在地形和水面上,它们无法悬停在基元(如桥梁和房屋)之外的物体上方。默认情况下,悬停行为将浮在地形和水面上,但可以通过设置一些标志来更改:如果你想制作一艘船,你应该设置VEHICLE_FLAG_HOVER_WATER_ONLY标志,或者如果你想在水下驾驶一个悬停坦克,你可以使用VEHICLE_FLAG_HOVER_TERRAIN_ONLY标志。最后,如果你想制作潜艇或气球,你可以使用VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT。
- VEHICLE_HOVER_HEIGHT确定车辆悬停在地形或水上将有多高,或全局的高度,并具有100米的最大值。请注意,为了悬停目的,车辆的“中心”是其“质量中心”,当用户化身坐在车辆上时它会改变。
- 请注意,这些标志是相互独立的,并且设置两个相互矛盾的标志将具有未定义的行为。这些标志使用llSetVehicleFlags脚本调用进行设置。
相关API
llSetVehicleType
函数:llSetVehicleType(integer type)
- integer type – VEHICLE_* flag
常量 | 中文说明 | 描述 | |
---|---|---|---|
VEHICLE_TYPE_NONE | 车辆类型无 | 0 | 关闭车辆支持 |
VEHICLE_TYPE_SLED | 车辆类型的雪橇 | 1 | 简单的车辆,沿地面颠簸,并喜欢沿着其x轴方向移动 |
VEHICLE_TYPE_CAR | 车辆类型的车 | 2 | 沿着地面反弹的车辆,但需要设置驱动以及control和timer事件 |
VEHICLE_TYPE_BOAT | 车辆类型的船 | 3 | 盘旋在有大量摩擦和角度偏转的水面上 |
VEHICLE_TYPE_AIRPLLANE | 车辆类型的飞机 | 4 | 使用线性偏转进行升降,无悬停和银行转机 |
VEHICLE_TYPE_BALLOON | 车辆类型的气球 | 5 | 有悬停和摩擦,但没有偏转 |
功能:设置车辆类型为默认车辆类型中的一种。
例子
llSetVehicleType(VEHICLE_TYPE_SLED);//设置为简单车辆
llSetVehicleRotationParame
函数:llSetVehicleRotationParam(integer param, rotation rot)
- integer param – VEHICLE_* flag
- rotation rot
常量 | 中文说明 | 描述 | |
---|---|---|---|
VEHICLE_REFERENCE_FRAME | 车辆参考系 | 44 | 车辆轴线相对于本地坐标轴的旋转 |
功能:将车辆的旋转参数设置在param到rot之间。
例子
llSetVehicleRotationParam( VEHICLE_REFERENCE_FRAME, ZERO_ROTATION);//设置为零偏转
llSetVehicleVectorParam
函数:llSetVehicleVectorParam(integer param, vector vec)
- integer param – VEHICLE_* flag
- vector vec
常量 | 中文说明 | 描述 | |
---|---|---|---|
VEHICLE_ANGULAR_FRICTION_TIMESCALE | 车辆摩擦角时间表 | 17 | 关于三个车轴的角速度指数衰减的时标矢量 |
VEHICLE_ANGULAR_MOTOR_DIRECTION | 载体角运动方向 | 19 | 车辆试图实现的角速度 |
VEHICLE_LINEAR_FRICTION_TIMESCALE | 车辆的线性摩擦时间尺度 | 16 | 三个车轴线速度呈指数衰减的时间尺度矢量 |
VEHICLE_LINEAR_MOTOR_DIRECTION | 车辆直线电机方向 | 18 | 车辆将尝试实现的线速度 |
VEHICLE_LINEAR_MOTOR_OFFSET | 车辆直线电机抵消 | 20 | 从施加线性电动机的车辆的质量中心偏移 |
功能:将车辆的矢量参数param设置为vec。
注意:VEHICLE_ANGULAR_MOTOR_DIRECTION可能与根物体中设置的任何活动llTargetOmega相冲突并阻止车辆转弯。故调用llTargetOmega时设置VEHICLE_ANGULAR_MOTOR_DIRECTION值为0而将其禁用。
llSetVehicleFloatParam
函数:llSetVehicleFloatParam(integer param, float value)
- integer param – VEHICLE_* flag
- float value
常量 | 中文说明 | 描述 | |
---|---|---|---|
VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY | 车辆角度偏移效率 | 32 | 介于0(无偏差)和1(最大强度)之间 |
VEHICLE_ANGULAR_DEFLECTION_TIMESCALE | 车角偏转时间表 | 33 | 指数时间刻度车辆实现全角度偏转 |
VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE | 车辆角运动衰减时间 | 35 | 指数时间刻度角电机的有效性衰减到零 |
VEHICLE_ANGULAR_MOTOR_TIMESCALE | 车辆角运动时间表 | 34 | 指数时间刻度车辆实现其全角电机速度 |
VEHICLE_BANKING_EFFICIENCY | 车辆倾斜效率 | 38 | -1(倾斜转弯),0(无银行)和+1(转弯) |
VEHICLE_BANKING_MIX | 车辆倾斜混合 | 39 | 介于0(静态倾斜)和1(动态倾斜)之间 |
VEHICLE_BANKING_TIMESCALE | 车辆倾斜时间表 | 40 | 倾斜行为能够充分发挥作用的指数时间表 |
VEHICLE_BUOYANCY | 车辆浮力 | 27 | 介于-1(双重引导)和1(完全反引力)之间 |
VEHICLE_HOVER_HEIGHT | 车辆悬浮高度 | 24 | 车辆将尝试悬停的高度 |
VEHICLE_HOVER_EFFICIENCY | 车辆悬浮效率 | 25 | 介于0(弹性)和1(临界阻尼)悬停行为之间 |
VEHICLE_HOVER_TIMESCALE | 车辆悬浮时间尺度 | 26 | 车辆达到悬停高度的时间段 |
VEHICLE_LINEAR_DEFLECTION_EFFICIENCY | 车辆线性偏转效率 | 28 | 介于0(无偏差)和1(最大强度)之间 |
VEHICLE_LINEAR_DEFLECTION_TIMESCALE | 车辆线性偏转时间表 | 29 | 指数时间刻度车辆将其速度重定向为沿其x轴 |
VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE | 车辆直线电机衰减时间 | 31 | 线性电机有效性衰减趋于零的指数时标 |
VEHICLE_LINEAR_MOTOR_TIMESCALE | 车辆直线电机时间表 | 30 | 指数时间刻度车辆达到其全部线性电机速度 |
VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY | 车辆垂直吸引力效率 | 36 | 介于车辆z轴到世界z轴(垂直)的0(弹性)和1(临界阻尼)吸引力之间 |
VEHICLE_VERTICAL_ATTRACTION_TIMESCALE | 车辆垂直吸引力时间表 | 37 | 车辆将其z轴与世界z轴对齐的指数时标(垂直) |
功能:将车辆的浮动参数param设置为value。
llSetVehicleFlags、llRemoveVehicleFlags
函数
llSetVehicleFlags(integer flags)
- integer flags – mask of VEHICLE_FLAG_* flags
llRemoveVehicleFlags(integer flags)
- integer flags – mask of VEHICLE_FLAG_* flags
常量 | 中文说明 | 描述 | |
---|---|---|---|
VEHICLE_FLAG_NO_DEFLECTION_UP | 无偏差 | 0x001 | 该标志可防止平行于世界z轴的线性偏转。这对于防止大型线性偏转的地面车辆(如碰碰车)避免其线性偏转进入天空非常有用。 |
VEHICLE_FLAG_LIMIT_ROLL_ONLY | 限制只滚动 | 0x002 | 对于想要爬升/俯冲的垂直吸引器的车辆,例如想要使用倾斜功能的飞机。 |
VEHICLE_FLAG_HOVER_WATER_ONLY | 悬浮水 | 0x004 | 悬停时忽略地形高度。 |
VEHICLE_FLAG_HOVER_TERRAIN_ONLY | 悬浮地形 | 0x008 | 悬停时忽略水的高度。 |
VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT | 悬停全球高度 | 0x010 | 悬停在全球高度,而不是高于地面或水面的高度。 |
VEHICLE_FLAG_HOVER_UP_ONLY | 只在空中盘旋 | 0x020 | 悬停不下推。使用此标志悬停车辆应能够跳过悬停高度。 |
VEHICLE_FLAG_LIMIT_MOTOR_UP | 升降 | 0x040 | 防止地面车辆驶入天空。与倾斜结合使用时,该标志具有微妙的影响:当车辆不再发生碰撞时,倾斜的强度将衰减。衰减时间表与VEHICLE_BANKING_TIMESCALE相同。这有助于防止地面车辆在中途跳跃时转向。 |
VEHICLE_FLAG_MOUSELOOK_STEER | MOUSELOOK引导 | 0x080 | 使用鼠标操纵车辆。使用此标志使角电机尝试使车辆转动,使其本地x轴指向与客户端摄像机相同的方向。 |
VEHICLE_FLAG_MOUSELOOK_BANK | MOUSELOOK倾斜 | 0x100 | 同上,但依赖于倾斜功能。它将客户端摄像头的左右运动(也称为“偏航”)重新映射为关于车辆本地x轴的旋转。 |
VEHICLE_FLAG_CAMERA_DECOUPLED | 相机旋转 | 0x200 | 使鼠标相机独立于车辆旋转。默认情况下,客户端mouselook摄像头会随着车辆旋转,但是当设置此标志时,摄像头方向与车辆的旋转无关。 |
功能:设置或禁用指定的车辆标志。
相关Event
run_time_permissions
Event: run_time_permissions(integer perm){ ; }
- integer perm - PERMISSIONS_ *标志授予权限的掩码
功能:当代理授予此脚本的运行时权限时触发,实行相应的行为动作。
例子:
default { state_entry() { llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); } run_time_permissions(integer perm) { if(PERMISSION_TRIGGER_ANIMATION & perm) { llStartAnimation("nyanya"); } } }
说明:参数perm是触发此事件时授予的所有权限的位组合。要确定是否授予了确切权限,您需要在perm和您正在查找的权限常量之间执行逐位AND比较。上面的例子演示了这一点。如果用户拒绝授予任何权限,则Perm将为0。
control
Event: control( key id, integer level, integer edge ){ ; }
- key id – 化身UUID
- integer level – 当一个或多个键被按住时,控制标记的位域,非零。
- integer edge – 当一个或多个键被按下或释放时,控制标记的位域,非零。
功能: 监听从键盘、鼠标输入的指令,并实现相应行为动作。
例子:
default { state_entry() { llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS); } run_time_permissions(integer perm) { if(PERMISSION_TAKE_CONTROLS & perm) { llTakeControls( CONTROL_FWD | CONTROL_BACK | CONTROL_LEFT | CONTROL_RIGHT | CONTROL_ROT_LEFT | CONTROL_ROT_RIGHT | CONTROL_UP | CONTROL_DOWN | CONTROL_LBUTTON | CONTROL_ML_LBUTTON | 0, TRUE, FALSE); // | 0 is for edit convenience, // it does not change the mask. } } control(key id, integer level, integer edge) { integer start = level & edge; integer end = ~level & edge; integer held = level & ~edge; integer untouched = ~(level | edge); llOwnerSay(llList2CSV([level, edge, start, end, held, untouched])); } }
说明:上述示例在获得相应权限后,每当捕获用户键盘输入后,输出相应变量的值。
collision
Event: collision(integer num_detected){ ; }
- integer num_detected
作用:当物体与另一物体发生碰撞时触发。
注意事项:
- 检测到的最大数量是8。
- 最小重复率大约为0.13秒。
- 不会检测与地面的碰撞; 改用land_collision。
- 不会检测坐在物体上的化身与物体本身之间的碰撞。
- 幻影对象永远不会收到触发器碰撞事件。
- llVolumeDetect(TRUE)对象会触发collision_start和collision_end,但不会触发collision事件。
- 与悬停的化身的碰撞不会触发collision事件,除非化身在转动或移动。
- 与物体或物体上的化身的碰撞不会持续触发碰撞,但会持续几次,除非有移动。
- 只有物理对象才会与非物理对象发生碰撞。
例子:
//当列表中有人撞到它时,它会变成幻影 list access_list = ["Governor Linden"]; default { collision(integer num_detected) { if(~llListFindList(access_list, (list)llDetectedName(0))) { llSetStatus(STATUS_PHANTOM, TRUE); } } }
collision_start
Event: collision_start(integer num_detected){ ; }
作用:当物体与另一个物体碰撞时触发。
注意事项:
- 不会检测与地面的碰撞; 改用land_collision。
- 幻影对象永远不会收到触发器碰撞事件。
- llVolumeDetect(TRUE)对象会触发collision_start和collision_end,但不会触发collision事件。
- 与悬停的化身的碰撞不会触发collision事件,除非化身在转动或移动。
- 只有物理对象才会与非物理对象发生碰撞。
例子:
default { collision_start(integer num) { llSay(0,"No pushing."); } }
collision_end
Event: collision_end(integer num_detected){ ; }
作用:当物体与另一个物体碰撞时触发。
注意事项:
- 这个事件并不总是触发。
- 幻影对象永远不会收到触发器碰撞事件。
- llVolumeDetect(TRUE)对象会触发collision_start和collision_end,但不会触发collision事件。
- 与悬停的化身的碰撞不会触发collision事件,除非化身在转动或移动。
- 只有物理对象才会与非物理对象发生碰撞。
例子:
collision_end(integer total_number) { llOwnerSay("The collision I've had with " + llDetectedName(0) + "has ended."); }
实例
简单实例
本实例实现了一个简单可控的车辆,当导入一个完整的车模型时,不直接将脚本放在车上,而是另外建一个透明的方块,包裹车,将脚本放在方块中,再将方块和车连接,以方块为根物体,当有化身坐在物体上时,自动获取相应权限,可通过w/s/a/d或↑/↓/←/→进行控制。
vector Sitpos = <0.60,0,.55>;//坐在物体上相对与物体中心的偏移量 vector SitrotV = <0,0,0>;//坐在物体上相对物体的旋转量 rotation Sitrot;//后面用来保存坐下的相对旋转量 key agent; integer Run;//记录当前是否处于被驾驶的状态 Init() { Run = 0; llSetVehicleType(VEHICLE_TYPE_NONE);//设置初始交通工具类型 llSetStatus(STATUS_PHYSICS, FALSE);//取消物理状态 vector rotv = llRot2Euler(llGetRot());//得到当前的旋转向量 rotation rot = llEuler2Rot(<0,0,rotv.z>);//得到欧拉旋转量 llSetRot(rot); Sitrot = llEuler2Rot(DEG_TO_RAD * SitrotV);//得到坐下的旋转方向 } //主状态开始 default { state_entry() { Init();//初始化交通工具的类型,物理性,部件的状态等属性 llSitTarget(Sitpos, Sitrot); } changed(integer change)//当某操作要改变该物体的属性时触发 { //化身坐在上面 if ((change & CHANGED_LINK) == CHANGED_LINK) { agent = llAvatarOnSitTarget();//得到坐在上面的化身的key值 if (agent != NULL_KEY)//如果有化身坐在上面 { llSetStatus(STATUS_PHYSICS, TRUE);//开启物理属性 llSetVehicleType(VEHICLE_TYPE_CAR);//设置交通工具类型,见常量部分 llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 0.5);//线性发动机减速到0的时间 //获取控制权限请求 llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS); Run = 1; } else {//其他状态的改变,即没有人坐在上面的时候 Run = 0;//停止车辆状态的运行 llReleaseControls();//解除控制 Init();//对车辆重新进行初始化 //恢复车辆的位置状态 llSetPos(llGetPos() + <0,0,0.5>); } } } run_time_permissions(integer perm) { if (perm) {//获得的控制许可 llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_DOWN | CONTROL_UP | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);//开启控制事件 llSetPos(llGetPos() + <0,0,0.5>);//往上提升一点位置 } } control(key id, integer level, integer edge) {//对控制事件的处理 if(Run == 0) { return; } if(level & CONTROL_FWD) { llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <10.0, 2.0, 1000.0>); llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <40,0,0>);//启动车辆 } if(level & CONTROL_BACK) {//控制倒车 llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <10.0, 2.0, 1000.0>); llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <-20,0,0>); } if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT)) {//设置右转的参数值 llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,-8>); } if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT)) {//设置左转的参数值 llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,8>); } } }
复杂实例
相比于上一个简单的车辆实例,本实例相对复杂一些,在一些具体的参数设置上,也与真实的车辆更为靠近。在本实例中,添加了车辆的速度控制、化身坐在车上的动作设置、化身坐在车上时的相机设置以及对于车辆发生碰撞后的处理。
化身坐姿文件: 文件:Driving generic.zip
key agent; vector Sitpos = <0.60,0,.55>;//坐在物体上相对与物体中心的偏移量 vector SitrotV = <0,0,0>;//坐在物体上相对物体的旋转量 rotation Sitrot;//后面用来保存坐下的相对旋转量 float forward_power = 14; //前进的推进力(1~30),这里值有点大 float forward_normal = 20;//正常的向前的推进力 float crash_power_forward = 2; float reverse_power = -3; //倒车的推进力 float turning_ratio = 0.25; //转向的敏锐程度,值越小表示转向越敏锐(.1 to 10) float Speed;//存放车速 integer Gear = 1;//存放档位,即加速度 integer Run;//记录当前是否处于被驾驶的状态 string not_owner_message = "You are not the owner of this vehicle, but you can copy it and have your own to test in this sim."; //非拥有者不能驾驶,但是可以复制一份,然后驾驶 //强制进行初始化更新 string DrivingAnim = "driving generic"; //坐在车上时,化身的姿势 setCamera(float degrees) { rotation sitRot = llAxisAngle2Rot(<0, 0, 1>, degrees * PI);//绕Z轴旋转指定度数 llSetCameraEyeOffset(<-10, 0, 3> * sitRot);//设置相机位置 llSetCameraAtOffset(<4, 0, 3> * sitRot);//设置相机的看点 llForceMouselook(FALSE);//取消鼠标视图,即:进入非第一人称视角 } setVehicle() { llSetVehicleType(VEHICLE_TYPE_CAR);//设置交通工具类型,见常量部分 //下面设置交通工具的浮点类型参数 llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.2);//设置旋转的效率 llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.80);//设置加速的效率 llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 0.10);//设置角度旋转全角度需要的时间 llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 0.10);//设置加速的时间 llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 3.0);//加到线性加速到全速的时间 llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 0.1);//线性发动机减速到0的时间 llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.1);//角度发动机转速达到全速的时间 llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 0.1);//角度发动机转速减为0的时间 llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <100.0, 2.0, 1000.0>);//三维的摩擦延迟 llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <0.1, 0.1, 0.1>);//三维的线性动力的延迟 llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.1); llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 5.0); llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.01 );//设置浮力属性 llSetVehicleFloatParam( VEHICLE_BANKING_EFFICIENCY, -0.2 ); llSetVehicleFloatParam( VEHICLE_BANKING_MIX, 1 ); llSetVehicleFloatParam( VEHICLE_BANKING_TIMESCALE, 1 ); } Init() { Run = 0; llSetVehicleType(VEHICLE_TYPE_NONE);//设置初始交通工具类型 llSetStatus(STATUS_PHYSICS, FALSE);//取消物理状态 vector rotv = llRot2Euler(llGetRot());//得到当前的旋转向量 rotation rot = llEuler2Rot(<0,0,rotv.z>);//得到欧拉旋转量 llSetRot(rot); Sitrot = llEuler2Rot(DEG_TO_RAD * SitrotV);//得到坐下的旋转方向 } //重置 Reset() { Run = 0; vector rotv = llRot2Euler(llGetRot()); rotation rot = llEuler2Rot(<0,0,rotv.z>); llSetRot(rot);//X、Y方向不旋转,保留Z轴旋转方向 llSetPos(llGetPos() + <0,0,0.5>);//保证位置离地面有0.5M的距离 } //主状态开始 default { state_entry() { Init();//初始化交通工具的类型,物理性,部件的状态等属性 llSitTarget(Sitpos, Sitrot); setCamera(0); } collision(integer collide1)//当本脚本所在物体发生碰撞时触发 { } collision_start(integer collide)//开始发生碰撞时触发,碰撞的控制 { forward_power = crash_power_forward; //突然减速到2,模拟碰撞的效果 turning_ratio = 0.05; //转向程度。越小越厉害 (.1 to 10) llSetBuoyancy(0.001);//几乎没有浮力 } collision_end(integer collide) { forward_power = forward_normal; //恢复到之前的向前的推进力 turning_ratio = 0.25; //转向灵活度,越小越灵活。(.1 to 10) llSetBuoyancy(0.0);//去除浮力 } on_rez(integer rn)//重置脚本时触发 { llResetScript();//重置脚本 llSetPos(llGetPos() + <0,0,0.5>);//设置整体向上移动0.5米,这样透明的底部也能在地面之上,地面不平就基本不影响了。 } changed(integer change)//当某操作要改变该物体的属性时触发 { //化身坐在上面 if ((change & CHANGED_LINK) == CHANGED_LINK) { agent = llAvatarOnSitTarget();//得到坐在上面的化身的key值 if (agent != NULL_KEY)//如果有化身坐在上面 { if( (agent != llGetOwner())) {//对于非拥有者,不能开动 llSay(0, not_owner_message); llUnSit(agent);//强制离开 llPushObject(agent, <0,0,50>, ZERO_VECTOR, FALSE);//推离开化身 } else {//对拥有者的处理 llSetStatus(STATUS_PHYSICS, TRUE);//开启物理属性 llSleep(.4);//将脚本暂停0.4s setVehicle();//设置交通工具 llSetTimerEvent(0.3);//设置0.3s后触发事件,保证Run的值已经为1,即车辆已经成功开始运行 //获取控制权限请求 llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS); Run = 1; } } else {//其他状态的改变,即没有人坐在上面的时候 Run = 0;//停止车辆状态的运行 llReleaseControls();//解除控制 llStopAnimation(DrivingAnim);//停止各个部分的动作 Init();//对车辆重新进行初始化 //恢复车辆的位置状态 llSetPos(llGetPos() + <0,0,0.5>); } } } run_time_permissions(integer perm) { if (perm) {//获得的控制许可 //给推进力,倒退的力量赋值 forward_power = forward_normal; //设置推进力(1 to 30) reverse_power = -3; //设置反向推力(-1 to -30) turning_ratio = 0.28; //设置转向的灵敏度 (.1 to 10) Gear = 2;//初始的档位 llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_DOWN | CONTROL_UP | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);//开启控制事件 llSetPos(llGetPos() + <0,0,0.5>);//往上提升一点位置 llStartAnimation(DrivingAnim);//开启各个部件的行驶动画 llWhisper(0,"Hit M for mouselook, page up and down for shifting, if you flip standing will flip car back on its wheels."); llSay(0,"Speed gear is 2"); } } control(key id, integer level, integer edge) {//对控制事件的处理 if(Run == 0) { return; } vector angular_motor; //获取当前速度 vector vel = llGetVel(); Speed = llVecMag(vel); //汽车控制 if ((level & edge & CONTROL_UP) || ((Gear >= 7) && (level & CONTROL_UP))) {//控制加档 Gear=Gear+1; if (Gear < 1) Gear = 1; if (Gear > 7) Gear = 7; llSay(0,"Speed gear is " + Gear); } if ((level & edge & CONTROL_DOWN) || ((Gear >= 7) && (level & CONTROL_DOWN))) {//控制降挡 Gear=Gear-1; if (Gear < 1) Gear = 1; if (Gear > 7) Gear = 7; llSay(0,"Speed gear is " + Gear); } if(level & CONTROL_FWD) {//按住前进,根据Gear的值来设置相应的推进力 turning_ratio = 0.3;//转向的灵敏度设置 llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <10.0, 2.0, 1000.0>); llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <(Gear*forward_power),0,0>);//启动车辆 } if(level & CONTROL_BACK) {//控制倒车 llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <10.0, 2.0, 1000.0>); llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <Gear*reverse_power,0,0>); turning_ratio = -0.3;//向左转 } if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT)) {//设置右转的参数值 angular_motor.z -= Speed / (turning_ratio*Gear); } if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT)) {//设置左转的参数值 angular_motor.z += Speed / (turning_ratio*Gear); } llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_motor);//根据之前设置好的转向参数进行车辆的偏转 } //end control timer(){ if(Run == 1){//如果人坐上车,车已经开始处于运行状态 vector vel = llGetVel(); Speed = llVecMag(vel); if(Speed > 0.0 && Speed <2.0) { llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1.0, 2.0, 1000.0>);//设置摩擦力 llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <0,0,0>);//速度小的时候停下来 } llSetTimerEvent(0.3); // 保持这个函数反复调用 } else { llSetTimerEvent(0.0);//停止该时间的调用,车没有运行 } } } //end default