Interactable : MRTK2
El Interactable
componente es un contenedor todo en uno para que cualquier objeto pueda interactuar fácilmente y responder a la entrada. Interactable actúa como un elemento catch-all para todos los tipos de entrada, incluidos los toques, los rayos de mano, la voz, etc., y canaliza estas interacciones en eventos y respuestas de temas visuales . Este componente proporciona una manera sencilla de crear botones, cambiar el color de los objetos con foco, etc.
Configuración de Interactable
El componente permite tres secciones principales de configuración:
- Configuración de entrada general
- Temas visuales dirigidos a varios GameObjects
- Controladores de eventos
Configuración de entrada general
Estados
States es un parámetro ScriptableObject que define las fases de interacciones, como presionar o observar, para perfiles interactables y temas visuales.
DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) se incluye con MRTK de fábrica y es el parámetro predeterminado para los componentes interactables.
El recurso DefaultInteractableStates contiene cuatro estados y utiliza la implementación del InteractableStates
modelo de estado.
Valor predeterminado: no ocurre nada, este es el estado base más aislado.
Enfoque: se apunta al objeto. Se trata de un único estado, no hay ningún otro estado establecido actualmente, pero se clasificará como Predeterminado.
Presionar: El objeto se apunta y se presiona un botón o una mano. El estado de la prensa se clasifica como Predeterminado y Foco. Este estado también se establecerá como reserva para La prensa física.
Deshabilitado: el botón no debe ser interactivo y los comentarios visuales harán saber al usuario si, por algún motivo, este botón no se puede usar en este momento. En teoría, el estado deshabilitado podría contener todos los demás estados, pero cuando Está habilitado está desactivado, el estado Deshabilitado supera a todos los demás estados.
Un valor de bits (#) se asigna al estado en función del orden de la lista.
Nota:
Por lo general, se recomienda usar DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) al crear componentes interactables .
Sin embargo, hay 17 estados interactables disponibles que se pueden usar para impulsar los temas, aunque algunos están diseñados para ser controlados por otros componentes. Esta es una lista de aquellos con funcionalidad integrada.
- Visitado: se ha hecho clic en Interactable.
- Alternar: el botón está en un estado de alternancia o el índice de dimensión es un número impar.
- Gesto: se presionó la mano o el controlador y se movió desde la posición original.
- VoiceCommand: se usó un comando de voz para desencadenar interactable.
- PhysicalTouch: actualmente se detecta una entrada táctil, que se usa
NearInteractionTouchable
para habilitar. - Grab: una mano está agarrándose actualmente en los límites del objeto, use
NearInteractionGrabbable
para habilitar
Enabled
Alterna si un interactable se iniciará habilitado o no. Esto corresponde a en el Interactable.IsEnabled
código.
La propiedad habilitada de un interactable es diferente de la propiedad habilitada configurada a través de GameObject/Component (es decir, SetActive, etc.). Deshabilitar GameObject o Interactable MonoBehaviour deshabilitará la ejecución de todo lo que hay en la clase, incluidos los temas de entrada, visuales, eventos, etc. Deshabilitar mediante Interactable.IsEnabled
deshabilitará la mayoría del control de entrada y restablecerá los estados de entrada relacionados. Sin embargo, la clase seguirá ejecutando cada fotograma y recibirá eventos de entrada que se omitirán. Esto es útil para mostrar interactable en un estado deshabilitado que se puede realizar a través de Temas visuales. Un ejemplo típico de esto sería un botón de envío a la espera de que se completen todos los campos de entrada necesarios.
Acciones de entrada
Seleccione la acción de entrada del perfil de asignación de controlador o configuración de entrada al que debe reaccionar el componente interactable .
Esta propiedad se puede configurar en tiempo de ejecución en código a través de Interactable.InputAction
.
IsGlobal
Si es true, marcará el componente como agente de escucha de entrada global para la acción de entrada seleccionada. El comportamiento predeterminado es false, que restringirá la entrada solo a este colisionador interactable o GameObject.
Esta propiedad se puede configurar en tiempo de ejecución en código a través de Interactable.IsGlobal
.
Comando de voz
Comando de voz, desde el perfil de comandos de voz de MRTK, para desencadenar un evento OnClick para la interacción de voz.
Esta propiedad se puede configurar en tiempo de ejecución en código a través de Interactable.VoiceCommand
.
Requiere foco
Si es true, el comando de voz solo activará interactable si y solo si ya tiene el foco de un puntero. Si es false, interactable actuará como agente de escucha global para el comando de voz seleccionado. El comportamiento predeterminado es true, ya que varios agentes de escucha de voz globales pueden ser difíciles de organizar en una escena.
Esta propiedad se puede configurar en tiempo de ejecución en código a través de Interactable.VoiceRequiresFocus
.
Modo de selección
Esta propiedad define la lógica de selección. Cuando se hace clic en interactable , itera en un siguiente nivel de dimensión .
Dimensiones es similar a la clasificación y define un estado fuera de las entradas (es decir, foco, pulsar, etc.). Son útiles para definir estados toggle u otros estados de clasificación múltiple asociados a un botón. Se realiza un seguimiento del nivel de dimensión actual mediante Interactable.DimensionIndex
.
Los modos de selección disponibles son:
- Botón - Dimensiones = 1, fácil de hacer clic en Interactable
- Alternar - Dimensiones = 2, alternativas interactables entre el estado activado/y desactivado
- Dimensión múltiple - Dimensiones>= 3, cada clic aumenta el nivel de dimensión actual + 1. Útil para definir un estado de botón en una lista, etc.
Interactable también permite definir varios temas por dimensión. Por ejemplo, cuando SelectionMode=Toggle, se puede aplicar un tema cuando se anula la selecciónde Interactable y se aplica otro tema cuando se selecciona el componente.
El modo de selección actual se puede consultar en tiempo de ejecución a través de Interactable.ButtonMode
. La actualización del modo en tiempo de ejecución se puede lograr estableciendo la Interactable.Dimensions
propiedad para que coincida con la funcionalidad deseada. Además, se puede acceder a la dimensión actual, útil para los modos Toggle y Multi-Dimension , a través de Interactable.CurrentDimension
.
Perfiles interactables
Los perfiles son elementos que crean una relación entre un GameObject y un tema visual. El perfil define qué contenido manipulará un tema cuando se produzca un cambio de estado.
Los temas funcionan mucho como los materiales. Son objetos que pueden incluir scripts que contienen una lista de propiedades que se asignarán a un objeto en función del estado actual. Los temas también se pueden volver a usar y se pueden asignar entre varios objetos de experiencia de usuario interactables .
Restablecer al destruir
Los temas visuales modifican varias propiedades en un Objeto GameObject de destino, dependiendo de la clase y el tipo de motor de tema seleccionados. Si Restablecer al destruir es true cuando se destruye el componente interactable, el componente restablecerá todas las propiedades modificadas de los temas activos a sus valores originales. De lo contrario, cuando se destruye, el componente Interactable dejará las propiedades modificadas tal y como están. En este último caso, el último estado de los valores se conservará a menos que otro componente externo lo modifique. El valor predeterminado es falso.

