输入系统
介绍
Unigine引擎提供的众多特征之一便是高级输入API,其允许使用各种不同的输入设备按照相同的方法进行工作(例如键盘,鼠标,控制杆,手柄等)并同时使用这些设备的性能。由于可用性,所有由引擎识别的输入设备具有通用接口。对输入设备的控制可分配给虚拟世界中确切的用户行为。应用程序需要对使用GUI激活的控制进行编辑。
输入脚本位于Unigine SDK的data/scripts/input目录下。
实体
Input device(输入设备)
输入设备是一种外部硬件设备,此设备给处理单元提供数据及控制信号。对于虚拟交互显现实系统,此设备是一种关键资源。每种输入设备无论是什么类型都有ID并具有轴线及按钮的数量以及状态的特征。
Input(输入)
Input(输入)代表提供给引擎的输入数据。
Button(按钮)
输入设备的Button(按钮)仅提供开放/关闭的数字信号,表明两种离散值:“0”和“1”。用户应用程序会相应地作出回应。
Axis(轴)
输入设备的Axis(轴)是一种模拟信号数据,与偏移角相一致。其具有三个基本位置:最小,中间及最大。对于Unigine引擎由于其间隔介于-1.0和 1.0之间,推荐将0 作为中间值。
根据轴的特点,可将轴分成4种校准类型:
- 增加轴 - 所用变化范围从 0.0 到 1.0;
- 减少轴 -所用变化范围从0.0 到 -1.0;
- 使用变化范围从 -1.0 到 1.0的正数轴;
- 使用变化范围从1.0 到 -1.0的负数轴。
Virtual axis(虚拟轴)
Virtual axis(虚拟轴)允许使用数字输入设备仿真模拟信号。其被用来实施平顺的数值变化,例如与操纵轮子的旋转相似。如果被分配有虚拟轴的按钮被持续或重复按下,虚拟轴的值将使用指定的改变速度增加到1.0。如果不再按下此按钮,则轴的值将使用回退速度减少到0。
Action(动作)
用户可在虚拟世界中做大量的动作,比如朝着不同方向移动,跳跃或设计。这些动作可通过许多方式得以激活:可按下按钮或者旋转手柄的模拟棒。通过Unigine的引擎,可为每种动作行为分配多个输入。分配给动作和输入轴的名称可被保存在配置文件中。
配置文件的语法
保存在XML文件中的配置语法如下:
<controls>
<action name="accelerate">
<input device="Logitec Racing Wheel" state="3" min="1" max="-1"/>
<input device="Keyboard" state="119"/>
</action>
<action name="brake">
<input device="Logitec Racing Wheel" state="2" min="1" max="-1"/>
<input device="Keyboard" state="115"/>
</action>
</controls>
Сontrols 标签用来描述控制动作的贴图。Action标签也包括在此标签内。
Action标签描述动作配置,通过动作名称进行识别(需要名称属性)。Action标签可包含Input标签。
Input标签包含输入配置。其具有下列属性:
- Device(设备)是一种所需属性。其指定输入设备的名称并被用来识别输入设备。将键盘 和 鼠标指定为输入设备对于所有类型的键盘和鼠标已足够。
- State(状态)是一种所需属性。其指定输入设备状态号码并用来将输入映射到特定的输入设备轴或按钮上。
无法直接使用按钮的名称,因为每种输入设备具有其自己的状态和状态名称。状态及状态名基于安装的驱动。考虑到这些因素,因而名称并不具有通用性。
然而可使用GUI接口编辑控制。这种情况下,无需指定确切的状态编号且可以看见输入的状态名称。 - Min是一种可选属性。其指定最小输入设备轴的值。
- Max 是一种可选属性。其指定最大输入设备轴的值。
- Neutral 在输入不活跃时,指定中间值。默认为0。
- Threshold以十进制单位指定用于对输入设备进行响应的线程。默认值为0.2。
- Change_speed 是一种可选属性。其指定轴的更改速度。
- Return_speed 是一种可选属性。其指定轴的回退速度。
使用方法
第一步:包括所需输入设备的首部:
#include <scripts/input/input_device.h>
#include <scripts/input/control.h>
第二步:添加初始化,更新并关闭处理器来初始化代码:
Unigine::Input::init();
Unigine::Input::update();
Unigine::Input::shutdown();
第三步:创建控制配置文件:
创建2个配置文件: controls_def 和 controls。
Controls_def文件定义动作的属性:
<?xml version="1.0" encoding="utf-8"?>
<controls_def>
<action_def name="accelerating" min="0" max="1" neutral="0" type="state"/>
</controls_def>
Action标签拥有以下属性:
- Name — 动作名。
- Min — 用于应用程序接收输入的最小轴的值。
- Max — 用于应用程序接收输入的最大轴的值。
- Neutral — 用于应用程序接收输入的中间轴的值。
- Type — 动作类型:
- State 指定起效的动作指定按下对应的输入。换句话说当有必要根据键/轴的状态持续改变某些条件时,需要使用状态动作。汽车的方向盘便是实例之一:
在state动作中, getState() 会返回当前的输入状态(根据输入范围及动作范围进行纠正)。
- Switch在有必要打开或关闭某些事物时进行使用。其允许处理key up和key down时间(每次仅能处理一种事件)。开关车头灯便是实例之一。
在switch动作中,当前的状态互不相干但当前状态与之前状态之间的差异才是问题所在。
- 按下键后, getState() 返回最大值。
- 键恢复时,getState()返回-1 * 最大值。
- 如果自上次更新以来,键的状态未发生变化,此方法将返回最小值。
- State 指定起效的动作指定按下对应的输入。换句话说当有必要根据键/轴的状态持续改变某些条件时,需要使用状态动作。汽车的方向盘便是实例之一:
Controls文件将输入和动作捆绑在一起:
<?xml version="1.0" encoding="utf-8"?>
<controls definition="/config/controls/controls_def">
<controls>
<action name="accelerate"/>
<action name="brake"/>
<!-- etc. -->
</controls>
第四步。
要加载控制配置,需使用
// 初始代码中的某处
Control control = new Control();
control.loadFromFile("you_config_file.xml");
// 更新代码中的某处
control.update(engine.game.getIFps())
Action action = control.getAction("accelerate");
current_car.setAccelerator(action.getState());
action = control.getActionByName("brake");
current_car.setBrake(action.getState());
// 等等。
使用GUI接口编辑控制
要激活此方法,需执行下列步骤:
第一步。将首部包括在内:
#include <scripts/input/control_setup_window.h>
第二步:添加初始化,在对应的代码区域内为ControlSetupWindow更新并关闭处理器:
Unigine::Input::ControlSetupWindow::init(engine.getGui());
Unigine::Input::ControlSetupWindow::update();
Unigine::Input::ControlSetupWindow::shutdown();
第三步:用来显示配置窗口代码的实例:
void cotroller_setup_button_clicked() {
if(controller_setup_button.isToggled()) {
// 显示窗口
Unigine::Input::ControlSetupWindow::addOnHideCallback("TestCarGui::on_save_car_controls",NULL);
Unigine::Input::ControlSetupWindow::show(control); // 参看上述控制定义
} else {
// 隐藏窗口
Unigine::Input::ControlSetupWindow::hide();
}
}