Elemento Interactivo [Experimental] — MRTK2
Un punto de entrada centralizado simplificado al sistema de entrada MRTK. Contiene métodos de administración de estado, administración de eventos y la lógica de configuración de estado para estados de interacción principales.
Interactive Element es una característica experimental compatible con Unity 2019.3 y versiones posteriores, ya que utiliza una funcionalidad nueva en Unity 2019.3: Serialize Reference.
Inspector de elementos interactivos
Durante el modo de reproducción, el inspector de elementos interactivos proporciona comentarios visuales que indican si el estado actual está activo o no. Si un estado está activo, se resaltará con un color cian. Si el estado no está activo, el color no cambia. Los números junto a los estados del inspector son los valores de estado, si el estado está activo, el valor es 1, si el estado no está activo, el valor es 0.
Estados principales
El elemento interactivo contiene estados principales y admite la adición de estados personalizados. Un estado principal es aquel que ya tiene la lógica de configuración de estado definida en BaseInteractiveElement
. A continuación se muestra una lista de los estados principales actuales controlados por entrada:
Estados principales actuales
Estados principales de interacción cercana y lejana:
Estados principales de interacción cercana:
Estados principales de interacción lejana:
Otros estados principales:
Cómo agregar un estado básico a través del inspector
Vaya a Add Core State (Agregar estado básico ) en el inspector para Interactive Element (Elemento interactivo).
Seleccione el botón Seleccionar estado para elegir el estado principal que se va a agregar. Los estados del menú se ordenan por tipo de interacción.
Abra el plegado Configuración de eventos para ver los eventos y las propiedades asociadas al estado.
Cómo agregar un estado principal a través de script
Use el AddNewState(stateName)
método para agregar un estado principal. Para obtener una lista de los nombres de estado principales disponibles, use la CoreInteractionState
enumeración .
// Add by name or add by CoreInteractionState enum to string
interactiveElement.AddNewState("SelectFar");
interactiveElement.AddNewState(CoreInteractionState.SelectFar.ToString());
Estructura interna de estados
Los estados del elemento interactivo son de tipo InteractionState
. Contiene InteractionState
las siguientes propiedades:
- Nombre: nombre del estado.
- Valor: el valor de estado. Si el estado está activado, el valor de estado es 1. Si el estado está desactivado, el valor de estado es 0.
- Activo: indica si el estado está activo actualmente. El valor de la propiedad Active es true cuando el estado está activado, false si el estado está desactivado.
-
Tipo de interacción: el tipo de interacción de un estado es el tipo de interacción para el que está pensado un estado.
-
None
: no admite ninguna forma de interacción de entrada. -
Near
: compatibilidad con la interacción cercana. La entrada se considera interacción cercana cuando una mano articulada tiene contacto directo con otro objeto de juego, es decir, la posición en la que la mano articulada está cerca de la posición del objeto del juego en el espacio mundial. -
Far
: compatibilidad con la interacción lejana. La entrada se considera interacción lejana cuando no se requiere contacto directo con el objeto del juego. Por ejemplo, la entrada a través del rayo del controlador o la mirada se considera entrada de interacción lejana. -
NearAndFar
: abarca la compatibilidad con la interacción cercana y lejana. -
Other
: compatibilidad con la interacción independiente del puntero.
-
- Configuración de eventos: la configuración de eventos de un estado es el punto de entrada del perfil de eventos serializados.
Todas estas propiedades se establecen internamente en el State Manager
contenido de Interactive Element. Para la modificación de los estados, use los métodos auxiliares siguientes:
Métodos auxiliares de configuración de estado
// Get the InteractionState
interactiveElement.GetState("StateName");
// Set a state value to 1/on
interactiveElement.SetStateOn("StateName");
// Set a state value to 0/off
interactiveElement.SetStateOff("StateName");
// Check if a state is present in the state list
interactiveElement.IsStatePresent("StateName");
// Check whether or not a state is active
interactiveElement.IsStateActive("StateName");
// Add a new state to the state list
interactiveElement.AddNewState("StateName");
// Remove a state from the state list
interactiveElement.RemoveState("StateName");
La obtención de la configuración del evento de un estado es específica del propio estado. Cada estado principal tiene un tipo de configuración de evento específico que se describe a continuación en las secciones que describen cada estado principal.
Este es un ejemplo generalizado de cómo obtener la configuración de eventos de un estado:
// T varies depending on the core state - the specific T's are specified under each of the core state sections
T stateNameEvents = interactiveElement.GetStateEvents<T>("StateName");
Estado predeterminado
El estado Predeterminado siempre está presente en un elemento interactivo. Este estado solo estará activo cuando todos los demás estados no estén activos. Si cualquier otro estado se activa, el estado Predeterminado se establecerá en desactivado internamente.
Un elemento interactivo se inicializa con los estados Default y Focus presentes en la lista de estados. El estado Predeterminado siempre debe estar presente en la lista de estados.
Obtención de eventos de estado predeterminados
Tipo de configuración de eventos para el estado predeterminado: StateEvents
StateEvents defaultEvents = interactiveElement.GetStateEvents<StateEvents>("Default");
defaultEvents.OnStateOn.AddListener(() =>
{
Debug.Log($"{gameObject.name} Default State On");
});
defaultEvents.OnStateOff.AddListener(() =>
{
Debug.Log($"{gameObject.name} Default State Off");
});
Estado del foco
El estado Foco es un estado de interacción cercano y lejano que se puede considerar como la realidad mixta equivalente al mantener el puntero. El factor distintivo entre la interacción cercana y lejana para el estado Focus es el tipo de puntero activo actual. Si el tipo de puntero para el estado Focus es el Puntero Poke, la interacción se considera casi interacción. Si el puntero principal no es el puntero Poke, la interacción se considera interacción lejana. El estado Focus está presente en el elemento interactivo de forma predeterminada.
Comportamiento del
Estado de enfoque del Inspector de
Obtención de eventos de estado de foco
Tipo de configuración de evento para el estado de enfoque: FocusEvents
FocusEvents focusEvents = interactiveElement.GetStateEvents<FocusEvents>("Focus");
focusEvents.OnFocusOn.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Focus On");
});
focusEvents.OnFocusOff.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Focus Off");
});
Enfoque cerca frente al comportamiento lejano del foco
Enfoque cerca del estado
El estado Focus Near se establece cuando se genera un evento de enfoque y el puntero principal es el puntero Poke, una indicación de interacción cercana.
Enfoque cerca del comportamiento del
Centrar el foco cerca
Obtención de eventos de estado focusNear
Tipo de configuración de evento para el estado FocusNear: FocusEvents
FocusEvents focusNearEvents = interactiveElement.GetStateEvents<FocusEvents>("FocusNear");
focusNearEvents.OnFocusOn.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Near Interaction Focus On");
});
focusNearEvents.OnFocusOff.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Near Interaction Focus Off");
});
Estado lejano del foco
El estado Focus Far se establece cuando el puntero principal no es el puntero Poke. Por ejemplo, el puntero de rayo del controlador predeterminado y el puntero GGV (Mirada, Gesto, Voz) se consideran punteros de interacción lejanos.
Estado de enfoque del comportamiento de
Componente de foco del inspector de
Obtención de eventos de estado lejano de foco
Tipo de configuración de eventos para el estado FocusFar: FocusEvents
FocusEvents focusFarEvents = interactiveElement.GetStateEvents<FocusEvents>("FocusFar");
focusFarEvents.OnFocusOn.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Focus On");
});
focusFarEvents.OnFocusOff.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Focus Off");
});
Estado táctil
El estado Touch es un estado de interacción cercano que se establece cuando una mano articulada toca el objeto directamente. Un toque directo significa que el dedo índice de la mano articulada está muy cerca de la posición mundial del objeto. De forma predeterminada, un NearInteractionTouchableVolume
componente se adjunta al objeto si el estado Touch se agrega a la lista de estados. La presencia de un NearInteractionTouchableVolume
componente o NearInteractionTouchable
es necesaria para detectar eventos Touch. La diferencia entre NearInteractionTouchableVolume
y NearInteractionTouchable
es que NearInteractionTouchableVolume
detecta un toque basado en el colisionador del objeto y NearInteractionTouchable
detecta el contacto dentro de un área definida de un plano.
Comportamiento
Componente de
Obtención de eventos de estado táctil
Tipo de configuración de eventos para el estado táctil: TouchEvents
TouchEvents touchEvents = interactiveElement.GetStateEvents<TouchEvents>("Touch");
touchEvents.OnTouchStarted.AddListener((touchData) =>
{
Debug.Log($"{gameObject.name} Touch Started");
});
touchEvents.OnTouchCompleted.AddListener((touchData) =>
{
Debug.Log($"{gameObject.name} Touch Completed");
});
touchEvents.OnTouchUpdated.AddListener((touchData) =>
{
Debug.Log($"{gameObject.name} Touch Updated");
});
Seleccionar estado lejano
El estado Seleccionar extremo es el IMixedRealityPointerHandler
que aparece. Este estado es un estado de interacción lejana que detecta el clic de interacción lejana (pulsación de aire) y se mantiene a través del uso de punteros de interacción lejana, como el puntero de rayo del controlador predeterminado o el puntero GGV. El estado Seleccionar extremo tiene una opción en el plegado de configuración de eventos denominado Global
. Si Global
es true, se IMixedRealityPointerHandler
registra como un controlador de entrada global. No es necesario centrarse en un objeto para desencadenar eventos del sistema de entrada si un controlador está registrado como global. Por ejemplo, si un usuario quiere saber cuándo se realiza el gesto de pulsar o seleccionar en el aire, independientemente del objeto en el foco, establezca Global
en true.
Seleccione Comportamiento de estado
Seleccione Far State Inspector.
Obtención de seleccionar eventos de estado lejano
Tipo de configuración de eventos para el estado SelectFar: SelectFarEvents
SelectFarEvents selectFarEvents = interactiveElement.GetStateEvents<SelectFarEvents>("SelectFar");
selectFarEvents.OnSelectUp.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Pointer Up");
});
selectFarEvents.OnSelectDown.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Pointer Down");
});
selectFarEvents.OnSelectHold.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Pointer Hold");
});
selectFarEvents.OnSelectClicked.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Pointer Clicked");
});
Estado en el que se ha clic
El estado Clicked se desencadena mediante un clic de interacción lejana (Seleccionar estado lejano) de forma predeterminada. Este estado se cambia internamente a activado, invoca el evento OnClicked y, a continuación, se desactiva inmediatamente.
Nota
Los comentarios visuales del inspector basados en la actividad de estado no están presentes para el estado Clicked porque se activa y, a continuación, se desactiva inmediatamente.
Comportamiento de estado en
Haga clic en el componente State Inspector.
Ejemplo de estado con clics cercanos y lejanos
El estado en el que se hace clic se puede desencadenar a través de puntos de entrada adicionales mediante el interactiveElement.TriggerClickedState()
método . Por ejemplo, si un usuario quiere que una interacción cercana toque también desencadene un clic en un objeto, agregaría el TriggerClickedState()
método como agente de escucha en el estado táctil.
Obtención de eventos de estado en los que se hace clic
Tipo de configuración de eventos para el estado clicked: ClickedEvents
ClickedEvents clickedEvent = interactiveElement.GetStateEvents<ClickedEvents>("Clicked");
clickedEvent.OnClicked.AddListener(() =>
{
Debug.Log($"{gameObject.name} Clicked");
});
Activar y desactivar el estado
Los estados Toggle On y Toggle Off son un par y ambos deben estar presentes para el comportamiento de alternancia. De forma predeterminada, los estados Activar y Desactivar alternancia se desencadenan a través de un clic de interacción lejana (Seleccionar estado lejano). De forma predeterminada, el estado Alternar desactivado está activo al iniciar, lo que significa que el botón de alternancia se inicializará en desactivado. Si un usuario quiere que el estado Alternar activado esté activo al iniciarse, en el estado Toggle On (Activar activado) establecido IsSelectedOnStart
en true.
ToggleOn y Toggle Off State Behavior (Activar y desactivar el comportamiento del estado)
ToggleOn y Toggle Off State Inspector
Ejemplo de estados de alternancia cerca y lejos
De forma similar al estado Clicked, la configuración de alternancia de estado puede tener varios puntos de entrada mediante el interactiveElement.SetToggleStates()
método . Por ejemplo, si un usuario quiere tocar como un punto de entrada adicional para establecer los estados de alternancia, agrega el SetToggleStates()
método a uno de los eventos en estado Touch.
Activar y desactivar eventos de estado
Tipo de configuración de eventos para el estado ToggleOn: ToggleOnEvents
Tipo de configuración de evento para el estado ToggleOff: ToggleOffEvents
// Toggle On Events
ToggleOnEvents toggleOnEvent = interactiveElement.GetStateEvents<ToggleOnEvents>("ToggleOn");
toggleOnEvent.OnToggleOn.AddListener(() =>
{
Debug.Log($"{gameObject.name} Toggled On");
});
// Toggle Off Events
ToggleOffEvents toggleOffEvent = interactiveElement.GetStateEvents<ToggleOffEvents>("ToggleOff");
toggleOffEvent.OnToggleOff.AddListener(() =>
{
Debug.Log($"{gameObject.name} Toggled Off");
});
Estado de palabra clave de voz
El estado de palabra clave de voz escucha las palabras clave definidas en el perfil de voz de Mixed Reality. Cualquier palabra clave nueva DEBE registrarse en el perfil de comando de voz antes del tiempo de ejecución (pasos siguientes).
Palabra clave Speech State Behavior
Componente de palabra clave speech State Inspector
Nota
El estado de palabra clave de voz se desencadenó en el editor presionando la tecla F5 en el gif anterior. La configuración en las pruebas del editor para la voz se describe en los pasos siguientes.
Registro de una palabra clave o comando de voz
Seleccionar el objeto de juego MixedRealityToolkit
Seleccione Copiar y personalizar el perfil actual.
Vaya a la sección Entrada y seleccione Clonar para habilitar la modificación del perfil de entrada.
Desplácese hacia abajo hasta la sección Voz del perfil de entrada y clone el perfil de voz.
Seleccione Add a New Speech Command (Agregar un nuevo comando de voz).
Escriba la nueva palabra clave. Opcional: cambie KeyCode a F5 (u otro keyCode) para permitir las pruebas en el editor.
Volver al inspector de estado de palabra clave de voz del elemento interactivo y seleccione Agregar palabra clave.
Escriba la nueva palabra clave que se acaba de registrar en el perfil de voz.
Para probar el estado de la palabra clave de voz en el editor, presione keyCode que se definió en el paso 6 (F5) para simular el evento reconocido de palabra clave de voz.
Obtención de eventos de estado de palabra clave de voz
Tipo de configuración de eventos para el estado SpeechKeyword: SpeechKeywordEvents
SpeechKeywordEvents speechKeywordEvents = interactiveElement.GetStateEvents<SpeechKeywordEvents>("SpeechKeyword");
speechKeywordEvents.OnAnySpeechKeywordRecognized.AddListener((speechEventData) =>
{
Debug.Log($"{speechEventData.Command.Keyword} recognized");
});
// Get the "Change" Keyword event specifically
KeywordEvent keywordEvent = speechKeywordEvents.Keywords.Find((keyword) => keyword.Keyword == "Change");
keywordEvent.OnKeywordRecognized.AddListener(() =>
{
Debug.Log("Change Keyword Recognized");
});
Estados personalizados
Cómo crear un estado personalizado mediante inspector
El estado personalizado creado a través del inspector se inicializará con la configuración de eventos de estado predeterminada. La configuración de eventos predeterminada para un estado personalizado es de tipo StateEvents
y contiene los eventos OnStateOn y OnStateOff.
Vaya a Crear estado personalizado en el inspector para el elemento interactivo.
Escriba el nombre del nuevo estado. Este nombre debe ser único y no puede ser el mismo que los estados principales existentes.
Seleccione Establecer nombre de estado para agregar a la lista de estados.
Este estado personalizado se inicializa con la configuración de eventos predeterminada
StateEvents
que contiene losOnStateOn
eventos yOnStateOff
. Para crear una configuración de eventos personalizada para un nuevo estado, consulte Creación de un estado personalizado con una configuración de eventos personalizados.
Creación de un estado personalizado mediante script
interactiveElement.AddNewState("MyNewState");
// A new state by default is initialized with a the default StateEvents configuration which contains the
// OnStateOn and OnStateOff events
StateEvents myNewStateEvents = interactiveElement.GetStateEvents<StateEvents>("MyNewState");
myNewStateEvents.OnStateOn.AddListener(() =>
{
Debug.Log($"MyNewState is On");
});
Creación de un estado personalizado con una configuración de eventos personalizada
Los archivos de ejemplo de un estado personalizado denominado Keyboard se encuentran aquí: MRTK\SDK\Experimental\InteractiveElement\Examples\Scripts\CustomStateExample
Los pasos siguientes le guiarán por un ejemplo existente de creación de una configuración de eventos de estado personalizado y archivos receptores.
Piense en un nombre de estado. Este nombre debe ser único y no puede ser el mismo que los estados principales existentes. Para los fines de este ejemplo, el nombre de estado será Teclado.
Cree dos archivos .cs denominados nombre de estado + "Receiver" y nombre de estado + "Events". La nomenclatura de estos archivos se tiene en cuenta internamente y debe seguir el nombre de estado + Convención de receptor/evento.
Consulte los archivos KeyboardEvents.cs y KeyboardReceiver.cs para obtener más detalles sobre el contenido del archivo. Las nuevas clases de configuración de eventos deben heredar de
BaseInteractionEventConfiguration
y las nuevas clases receptoras de eventos deben heredar deBaseEventReceiver
. Los ejemplos de la configuración de estado para el estado teclado se encuentran en elCustomStateSettingExample.cs
archivo.Agregue el estado al elemento interactivo con el nombre de estado, el nombre de estado se reconocerá si existen archivos de configuración de eventos y receptores de eventos. Las propiedades del archivo de configuración de eventos personalizados deben aparecer en el inspector.
Para obtener más ejemplos de archivos de configuración de eventos y receptores de eventos, consulte los archivos en estas rutas de acceso:
- MRTK\SDK\Experimental\InteractiveElement\InteractiveElement\Events\EventConfigurations
- MRTK\SDK\Experimental\InteractiveElement\InteractiveElement\Events\EventReceivers
Escena de ejemplo
La escena de ejemplo del visualizador de elementos interactivos y estado se encuentra aquí: MRTK\SDK\Experimental\InteractiveElement\Examples\InteractiveElementExampleScene.unity
Botón comprimible
La escena de ejemplo contiene objetos prefabricados denominados CompressableButton
y CompressableButtonToggle
, estos objetos prefabricados reflejan el comportamiento de los PressableButtonHoloLens2
botones, que se construyen mediante el elemento interactivo y el visualizador de estado.
El CompressableButton
componente es actualmente una combinación de PressableButton
+ PressableButtonHoloLens2
con BaseInteractiveElement
como una clase base.
Visualizador de estado [Experimental]
El componente Visualizador de estado agrega animaciones a un objeto basado en los estados definidos en un componente de elemento interactivo vinculado. Este componente crea activos de animación, los coloca en la carpeta MixedRealityToolkit.Generated y habilita la configuración simplificada del fotograma clave de animación mediante la adición de propiedades animables a un objeto de juego de destino. Para habilitar las transiciones de animación entre estados, se crea un recurso controlador de animadores y se genera una máquina de estado predeterminada con los parámetros asociados y las transiciones de estado. La máquina de estado se puede ver en la ventana Animator de Unity.
Visualizador de estado y sistema de animación de Unity
El visualizador de estado aprovecha actualmente el sistema de animación de Unity.
Cuando se presiona el botón Generar nuevos clips de animación en el visualizador de estado, se generan nuevos recursos de clip de animación basados en los nombres de estado del elemento interactivo y se colocan en la carpeta MixedRealityToolkit.Generated. La propiedad Clip de animación de cada contenedor de estado se establece en el clip de animación asociado.
También se genera una máquina de estado de animador para administrar transiciones fluidas entre clips de animación. De forma predeterminada, la máquina de estado utiliza el estado Any Para permitir las transiciones entre cualquier estado de Interactive Element.
Los visualizadores de estado desencadenados en el animador también se generan para cada estado, los parámetros del desencadenador se usan en el Visualizador de estado para desencadenar una animación.
Limitaciones en tiempo de ejecución
El visualizador de estado debe agregarse a un objeto a través del Inspector y no se puede agregar a través del script. Las propiedades que modifican AnimatorStateMachine/AnimationController se encuentran en un espacio de nombres del editor (UnityEditor.Animations
) que se quita cuando se compila la aplicación.
Cómo usar el visualizador de estado
Crear un cubo
Elemento Attach Interactive
Adjuntar visualizador de estado
Seleccione Generate New Animation Clips (Generar nuevos clips de animación).
En el contenedor de estado de enfoque, seleccione Agregar destino.
Arrastre el objeto de juego actual al campo de destino.
Abrir el plegado Propiedades animables de cubo
Seleccione el menú desplegable De la propiedad Animatable y seleccione Color.
Seleccione Agregar la propiedad Animatable de color.
Elegir un color
Presione reproducir y observe el cambio de color transitorio
Propiedades que se pueden animar
El propósito principal de las propiedades animables es simplificar la configuración del fotograma clave del clip de animación. Si un usuario está familiarizado con el sistema de animación de Unity y prefiere establecer directamente fotogramas clave en los clips de animación generados, simplemente no puede agregar propiedades animables a un objeto de destino y abrir el clip en la ventana Animación de Unity (Animación de > animación de Windows>).
Si usa las propiedades Animatable para la animación, el tipo de curva se establece en EaseInOut.
Propiedades animables actuales:
- Desplazamiento de escala
- Desplazamiento de posición
- Color
- Color del sombreador
- Sombreador Float
- Vector de sombreador
Desplazamiento de escala
La propiedad Animatable Scale Offset toma la escala actual del objeto y agrega el desplazamiento definido.
Desplazamiento de posición
La propiedad Position Offset Animatable toma la posición actual del objeto y agrega el desplazamiento definido.
Color
La propiedad Color Animatable representa el color principal de un material si el material tiene una propiedad de color principal. Esta propiedad anima la material._Color
propiedad .
Color del sombreador
La propiedad Animatable Color de sombreador hace referencia a una propiedad de sombreador de color de tipo. Se requiere un nombre de propiedad para todas las propiedades del sombreador. El gif siguiente muestra cómo animar una propiedad de color de sombreador denominada Fill_Color que no es el color principal del material. Observe los valores cambiantes en el inspector de material.
Sombreador Float
La propiedad Shader Float Animatable hace referencia a una propiedad de sombreador de tipo float. Se requiere un nombre de propiedad para todas las propiedades del sombreador. En el gif siguiente, observe los valores cambiantes en el inspector de material para la propiedad Metalizada.
Vector de sombreador
La propiedad Animatable vector de sombreador hace referencia a una propiedad de sombreador de tipo Vector4. Se requiere un nombre de propiedad para todas las propiedades del sombreador. En el gif siguiente, observe los valores cambiantes del inspector de material para la propiedad Tiling (Main Tex_ST).
Cómo buscar nombres de propiedad de sombreador animables
Vaya a Animación de animación > de ventana >
Asegúrese de que el objeto con el visualizador de estado está seleccionado en la jerarquía.
Seleccionar cualquier clip de animación en la ventana Animación
Seleccione Agregar propiedad y abra el plegado del representador de malla.
Esta lista contiene los nombres de todos los nombres de propiedad Animatable.