Eventos
Cada componente interactable tiene un evento OnClick que se desencadena cuando el componente se selecciona simplemente. Sin embargo, interactable se puede usar para detectar eventos de entrada que no sean solo OnClick.
Haga clic en el botón Agregar evento para agregar un nuevo tipo de definición de receptor de eventos. Una vez agregado, seleccione el tipo de evento deseado.
)
Hay diferentes tipos de receptores de eventos para responder a diferentes tipos de entrada. MRTK incluye el siguiente conjunto de receptores listos para usar.
InteractableAudioReceiver
InteractableOnClickReceiver
InteractableOnFocusReceiver
InteractableOnGrabReceiver
InteractableOnHoldReceiver
InteractableOnPressReceiver
InteractableOnToggleReceiver
InteractableOnTouchReceiver
Se puede crear un receptor personalizado mediante la creación de una nueva clase que extienda ReceiverBase
.
Ejemplo de un receptor de eventos toggle
Receptores interactables
El InteractableReceiver
componente permite definir eventos fuera del componente interactable de origen.
InteractableReceiver escuchará un tipo de evento filtrado desencadenado por otro interactable. Si la propiedad Interactable no está asignada directamente, la propiedad Ámbito de búsqueda define la dirección en la que interactableReceiver escucha eventos que están en sí mismo, en un elemento primario o en un GameObject secundario.
InteractableReceiverList
actúa de forma similar, pero para una lista de eventos coincidentes.

