Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Die Interactable Komponente ist ein All-in-One-Container, damit jedes Objekt einfach interagierbar ist und auf Eingaben reagiert. Interagierbar fungiert als Sammelaktion für alle Arten von Eingaben, einschließlich Toucheingaben, Handstrahlen, Sprache usw. und leiten diese Interaktionen in Ereignisse und visuelle Designantworten ein. Diese Komponente bietet eine einfache Möglichkeit, Schaltflächen zu erstellen, die Farbe von Objekten mit Fokus zu ändern und vieles mehr.
Konfigurieren von Interagierbarem
Die Komponente ermöglicht drei primäre Konfigurationsabschnitte:
- Allgemeine Eingabekonfiguration
- Visuelle Designs , die auf mehrere GameObjects ausgerichtet sind
- Ereignishandler
Allgemeine Eingabeeinstellungen
Zustände
Status ist ein ScriptableObject-Parameter , der die Interaktionsphasen wie Drücken oder Beobachtet für interagierbare Profile und visuelle Designs definiert.
DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) wird standardmäßig mit MRTK ausgeliefert und ist der Standardparameter für interaktive Komponenten.
Das DefaultInteractableStates-Objekt enthält vier Zustände und verwendet die InteractableStates Zustandsmodellimplementierung.
Standard: Es geschieht nichts, dies ist der isolierteste Basiszustand.
Fokus: Auf das Objekt wird gezeigt. Dies ist ein einzelner Zustand, es sind derzeit keine anderen Zustände festgelegt, aber er hat den Rang "Standard".
Drücken: Auf das Objekt wird gezeigt, und eine Taste oder Hand wird gedrückt. Der Press state out rangiert in den Rängen Standard und Fokus. Dieser Zustand wird auch als Fallback auf Physisches Drücken festgelegt.
Deaktiviert: Die Schaltfläche sollte nicht interaktiv sein, und visuelles Feedback informiert den Benutzer darüber, ob diese Schaltfläche aus irgendeinem Grund derzeit nicht verwendet werden kann. Theoretisch könnte der Status Deaktiviert alle anderen Zustände enthalten, aber wenn Aktiviert deaktiviert ist, übertrumpft der Status Deaktiviert alle anderen Zustände.
Abhängig von der Reihenfolge in der Liste wird dem Status ein Bitwert (#) zugewiesen.
Hinweis
Es wird im Allgemeinen empfohlen, beim Erstellen interagierbarer Komponenten DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) zu verwenden.
Es sind jedoch 17 interagierbare Zustände verfügbar, die zum Steuern von Designs verwendet werden können, obwohl einige von anderen Komponenten gesteuert werden sollen. Im Folgenden finden Sie eine Liste derjenigen mit integrierter Funktionalität.
- Besucht: Auf das Interaktive Objekt wurde geklickt.
- Umschalten: Die Schaltfläche befindet sich in einem umgeschalteten Zustand, oder der Dimensionsindex ist eine ungerade Zahl.
- Geste: Die Hand oder der Controller wurde gedrückt und von der ursprünglichen Position verschoben.
- VoiceCommand: Ein Sprachbefehl wurde verwendet, um die Interaktion auszulösen.
- PhysicalTouch: Eine Toucheingabe wird derzeit erkannt, verwenden Sie
NearInteractionTouchablezum Aktivieren. - Grab: Eine Hand greift derzeit in den Begrenzungen des Objekts. Verwenden Sie
NearInteractionGrabbablezum Aktivieren von
Enabled
Schaltet ein, ob ein interaktives Objekt aktiviert wird oder nicht. Dies entspricht dem Interactable.IsEnabled im Code.
Die aktivierte Eigenschaft eines Interactable-Objekts unterscheidet sich von der aktivierten Eigenschaft, die über GameObject/Component (z. B. SetActive usw.) konfiguriert wurde. Durch das Deaktivieren von GameObject oder Interactable MonoBehaviour wird die Ausführung aller Elemente in der Klasse deaktiviert, einschließlich Eingaben, visuellen Designs, Ereignissen usw. Wenn Sie über Interactable.IsEnabled deaktivieren, werden die meisten Eingabebehandlungen deaktiviert und verwandte Eingabezustände zurückgesetzt. Die -Klasse führt jedoch weiterhin jeden Frame aus und empfängt Eingabeereignisse, die ignoriert werden. Dies ist nützlich für die Anzeige des Interagierbaren in einem deaktivierten Zustand, der über visuelle Designs erfolgen kann. Ein typisches Beispiel hierfür wäre eine Absenden-Schaltfläche, die darauf wartet, dass alle erforderlichen Eingabefelder abgeschlossen sind.
Eingabeaktionen
Wählen Sie die Eingabeaktion aus der Eingabekonfiguration oder dem Controllerzuordnungsprofil aus, auf die die Interaktionskomponente reagieren soll.
Diese Eigenschaft kann zur Laufzeit im Code über Interactable.InputActionkonfiguriert werden.
IsGlobal
Wenn true, wird die Komponente als globaler Eingabelistener für die ausgewählte Eingabeaktion markiert. Das Standardverhalten ist false, wodurch die Eingabe nur auf diesen interagierbaren Collider/GameObject beschränkt wird.
Diese Eigenschaft kann zur Laufzeit im Code über Interactable.IsGlobalkonfiguriert werden.
Sprachbefehl
Sprachbefehl aus dem MRTK-Sprachbefehlsprofil, um ein OnClick-Ereignis für die Sprachinteraktion auszulösen.
Diese Eigenschaft kann zur Laufzeit im Code über Interactable.VoiceCommandkonfiguriert werden.
Erfordert Fokus
Bei "true" wird der Sprachbefehl nur dann aktiviert, wenn der Fokus bereits über einen Zeiger verfügt. False gibt an, dass der Interaktive als globaler Listener für den ausgewählten Sprachbefehl fungiert. Das Standardverhalten ist true, da mehrere globale Sprachlistener in einer Szene schwer zu organisieren sein können.
Diese Eigenschaft kann zur Laufzeit im Code über Interactable.VoiceRequiresFocuskonfiguriert werden.
Auswahlmodus
Diese Eigenschaft definiert die Auswahllogik. Wenn auf ein Interagierbares geklickt wird, wird es in eine nächste Dimensionsebene durchlaufen.
Dimensionen ähneln der Rangfolge und definieren einen Zustand außerhalb von Eingaben (z. B. Fokus, Drücken usw.). Sie sind nützlich zum Definieren von Umschaltzuständen oder anderen Zuständen mit mehreren Rangfolgen, die einer Schaltfläche zugeordnet sind. Die aktuelle Dimensionsebene wird von Interactable.DimensionIndexnachverfolgt.
Folgende Auswahlmodi sind verfügbar:
- Schaltfläche - Dimensionen = 1, einfach anklickbar Interagierbar
- Umschalten - Dimensionen = 2, Interagierbare Alternativen zwischen dem Aus-Zustand/
- Mehrdimensionale Dimensionen - Dimensionen>= 3, bei jedem Klick wird die aktuelle Dimensionsebene + 1 erhöht. Nützlich zum Definieren eines Schaltflächenzustands für eine Liste usw.
Interagierbar ermöglicht auch die Definition mehrerer Designs pro Dimension. Wenn Sie beispielsweise SelectionMode=Toggle verwenden, kann ein Design angewendet werden, wenn die Option Interagierbardeaktiviert wird, und ein anderes Design, wenn die Komponente ausgewählt wird.
Der aktuelle Auswahlmodus kann zur Laufzeit über Interactable.ButtonModeabgefragt werden. Das Aktualisieren des Modus zur Laufzeit kann erreicht werden, indem die Interactable.Dimensions -Eigenschaft so festgelegt wird, dass sie der gewünschten Funktionalität entspricht. Darüber hinaus kann über Interactable.CurrentDimensionauf die aktuelle Dimension zugegriffen werden, die für die Modi Umschalten und Mehrdimension nützlich ist.
Interagierbare Profile
Profile sind Elemente, die eine Beziehung zwischen einem GameObject und einem visuellen Design erstellen. Das Profil definiert, welche Inhalte von einem Design bearbeitet werden, wenn eine Zustandsänderung eintritt.
Designs funktionieren sehr ähnlich wie Materialien. Dabei handelt es sich um skriptfähige Objekte, die eine Liste von Eigenschaften enthalten, die einem Objekt basierend auf dem aktuellen Zustand zugewiesen werden. Designs können auch wiederverwendbar und über mehrere interaktive UX-Objekte hinweg zugewiesen werden.
Zurücksetzen bei Zerstörung
Visuelle Designs ändern verschiedene Eigenschaften eines GameObject-Zielobjekts, abhängig von der Klasse und dem Typ der ausgewählten Design-Engine. Wenn Reset On Destroy true ist, wenn die Interaktivierbare Komponente zerstört wird, setzt die Komponente alle geänderten Eigenschaften aus aktiven Designs auf ihre ursprünglichen Werte zurück. Andernfalls belässt die Interagierbare Komponente bei der Zerstörung alle geänderten Eigenschaften unverändert. In diesem letzteren Fall bleibt der letzte Zustand von Werten bestehen, es sei denn, es wird von einer anderen externen Komponente geändert. Der Standardwert ist „false“.
Ereignisse
Jede interaktionsfähige Komponente verfügt über ein OnClick-Ereignis , das ausgelöst wird, wenn die Komponente einfach ausgewählt wird. Interactable kann jedoch verwendet werden, um andere Eingabeereignisse als nur OnClick zu erkennen.
Klicken Sie auf die Schaltfläche Ereignis hinzufügen , um einen neuen Typ der Ereignisempfängerdefinition hinzuzufügen. Wählen Sie nach dem Hinzufügen den gewünschten Ereignistyp aus.
)
Es gibt verschiedene Arten von Ereignisempfängern, um auf verschiedene Eingabetypen zu reagieren. MRTK wird standardmäßig mit den folgenden Empfängern ausgeliefert.
InteractableAudioReceiverInteractableOnClickReceiverInteractableOnFocusReceiverInteractableOnGrabReceiverInteractableOnHoldReceiverInteractableOnPressReceiverInteractableOnToggleReceiverInteractableOnTouchReceiver
Ein benutzerdefinierter Empfänger kann erstellt werden, indem eine neue Klasse erstellt wird, die erweitert ReceiverBase.
Beispiel für einen Toggle-Ereignisempfänger
Interaktionsfähige Empfänger
Die InteractableReceiver Komponente ermöglicht die Definition von Ereignissen außerhalb der interagierbaren Quellkomponente.
InteractableReceiver lauscht auf einen gefilterten Ereignistyp, der von einem anderen Interactable ausgelöst wird. Wenn die Interactable-Eigenschaft nicht direkt zugewiesen wird, definiert die Suchbereich-Eigenschaft die Richtung, in der interactableReceiver auf Ereignisse lauscht, die sich entweder auf sich selbst, in einem übergeordneten oder in einem untergeordneten GameObject befinden.
InteractableReceiverList verhält sich auf ähnliche Weise, aber für eine Liste übereinstimmende Ereignisse.
Erstellen benutzerdefinierter Ereignisse
Wie visuelle Designs können Ereignisse erweitert werden, um ein beliebiges Zustandsmuster zu erkennen oder Funktionen verfügbar zu machen.
Benutzerdefinierte Ereignisse können hauptsächlich auf zwei Arten erstellt werden:
Erweitern Sie die
ReceiverBase-Klasse, um ein benutzerdefiniertes Ereignis zu erstellen, das in der Dropdownliste der Ereignistypen angezeigt wird. Standardmäßig wird ein Unity-Ereignis bereitgestellt, aber es können zusätzliche Unity-Ereignisse hinzugefügt oder das Ereignis so festgelegt werden, dass Unity-Ereignisse ausgeblendet werden. Diese Funktion ermöglicht es einem Designer, mit einem Techniker an einem Projekt zusammenzuarbeiten, um ein benutzerdefiniertes Ereignis zu erstellen, das der Designer im Editor einrichten kann.Erweitern Sie die
ReceiverBaseMonoBehavior-Klasse, um eine vollständig benutzerdefinierte Ereigniskomponente zu erstellen, die sich auf dem Interactable-Objekt oder einem anderen Objekt befinden kann. DerReceiverBaseMonoBehaviorverweist auf das Interagierbare , um Zustandsänderungen zu erkennen.
Beispiel für die Erweiterung ReceiverBase
Die CustomInteractablesReceiver -Klasse zeigt status Informationen zu einem Interactable-Objekt an und ist ein Beispiel für das Erstellen eines benutzerdefinierten Ereignisempfängers.
public CustomInteractablesReceiver(UnityEvent ev) : base(ev, "CustomEvent")
{
HideUnityEvents = true; // hides Unity events in the receiver - meant to be code only
}
Die folgenden Methoden sind nützlich, um beim Erstellen eines benutzerdefinierten Ereignisempfängers zu überschreiben/zu implementieren.
ReceiverBase.OnUpdate() ist eine abstrakte Methode, die verwendet werden kann, um Zustandsmuster/Übergänge zu erkennen. Darüber hinaus sind die ReceiverBase.OnVoiceCommand() Methoden und ReceiverBase.OnClick() nützlich, um benutzerdefinierte Ereignislogik zu erstellen, wenn interagierbar ausgewählt ist.
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
}
Anzeigen benutzerdefinierter Ereignisempfängerfelder im Inspektor
ReceiverBase-Skripts verwenden InspectorField Attribute, um benutzerdefinierte Eigenschaften im Inspektor verfügbar zu machen. Hier sehen Sie ein Beispiel für Vector3, eine benutzerdefinierte Eigenschaft mit QuickInfo und Bezeichnungsinformationen. Diese Eigenschaft wird im Inspektor als konfigurierbar angezeigt, wenn ein interagierbares GameObject ausgewählt ist und der zugeordnete Ereignisempfängertyp hinzugefügt wird.
[InspectorField(Label = "<Property label>",Tooltip = "<Insert tooltip info>",Type = InspectorField.FieldTypes.Vector3)]
public Vector3 EffectOffset = Vector3.zero;
Verwenden von Interagierbarem
Erstellen einer einfachen Schaltfläche
Sie können eine einfache Schaltfläche erstellen, indem Sie die Interaktionskomponente zu einem GameObject hinzufügen, das für den Empfang von Eingabeereignissen konfiguriert ist. Es kann einen Collider darauf oder auf einem untergeordneten Element haben, um Eingaben zu empfangen. Wenn Sie Interactable mit einem auf der Unity-Benutzeroberfläche basierenden GameObjects verwenden, sollte es sich unter dem Canvas GameObject befinden.
Gehen Sie mit der Schaltfläche einen Schritt weiter, indem Sie ein neues Profil erstellen, das GameObject selbst zuweisen und ein neues Design erstellen. Verwenden Sie außerdem das OnClick-Ereignis , um etwas zu bewirken.
Hinweis
Damit eine Schaltfläche gedrückt werden kann , ist die PressableButton -Komponente erforderlich. Darüber hinaus ist die PhysicalPressEventRouter -Komponente erforderlich, um Pressereignisse an die interaktionsfähige Komponente zu leiten.
Erstellen von Umschalt- und Mehrdimensionsschaltflächen
Umschaltfläche
Um eine Schaltfläche umschaltfähig zu machen, ändern Sie das Selection Mode Feld in den Typ Toggle. Im Abschnitt Profile wird ein neues umschaltbares Design für jedes Profil hinzugefügt, das verwendet wird, wenn interagierbar aktiviert wird.
Während auf SelectionMode Umschalten festgelegt ist, kann das Kontrollkästchen IsToggled verwendet werden, um den Standardwert des Steuerelements bei der Laufzeitinitialisierung festzulegen.
CanSelect bedeutet, dass das Interaktive von "Aus " nach "Ein " wechseln kann, während "CanDeselect " die Umkehrung bedeutet.
Entwickler können die SetToggled Schnittstellen und IsToggled verwenden, um den Umschaltzustand eines Interagierbaren über Code abzurufen bzw. festzulegen.
// 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;
Schaltflächensammlung umschalten
Es ist üblich, eine Liste von Umschaltflächen zu haben, bei denen nur eine zu einem bestimmten Zeitpunkt aktiv sein kann, auch bekannt als radialer Satz oder Optionsfelder usw.
Verwenden Sie die InteractableToggleCollection -Komponente, um diese Funktionalität zu aktivieren. Dieses Steuerelement stellt sicher, dass zu einem bestimmten Zeitpunkt nur ein Interaktionssteuerelement aktiviert wird. Das RadialSet (Assets/MRTK/SDK/Features/UX/Interactable/Prefabs/RadialSet.prefab) ist ebenfalls ein hervorragender Ausgangspunkt.
So erstellen Sie eine benutzerdefinierte radiale Schaltflächengruppe:
- Erstellen mehrerer interagierbarer GameObjects/Schaltflächen
- Legen Sie jedes Interagierbare mit SelectionMode = Umschalten, CanSelect = true und CanDeselect = false fest.
- Erstellen Sie ein leeres übergeordnetes GameObject für alle Interactables, und fügen Sie die InteractableToggleCollection-Komponente hinzu.
- Hinzufügen aller Interactables zur ToggleList für InteractableToggleCollection
- Legen Sie die InteractableToggleCollection.CurrentIndex-Eigenschaft fest, um zu bestimmen, welche Schaltfläche beim Start standardmäßig ausgewählt ist.
Mehrdimensionale Schaltfläche
Der Auswahlmodus mit mehreren Dimensionen wird verwendet, um sequenzielle Schaltflächen oder eine Schaltfläche mit mehr als zwei Schritten zu erstellen, z. B. die Steuerung der Geschwindigkeit mit drei Werten, Schnell (1x), Schneller (2x) oder Schnellster (3x).
Wenn Dimensionen ein numerischer Wert sind, können bis zu 9 Designs hinzugefügt werden, um die Textbeschriftung oder Textur der Schaltfläche für jede Geschwindigkeitseinstellung zu steuern, wobei für jeden Schritt ein anderes Design verwendet wird.
Jedes Klickereignis wird zur DimensionIndex Laufzeit um 1 vorgefahren, bis der Dimensions Wert erreicht ist. Anschließend wird der Zyklus auf 0 zurückgesetzt.
Entwickler können bewerten DimensionIndex , um zu bestimmen, welche Dimension derzeit aktiv ist.
// 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();
Erstellen von Interagierbar zur Laufzeit
Interagierbar kann zur Laufzeit ganz einfach zu jedem GameObject hinzugefügt werden. Im folgenden Beispiel wird veranschaulicht, wie Sie ein Profil mit einem visuellen Design zuweisen.
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()
Interagierbare Ereignisse über Code
Mit dem folgenden Beispiel kann dem Basisereignis Interactable.OnClick über Code eine Aktion hinzugefügt werden.
public static void AddOnClick(Interactable interactable)
{
interactable.OnClick.AddListener(() => Debug.Log("Interactable clicked"));
}
Verwenden Sie die Interactable.AddReceiver<T>() -Funktion, um Ereignisempfänger dynamisch zur Laufzeit hinzuzufügen.
Der folgende Beispielcode veranschaulicht, wie Sie einen InteractableOnFocusReceiver hinzufügen, der auf das Eingeben/Beenden des Fokus lauscht, und darüber hinaus Aktionscode definieren, der ausgeführt werden soll, wenn die Ereignisinstanzen ausgelöst werden.
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"));
}
Der folgende Beispielcode veranschaulicht, wie ein InteractableOnToggleReceiver hinzugefügt wird, der auf ausgewählte/nicht ausgewählte Zustandsübergänge auf umschaltbaren interagierbaren Geräten lauscht und darüber hinaus Aktionscode definiert, der ausgeführt werden soll, wenn die Ereignisinstanzen ausgelöst werden.
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"));
}