HoloLens2开发-MRTK2.5-Interactable(可互动的)

HoloLens2开发-MRTK2.5-Interactable(可互动的)

Interactable 组件是一个多合一的容器,可以使任何对象轻松交互并响应输入。交互性是所有类型的输入(包括触摸,手光线,语音等)的统筹兼用,并将这些交互作用转化为事件视觉主题响应。该组件提供了一种简单的方法来制作按钮,更改具有焦点的对象的颜色等等。

如何配置Interactable

该组件允许配置的三个主要部分:

  1. 常规输入配置
  2. 针对多个GameObjects的视觉主题
  3. 事件处理程序

常规输入设置

HoloLens2开发-MRTK2.5-Interactable(可互动的)

状态

状态ScriptableObject参数,用于定义“交互的配置文件”和“视觉主题”的交互阶段,例如按下或观察。

DefaultInteractableStates(Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset)附带MRTK外的盒子,并且是默认的参数可交互组件。

HoloLens2开发-MRTK2.5-Interactable(可互动的)

DefaultInteractableStates资产包含四种状态,并利用InteractableStates状态模型实现。

  • 默认值:什么都没有发生,这是最孤立的基本状态。
  • 焦点:指向对象。这是一个状态,当前未设置其他任何状态,但其排名将超过默认值。
  • 按下:指向对象,并按下按钮或手。按下状态将对“默认”和“焦点”进行排名。此状态也将设置为对物理出版社的后备。
  • 禁用:该按钮不应是交互式的,视觉反馈将使用户知道该按钮由于某种原因当前不可用。从理论上讲,禁用状态可以包含所有其他状态,但是当禁用“启用”时,“禁用”状态将胜过所有其他状态。

