Was ist ein Zielsystem und warum sollte man eines verwenden?
Ein Zielsystem, manchmal auch Eye-Target- oder Interaktionssystem genannt, ersetzt den traditionellen Ansatz, eine Taste zu drücken, während man sich in der Nähe von etwas befindet. Anstatt auf einen NPC zuzugehen und E zu drücken und zu hoffen, dass man nahe genug ist, halten Spieler eine Taste (normalerweise die linke Alt-Taste) gedrückt, um in den Zielmodus zu gelangen, der ein kleines Fadenkreuz in der Mitte des Bildschirms anzeigt. Wenn sich das Fadenkreuz über einem anvisierbaren Objekt, Objekt oder einer Zone befindet, wird ein Menü mit verfügbaren Aktionen angezeigt. Dieser Ansatz ist wesentlich intuitiver, da er den Spielern eine präzise Kontrolle darüber gibt, womit sie interagieren. In einer überfüllten Szene mit mehreren NPCs, Fahrzeugen und Objekten kannst du mit einem Zielsystem genau das auswählen, was du möchtest, ohne sich mit überlappenden Interaktionsaufforderungen auseinandersetzen zu müssen. Die beiden beliebtesten Implementierungen sind ox_target (vom Overextended-Team) und qb-target (entwickelt für QBCore). Dieser Leitfaden behandelt beides, wobei der Schwerpunkt auf ox_target liegt, da es Framework-unabhängig ist und aktiver weiterentwickelt wird.
ox_target vs. qb-target: Was du wählen sollten
Beide Systeme erreichen das gleiche Ziel, unterscheiden sich jedoch im API-Design und in der Leistung. ox_target ist eigenständig, funktioniert mit jedem Framework, nutzt Raycasting zur Entitätserkennung und verfügt über eine sauberere API mit besserer TypeScript-Unterstützung. qb-target ist eng in QBCore integriert, verwendet einen ähnlichen Raycast-Ansatz und gibt es schon länger, sodass mehr vorhandene Scripts es sofort unterstützen. Wenn du einen neuen Server starten oder ESX/Standalone verwenden, verwende ox_target. Wenn du QBCore verwenden und die meisten deiner gekauften Scripts qb-target-Exporte verwenden, vermeidet das Festhalten an qb-target Kompatibilitätsprobleme. Die gute Nachricht ist, dass ox_target eine qb-target-Kompatibilitätsschicht enthält, sodass Scripts, die exports['qb-target'] aufrufen, mit installiertem ox_target funktionieren. Das Gegenteil ist jedoch nicht der Fall, sodass für ox_target geschriebene Scripts ohne Änderungen nicht mit qb-target funktionieren.
Ziele zu bestimmten Entitäten hinzufügen
Entitätsziele verbinden Interaktionsoptionen mit einer bestimmten erzeugten Entität wie einem Fußgänger, einem Fahrzeug oder einem Objekt. Dies ist nützlich, wenn du einen NPC für einen Job erstellen und möchten, dass Spieler gezielt mit diesem NPC interagieren und nicht mit irgendeinem Ped-Modell auf der Welt. Das Ziel folgt der Entität. Wenn der NPC also herumläuft, bewegt sich der Interaktionspunkt mit ihm. Du geben das Entitätshandle, das Optionsarray und einen optionalen Abstand an, der steuert, wie weit das Fadenkreuz das Entitätsobjekt erkennen kann. Bereinige Entitätsziele immer, wenn die Entität gelöscht oder die Ressource angehalten wird, um zu verhindern, dass verwaiste Ziele im Speicher verbleiben.
Modellbasierte Ziele: Ausrichtung auf alle Instanzen
Modellziele wenden Interaktionsoptionen auf jede Instanz eines bestimmten Modells in der Spielwelt an. Dies ist äußerst wirkungsvoll für Dinge wie Geldautomaten, Verkaufsautomaten, Müllcontainer, Mülleimer oder andere Gegenstände, die an mehreren Orten auf der Karte vorhanden sind. Anstatt Ziele manuell an Hunderten von Koordinaten zu registrieren, registriere sich nur einmal anhand des Modellnamens und jedes passende Objekt wird interaktiv. Die Auswirkungen auf die Leistung sind minimal, da das Zielsystem nur Modelle innerhalb des Raycast-Bereichs überprüft, nicht jedes Objekt auf der ganzen Welt. Sei jedoch vorsichtig mit gängigen Modellen. Durch das Anvisieren jedes prop_bin_01a auf der Karte erhalten Spieler Hunderte von Interaktionspunkten. Stelle daher sicher, dass die Aktion für alle Instanzen dieses Modells sinnvoll ist.
Zonenbasierte Ziele: Unsichtbare Interaktionsbereiche
Zonenziele erzeugen unsichtbare Interaktionsbereiche an bestimmten Koordinaten. Diese eignen sich ideal für Orte, an denen kein physisches Objekt vorhanden ist, die Spieler aber dennoch interagieren sollen, z. B. eine Theke im Inneren eines Gebäudes, eine bestimmte Stelle auf dem Boden für ein Versteck oder ein Bereich vor einer Tür für die Möglichkeit, ein Dietrich zu knacken. Du definieren Zonen als Kästen oder Kugeln mit Koordinaten, Größe und Drehung. Die Zone ist nur dann aktiv, wenn das Fadenkreuz auf den Bereich der Zone zeigt. Dies sorgt für Präzision und verhindert versehentliche Interaktionen. Zonenziele sind auch die Lösung der Wahl, um Interaktionen zu Teilen von Karten-MLOs hinzuzufügen, bei denen die Requisiten in die Karte integriert sind und nicht vom Modell anvisiert werden können.
Bedingte Sichtbarkeit mit canInteract
Die Funktion canInteract macht Zielsysteme wirklich leistungsstark. Es wird jedes Mal ausgeführt, wenn sich das Fadenkreuz über einem Ziel befindet, und bestimmt, ob die einzelnen Optionen angezeigt oder ausgeblendet werden sollen. Dadurch kannst du kontextsensitive Interaktionen erstellen, bei denen ein Polizist andere Optionen sieht als ein Zivilist, bei denen eine Dietrich-Option nur angezeigt wird, wenn der Spieler einen Dietrich-Gegenstand hat, oder bei denen eine Fahrzeugreparaturoption nur angezeigt wird, wenn das Fahrzeug beschädigt ist. Als Parameter erhält die Funktion das Entity-Handle, die Entfernung, die Koordinaten und den Optionsnamen. Halte die Logik in canInteract leichtgewichtig, da sie in jedem Frame ausgeführt wird, während der Player über dem Ziel schwebt. Vermeide darin Datenbankabfragen oder umfangreiche Berechnungen. Speichere stattdessen die erforderlichen Daten in einer lokalen Variablen zwischen, die durch Ereignisse aktualisiert wird.
Globale Ziele: Spieler- und Fahrzeuginteraktionen
Globale Ziele gelten für jeden Spieler oder jedes Fahrzeug auf der Welt, ohne dass jedes einzelne registriert werden muss. addGlobalPlayer fügt Optionen hinzu, die angezeigt werden, wenn ein anderer Spieler als Ziel ausgewählt wird. Dies eignet sich perfekt für Interaktionen wie das Übergeben von Gegenständen, das Überprüfen von Ausweisen, das Anlegen von Handschellen an Verdächtige oder das Heilen anderer Spieler. addGlobalVehicle fügt Optionen für jedes Fahrzeug hinzu, nützlich für Mechaniker, Polizeisuchen oder Tanksysteme. Verwende canInteract großzügig mit globalen Zielen, um eine Optionsüberladung zu verhindern. Ein Zivilist sollte keine Manschettenoption sehen, und ein Mechaniker sollte Reparaturoptionen nur im Dienst sehen. Globale Ziele sind die bequemste Möglichkeit, universelle Interaktionen hinzuzufügen, sind aber auch am einfachsten zu missbrauchen. Überlege daher sorgfältig, wann jede Option tatsächlich sichtbar sein soll.
Leistungstipps und häufige Fehler
Zielsysteme sind gut optimiert, können aber bei Missbrauch dennoch die Leistung beeinträchtigen. Der häufigste Fehler besteht darin, zu viele Zonenziele mit aktiviertem Debugmodus in der Produktion zu registrieren. Beim Debug-Rendering werden Drahtgitterformen für jede Zone gezeichnet, was bei Dutzenden davon teuer ist. Lege vor der Bereitstellung immer debug = false fest. Ein weiterer Fehler besteht darin, teure Logik in canInteract-Funktionen einzubauen. Da dies in jedem Frame ausgeführt wird, während du den Mauszeiger bewegen, kann sich sogar ein einzelner exports.ox_inventory:Search-Aufruf summieren, wenn du zehn Optionen haben, die alle gleichzeitig Bestandsprüfungen ausführen. Speichere diese Werte stattdessen im Cache und aktualisierest du sie, wenn sich der Bestand ändert. Bereinige schließlich immer Ziele, wenn deine Ressource stoppt. Verwende den Ereignishandler onResourceStop, um alle Zonen-, Modell- und Entitätsziele zu entfernen. Durchgesickerte Ziele verbleiben im Speicher und können Fehler oder doppelte Optionen verursachen, wenn die Ressource neu gestartet wird. ox_target führt einige Bereinigungen für lokale Entitäten automatisch durch, eine explizite Bereinigung ist jedoch immer der sicherste Ansatz.