Creación de eventos personalizados
Al igual que los temas visuales, los eventos se pueden ampliar para detectar cualquier patrón de estado o para exponer la funcionalidad.
Los eventos personalizados se pueden crear de dos maneras principales:
Extienda la
ReceiverBase
clase para crear un evento personalizado que se mostrará en la lista desplegable de tipos de eventos. De forma predeterminada, se proporciona un evento de Unity, pero se pueden agregar eventos adicionales de Unity o se puede establecer el evento para ocultar eventos de Unity. Esta funcionalidad permite a un diseñador trabajar con un ingeniero en un proyecto para crear un evento personalizado que el diseñador puede configurar en el editor.Extienda la
ReceiverBaseMonoBehavior
clase para crear un componente de evento completamente personalizado que pueda residir en interactable u otro objeto.ReceiverBaseMonoBehavior
hará referencia a Interactable para detectar cambios de estado.
Ejemplo de ampliación ReceiverBase
La CustomInteractablesReceiver
clase muestra información de estado sobre un objeto Interactable y es un ejemplo de cómo crear un receptor de eventos personalizado.
public CustomInteractablesReceiver(UnityEvent ev) : base(ev, "CustomEvent")
{
HideUnityEvents = true; // hides Unity events in the receiver - meant to be code only
}
Los métodos siguientes son útiles para invalidar o implementar al crear un receptor de eventos personalizado.
ReceiverBase.OnUpdate()
es un método abstracto que se puede usar para detectar patrones de estado o transiciones. Además, los ReceiverBase.OnVoiceCommand()
métodos y ReceiverBase.OnClick()
son útiles para crear lógica de eventos personalizada cuando se selecciona Interactable .
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
}
Mostrar campos de receptor de eventos personalizados en el inspector
Los scripts de ReceiverBase usan InspectorField
atributos para exponer propiedades personalizadas en el inspector. Este es un ejemplo de Vector3, una propiedad personalizada con información sobre herramientas e información de etiqueta. Esta propiedad se mostrará como configurable en el inspector cuando se selecciona un Objeto GameObject interactable y se agrega el tipo receptor de eventos asociado.
[InspectorField(Label = "<Property label>",Tooltip = "<Insert tooltip info>",Type = InspectorField.FieldTypes.Vector3)]
public Vector3 EffectOffset = Vector3.zero;
Uso de Interactable
Crear un botón simple
Se puede crear un botón simple agregando el componente Interactable a un GameObject configurado para recibir eventos de entrada. Puede tener un colisionador en él o en un niño para recibir la entrada. Si usa Interactable con una interfaz de usuario de Unity basada en GameObjects, debe estar en Canvas GameObject.
Lleve el botón un paso más allá, creando un nuevo perfil, asignando el propio GameObject y creando un nuevo tema. Además, use el evento OnClick para que suceda algo.
Nota:
Hacer que un botón se presione requiere el PressableButton
componente. Además, el PhysicalPressEventRouter
componente es necesario para canalizar eventos de prensa al componente interactable .
Crear botones de alternancia y de varias dimensiones
Botón de alternancia
Para hacer que un botón pueda alternar, cambie el Selection Mode
campo para escribir Toggle
. En la sección Perfiles , se agrega un nuevo tema alternado para cada perfil que se usa cuando se activa interactable .
Mientras se establece en SelectionMode
Toggle, la casilla IsToggled se puede usar para establecer el valor predeterminado del control en la inicialización en tiempo de ejecución.
CanSelect significa que Interactable puede ir de desactivado a activado , mientras que CanDeselect significa el inverso.
Los desarrolladores pueden usar las SetToggled
interfaces y IsToggled
para obtener o establecer el estado de alternancia de un interactable mediante código.
// 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;
Alternar colección de botones
Es común tener una lista de botones de alternancia donde solo uno puede estar activo en un momento dado, también conocido como un conjunto radial o botones de radio, etc.
Use el InteractableToggleCollection
componente para habilitar esta funcionalidad. Este control garantiza que solo se activa un elemento Interactable en un momento dado.
RadialSet (Assets/MRTK/SDK/Features/UX/Interactable/Prefabs/RadialSet.prefab) también es un excelente punto de partida listo para usar.
Para crear un grupo de botones radial personalizado:
- Crear varios gameobjects o botones interactables
- Establecer cada interactable con SelectionMode = Toggle, CanSelect = true y CanDeselect = false
- Cree un objeto GameObject primario vacío en todos los elementos interactables y agregue el componente InteractableToggleCollection .
- Agregar todos los interactables a ToggleList en InteractableToggleCollection
- Establezca la propiedad InteractableToggleCollection.CurrentIndex para determinar qué botón está seleccionado de forma predeterminada al principio.

Botón multidimensional
El modo de selección multi dimensiones se usa para crear botones secuenciales o un botón que tiene más de dos pasos, como controlar la velocidad con tres valores, Rápido (1x), Más rápido (2x) o Más rápido (3x).
Con las dimensiones como un valor numérico, se pueden agregar hasta 9 temas para controlar la etiqueta de texto o la textura del botón para cada configuración de velocidad, usando un tema diferente para cada paso.
Cada evento click avanzará en DimensionIndex
1 en tiempo de ejecución hasta que se alcance el Dimensions
valor. A continuación, el ciclo se restablecerá a 0.
Los desarrolladores pueden evaluar DimensionIndex
para determinar qué dimensión está activa actualmente.
// 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();
Creación de interactable en tiempo de ejecución
La interacción se puede agregar fácilmente a cualquier GameObject en tiempo de ejecución. En el ejemplo siguiente se muestra cómo asignar un perfil con un tema visual.
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()
Eventos interactables mediante código
Se puede agregar una acción al evento base Interactable.OnClick
a través de código con el ejemplo siguiente.
public static void AddOnClick(Interactable interactable)
{
interactable.OnClick.AddListener(() => Debug.Log("Interactable clicked"));
}
Use la Interactable.AddReceiver<T>()
función para agregar receptores de eventos dinámicamente en tiempo de ejecución.
En el código de ejemplo siguiente se muestra cómo agregar un InteractableOnFocusReceiver, que escucha el foco enter/exit y, además, definir el código de acción que se realizará cuando se activen las instancias de evento.
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"));
}
En el código de ejemplo siguiente se muestra cómo agregar un InteractableOnToggleReceiver, que escucha las transiciones de estado seleccionadas o deseleccionadas en interactables que pueden alternar y, además, define el código de acción que se debe realizar cuando se activan las instancias de evento.
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"));
}