根据列表中的顺序,为状态分配一个位值(#)。

[!注意]在创建可交互组件时,通常建议使用DefaultInteractableStates(Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset)。

但是,有17种可交互状态可用于驱动主题,尽管有些状态是由其他组件驱动的。这是具有内置功能的列表。

已访问:已单击交互对象。

已切换:按钮处于已切换状态,或者维度索引为奇数。

手势:按下手或控制器并从原始位置移开。

语音命令:语音命令用于触发交互对象。

PhysicalTouch:当前检测到触摸输入,用于NearInteractionTouchable启用。

抓取:一只手当前正在抓住对象的边界,用于NearInteractionGrabbable启用

已启用

切换交互对象是否将开始启用。这对应于Interactable.IsEnabledin代码。

一个可交互的启用性能比通过游戏对象/组件(即SETACTIVE等),被配置启用的属性不同。禁用GameObject或Interactable MonoBehaviour将禁用类中所有内容的运行,包括输入,视觉主题,事件等。禁用viaInteractable.IsEnabled将禁用大多数输入处理,并重置相关的输入状态。但是,该类仍将在每一帧运行,并接收将被忽略的输入事件。这对于通过Visual Themes可以在禁用状态下显示交互对象很有用。一个典型的例子是提交按钮,等待所有必填的输入字段完成。

输入动作

从输入配置或控制器映射概要文件中选择Interactionable组件应作出反应的输入操作

可以在运行时通过来配置此属性Interactable.InputAction

IsGlobal

如果为true,则将组件标记为所选输入action的全局输入侦听。默认行为为false,这会将输入限制为仅此Interactable collider / GameObject。

可以在运行时通过来配置此属性Interactable.IsGlobal

语音指令

语音命令,从MRTK语音命令资料,来触发针对语音交互onClick事件。

可以在运行时通过来配置此属性Interactable.VoiceCommand

需要重点

如果为true,则仅当且仅当语音命令已经具有指针的焦点时,语音命令才会激活Interactable。如果为false,则交互对象将充当所选语音命令的全局侦听器。默认行为是正确的,因为可能很难在一个场景中组织多个全局语音侦听器。

可以在运行时通过来配置此属性 Interactable.VoiceRequiresFocus

选择模式

此属性定义选择逻辑。当一个可交互被点击时,它遍历到下一个维度的水平。尺寸与等级相似,并定义了输入之外的状态(即焦点,按下等)。它们对于定义与按钮关联的切换状态或其他多列状态很有用。当前Dimension级别由跟踪Interactable.DimensionIndex

可用的选择模式为:

  • 按钮尺寸= 1,简单可点击可交互
  • 切换尺寸= 2,交互作用/状态之间交替
  • 多维尺寸> = 3,每次单击都会增加当前尺寸级别+1。对于定义列表的按钮状态等有用。

Interactable 还允许每个 Dimension 定义多个主题。例如当的 SelectionMode =Toggle,一个主题可以在所施加的可交互取消选择,并且该组件时另一个主题施加选择

可以在运行时通过查询当前选择模式Interactable.ButtonMode。可以通过设置Interactable.Dimensions属性以匹配所需功能来在运行时更新模式 。此外,可通过来访问对“切换”和“多维”模式有用的当前尺寸Interactable.CurrentDimension

交互配置文件

配置文件是在GameObject和Visual Theme之间建立关系的项目。配置文件定义了状态更改发生时主题将处理的内容。

主题的工作原理很像材料。它们是可编写脚本的对象,其中包含将基于当前状态分配给对象的属性列表。主题也可以重用,并且可以在多个Interactable UX对象之间分配。

销毁时重置

视觉主题会根据所选主题引擎的类和类型来修改目标GameObject上的各种属性。如果在销毁可交互组件时销毁重置为true,则该组件会将所有修改后的属性从活动主题重置为其原始值。否则,在被破坏时,可交互组件将保留所有修改后的属性。在后一种情况下,除非被另一个外部组件更改,否则值的最后状态将保持不变。默认为false。

事件

每个Interactable组件都有一个OnClick事件,该事件在仅选择该组件时就会触发。但是,Interactable可以用于检测输入事件,而不仅仅是OnClick

单击添加事件按钮以添加新类型的事件接收器定义。添加后,选择所需事件的类型。

有不同类型的事件接收器来响应不同类型的输入。MRTK随附了以下几套现成的接收机。

  • InteractableAudioReceiver
  • InteractableOnClickReceiver
  • InteractableOnFocusReceiver
  • InteractableOnGrabReceiver
  • InteractableOnHoldReceiver
  • InteractableOnPressReceiver
  • InteractableOnToggleReceiver
  • InteractableOnTouchReceiver

可以通过扩展新类来创建自定义接收器ReceiverBase

HoloLens2开发-MRTK2.5-Interactable(可互动的)

切换事件接收器的示例

互动式接收器

InteractableReceiver组件允许在源Interactable组件之外定义事件。该InteractableReceiver将听取由另一发射的过滤事件类型可交互。如果没有直接分配Interactable属性,则“搜索范围”属性将定义InteractableReceiver侦听事件的方向,该方向可以是自身,父对象或子GameObject中的事件。

InteractableReceiverList 行为类似,但包含匹配事件列表。

HoloLens2开发-MRTK2.5-Interactable(可互动的)

创建自定义事件

Visual Themes一样,事件可以扩展为检测任何状态模式或公开功能。

可以通过两种主要方式创建自定义事件:

  1. 扩展ReceiverBase类以创建一个自定义事件,该事件将显示在事件类型的下拉列表中。默认情况下会提供一个Unity事件,但是可以添加其他Unity事件,也可以将该事件设置为隐藏Unity事件。此功能使设计人员可以与工程师合作处理项目,以创建设计人员可以在编辑器中设置的自定义事件。
  2. 扩展ReceiverBaseMonoBehavior该类以创建可以驻留在Interactable或另一个对象上的完全自定义事件组件。该ReceiverBaseMonoBehavior会参考可交互检测状态的变化。

扩展示例 ReceiverBase

CustomInteractablesReceiver约一类的显示状态信息可交互,是如何创建一个自定义事件接收的例子。

public CustomInteractablesReceiver(UnityEvent ev) : base(ev, "CustomEvent")
{
    HideUnityEvents = true; // hides Unity events in the receiver - meant to be code only
}

创建自定义事件接收器时,以下方法对于覆盖/实现很有用。ReceiverBase.OnUpdate()是一种可用于检测状态模式/转换的抽象方法。此外,当选择Interactable时,ReceiverBase.OnVoiceCommand()ReceiverBase.OnClick()方法对于创建自定义事件逻辑很有用。

public override void OnUpdate(InteractableStates state, Interactable source)
{
    if (state.CurrentState() != lastState)
    {
        // the state has changed, do something new
        lastState = state.CurrentState();
        ...
    }
}

public virtual void OnVoiceCommand(InteractableStates state, Interactable source,
                                    string command, int index = 0, int length = 1)
{
    base.OnVoiceCommand(state, source, command, index, length);
    // voice command called, perform some action
}  

public virtual void OnClick(InteractableStates state,
                            Interactable source,
                            IMixedRealityPointer pointer = null)
{
    base.OnClick(state, source);
    // click called, perform some action
}
在检查器中显示自定义事件接收器字段

ReceiverBase脚本使用InspectorField属性在检查中公开自定义属性。这是Vector3的示例,Vector3是带有工具提示和标签信息的自定义属性。选择Interactable GameObject并添加关联的事件接收器类型后,此属性将在检查器中显示为可配置。

[InspectorField(Label = "<Property label>",Tooltip = "<Insert tooltip info>",Type = InspectorField.FieldTypes.Vector3)]
public Vector3 EffectOffset = Vector3.zero;

如何使用互动式

建立一个简单的按钮

通过将Interactable组件添加到配置为接收输入事件的GameObject中,可以创建一个简单的按钮。它可以在其上或在孩子身上带有对撞机,以接收输入。如果将Interactable与基于Unity UI的GameObjects一起使用,则它应位于Canvas GameObject下。

通过创建新的配置文件,分配GameObject本身并创建新的主题,将按钮进一步向前移动。此外,使用OnClick事件可以使某些事情发生。

[!NOTE]使按钮可按下需要该PressableButton组件。此外,PhysicalPressEventRouter还需要该组件将新闻事件集中到Interactable组件。

创建切换和多维按钮

切换按钮

要使按钮可切换,请将Selection Mode字段更改为Toggle。在“个人档案”部分中,为打开“互动”时使用的每个个人档案添加了新的切换主题。

SelectionMode设置为Toggle时,“ IsToggled”复选框可用于在运行时初始化时设置控件的默认值。

CanSelect表示交互对象可以从关闭变为打开,CanDeselect表示相反。

HoloLens2开发-MRTK2.5-Interactable(可互动的)

开发人员可以使用SetToggledIsToggled接口通过代码获取/设置Interactable的切换状态。

// If using SelectionMode = Toggle (i.e Dimensions == 2)

// Make the Interactable selected and toggled on
myInteractable.IsToggled = true;

// Get whether the Interactable is selected or not
bool isSelected = myInteractable.IsToggled;
切换按钮集合

通常有一系列切换按钮,在任何给定时间都只能激活一个切换按钮,也称为径向按钮或单选按钮等。

使用InteractableToggleCollection组件启用此功能。此控件可确保在任何给定时间仅打开一个Interactable。该RadialSet(资产/ MRTK / SDK /功能/ UX /可交互/预制件/ RadialSet.prefab)也是一个很好的起点外的框。

要创建自定义的径向按钮组:

  1. 创建多个可交互的GameObjects /按钮
  2. 使用SelectionMode = Toggle,CanSelect = true和CanDeselect = false设置每个Interactable
  3. 在所有Interactables上创建一个空的父GameObject并添加InteractableToggleCollection组件
  4. 所有加入InteractablesToggleListInteractableToggleCollection
  5. 设置InteractableToggleCollection.CurrentIndex属性,以确定在启动时默认选择哪个按钮
HoloLens2开发-MRTK2.5-Interactable(可互动的)

多维按钮

多维选择模式用于创建顺序按钮或具有两个以上步骤的按钮,例如使用三个值控制速度(快速(1x),更快(2x)或最快(3x))。

尺寸为数字值时,可以为每个速度设置添加最多9个主题,以控制按钮的文本标签或纹理,并为每个步骤使用不同的主题。

每个click事件都会DimensionIndex在运行时将其递增1,直到Dimensions达到该值为止。然后循环将重置为0。

HoloLens2开发-MRTK2.5-Interactable(可互动的)

开发人员可以评估DimensionIndex以确定当前处于活动状态的维度。

// If using SelectionMode = Multi-dimension (i.e Dimensions >= 3)

//Access the current DimensionIndex
int currentDimension = myInteractable.CurrentDimension;

//Set the current DimensionIndex to 2
myInteractable.CurrentDimension = 2;

// Promote Dimension to next level
myInteractable.IncreaseDimension();

在运行时创建交互

可在运行时将Interactable轻松添加到任何GameObject中。以下示例演示了如何为配置文件分配视觉主题

var interactableObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
var interactable = interactableObject.AddComponent<Interactable>();

// Get the default configuration for the Theme engine InteractableColorTheme
var newThemeType = ThemeDefinition.GetDefaultThemeDefinition<InteractableColorTheme>().Value;

// Define a color for every state in our Default Interactable States
newThemeType.StateProperties[0].Values = new List<ThemePropertyValue>()
{
    new ThemePropertyValue() { Color = Color.black},  // Default
    new ThemePropertyValue() { Color = Color.black}, // Focus
    new ThemePropertyValue() { Color = Random.ColorHSV()},   // Pressed
    new ThemePropertyValue() { Color = Color.black},   // Disabled
};

interactable.Profiles = new List<InteractableProfileItem>()
{
    new InteractableProfileItem()
    {
        Themes = new List<Theme>()
        {
            Interactable.GetDefaultThemeAsset(new List<ThemeDefinition>() { newThemeType })
        },
        Target = interactableObject,
    },
};

// Force the Interactable to be clicked
interactable.TriggerOnClick()

通过代码进行交互的事件

可以Interactable.OnClick通过以下示例通过代码向基本事件添加操作。

public static void AddOnClick(Interactable interactable)
{
    interactable.OnClick.AddListener(() => Debug.Log("Interactable clicked"));
}

使用该Interactable.AddReceiver<T>()函数在运行时动态添加事件接收器。

下面的示例代码演示了如何添加一个InteractableOnFocusReceiver,它侦听焦点的进入/退出,并且还定义了在事件实例触发时执行的动作代码。

public static void AddFocusEvents(Interactable interactable)
{
    var onFocusReceiver = interactable.AddReceiver<InteractableOnFocusReceiver>();

    onFocusReceiver.OnFocusOn.AddListener(() => Debug.Log("Focus on"));
    onFocusReceiver.OnFocusOff.AddListener(() => Debug.Log("Focus off"));
}

下面的示例代码演示了如何添加一个InteractableOnToggleReceiver,它侦听可切换Interactables上的已选择/取消选择状态转换,并且还定义了在事件实例触发时执行的动作代码。

public static void AddToggleEvents(Interactable interactable)
{
    var toggleReceiver = interactable.AddReceiver<InteractableOnToggleReceiver>();

    // Make the interactable have toggle capability, from code.
    // In the gui editor it's much easier
    interactable.Dimensions = 2;
    interactable.CanSelect = true;
    interactable.CanDeselect  = true;

    toggleReceiver.OnSelect.AddListener(() => Debug.Log("Toggle selected"));
    toggleReceiver.OnDeselect.AddListener(() => Debug.Log("Toggle un-selected"));
}

也可以看看

原创文章,作者:游戏开发极客,如若转载,请注明出处:https://hololens2.cn/2020/10/16/%e5%8f%af%e4%ba%92%e5%8a%a8%e7%9a%84/

发表评论

电子邮件地址不会被公开。 必填项已用*标注