虚拟世界/Vehicles

来自人工智能助力教育知识百科
Wyg讨论 | 贡献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_ *标志授予权限的掩码

功能:当代理授予此脚本的运行时权限时触发,实行相应的行为动作。

文件:Run time permissions.png

例子:

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 – 当一个或多个键被按下或释放时,控制标记的位域,非零。

功能: 监听从键盘、鼠标输入的指令,并实现相应行为动作。

文件:Control.png

例子:

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

参考