Treffererkennung mit Lasern

*Dieser Inhalt wurde mit KI (Beta) übersetzt und kann Fehler enthalten. Um diese Seite auf Englisch zu sehen, klicke hier.

In diesem Tutorial lernen Sie, wie Sie einen Laser aus dem Blaster in Spielerwerkzeuge erstellen abfeuern und erkennen, ob er einen Spieler trifft oder nicht.

Raycasting zur Kollisionserkennung

Raycasting erzeugt einen unsichtbaren Strahl von einer Startposition in eine gegebene Richtung mit einer definierten Länge. Wenn der Strahl mit Objekten oder Terrain in seinem Weg kollidiert, gibt er Informationen über die Kollision zurück, wie die Position und das Objekt, mit dem er kollidiert ist.

Raycast von A nach B, der mit einer Wand kollidiert

Finden Sie die Mausposition

Bevor ein Laser abgefeuert werden kann, müssen Sie zunächst wissen, wo der Spieler zielt. Dies kann durch Raycasting von der 2D-Mausposition des Spielers auf dem Bildschirm direkt nach vorne von der Kamera in die 3D-Welt gefunden werden. Der Strahl wird mit dem kollidieren, was der Spieler mit der Maus anvisiert.

  1. Öffnen Sie das ToolController-Skript im Blaster-Werkzeug aus Spielerwerkzeuge erstellen. Wenn Sie dieses Tutorial noch nicht abgeschlossen haben, können Sie das Blaster-Modell herunterladen und in StarterPack einfügen.

  2. Deklarieren Sie oben im Skript eine Konstante namens MAX_MOUSE_DISTANCE mit einem Wert von 1000.

  3. Erstellen Sie eine Funktion namens getWorldMousePosition.

    local tool = script.Parent
    local MAX_MOUSE_DISTANCE = 1000
    local function getWorldMousePosition()
    end
    local function toolEquipped()
    tool.Handle.Equip:Play()
    end
    local function toolActivated()
    tool.Handle.Activate:Play()
    end
    -- Verbinden Sie Ereignisse mit den entsprechenden Funktionen
    tool.Equipped:Connect(toolEquipped)
    tool.Activated:Connect(toolActivated)
  4. Verwenden Sie die GetMouseLocation-Funktion von UserInputService, um die 2D-Mausposition des Spielers auf dem Bildschirm zu erhalten. Weisen Sie dies einer Variablen mit dem Namen mouseLocation zu.

    local UserInputService = game:GetService("UserInputService")
    local tool = script.Parent
    local MAX_MOUSE_DISTANCE = 1000
    local function getWorldMousePosition()
    local mouseLocation = UserInputService:GetMouseLocation()
    end

Jetzt ist die 2D-Mausposition bekannt, ihre X- und Y-Eigenschaften können als Parameter für die Camera:ViewportPointToRay()-Funktion verwendet werden, die einen Ray vom Bildschirm in die 3D-Welt erstellt.

  1. Verwenden Sie die X- und Y-Eigenschaften von mouseLocation als Argumente für die ViewportPointToRay()-Funktion. Weisen Sie dies einer Variablen mit dem Namen screenToWorldRay zu.

    local function getWorldMousePosition()
    local mouseLocation = UserInputService:GetMouseLocation()
    -- Erstellen Sie einen Strahl von der 2D-Mausposition
    local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    end

Es ist Zeit, die Raycast-Funktion zu verwenden, um zu überprüfen, ob der Strahl ein Objekt trifft. Dies erfordert eine Startposition und einen Richtungsvektor: In diesem Beispiel verwenden Sie die Ursprungs- und Richtungs-Eigenschaften von screenToWorldRay.

Die Länge des Richtungsvektors bestimmt, wie weit der Strahl reisen wird. Der Strahl muss so lang sein wie die MAX_MOUSE_DISTANCE, also müssen Sie den Richtungsvektor mit MAX_MOUSE_DISTANCE multiplizieren.

  1. Deklarieren Sie eine Variable mit dem Namen directionVector und weisen Sie ihr den Wert von screenToWorldRay.Direction multipliziert mit MAX_MOUSE_DISTANCE zu.

    local function getWorldMousePosition()
    local mouseLocation = UserInputService:GetMouseLocation()
    -- Erstellen Sie einen Strahl von der 2D-Mausposition
    local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    -- Der Einheitsrichtungsvektor des Strahls multipliziert mit einer maximalen Entfernung
    local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
  2. Rufen Sie die Raycast-Funktion von workspace auf und übergeben Sie die Origin-Eigenschaft von screenToWorldRay als erstes Argument und directionVector als zweites. Weisen Sie dies einer Variablen mit dem Namen raycastResult zu.

    local function getWorldMousePosition()
    local mouseLocation = UserInputService:GetMouseLocation()
    -- Erstellen Sie einen Strahl von der 2D-Mausposition
    local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    -- Der Einheitsrichtungsvektor des Strahls multipliziert mit einer maximalen Entfernung
    local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
    -- Raycast von der Ursprungsposition des Strahls in Richtung seiner Richtung
    local raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)

Kollision Informationen

Wenn die Raycast-Operation ein Objekt findet, das vom Strahl getroffen wurde, gibt sie ein RaycastResult zurück, das Informationen über die Kollision zwischen dem Strahl und dem Objekt enthält.

RaycastResult-EigenschaftBeschreibung
InstanceDas BasePart oder Terrain-Element, das der Strahl durchdrungen hat.
PositionWo die Schnittstelle aufgetreten ist; normalerweise ein Punkt direkt auf der Oberfläche eines Teils oder Terrains.
MaterialDas Material am Kollisionspunkt.
NormalDer Normalenvektor der durchdrungenen Fläche. Dies kann verwendet werden, um zu bestimmen, in welche Richtung die Fläche zeigt.

Die Position-Eigenschaft wird die Position des Objekts sein, über dem die Maus schwebt. Wenn die Maus über keinem Objekt innerhalb einer Entfernung von MAX_MOUSE_DISTANCE schwebt, wird raycastResult nil sein.

  1. Erstellen Sie eine if-Anweisung, um zu überprüfen, ob raycastResult existiert.

  2. Wenn raycastResult einen Wert hat, geben Sie seine Position-Eigenschaft zurück.

  3. Wenn raycastResult nil ist, finden Sie das Ende des Raycasts. Berechnen Sie die 3D-Position der Maus, indem Sie screenToWorldRay.Origin und directionVector zusammen addieren.

local function getWorldMousePosition()
local mouseLocation = UserInputService:GetMouseLocation()
-- Erstellen Sie einen Strahl von der 2D-Mausposition
local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
-- Der Einheitsrichtungsvektor des Strahls multipliziert mit einer maximalen Entfernung
local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
-- Raycast von der Ursprungsposition des Strahls in Richtung seiner Richtung
local raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)
if raycastResult then
-- Geben Sie den 3D-Schnittpunkt zurück
return raycastResult.Position
else
-- Kein Objekt wurde getroffen, also berechnen Sie die Position am Ende des Strahls
return screenToWorldRay.Origin + directionVector
end
end

Zielen Sie auf das Ziel

Jetzt, da die 3D-Mausposition bekannt ist, kann sie als Zielposition verwendet werden, um einen Laser abzufeuern. Ein zweiter Strahl kann zwischen der Waffe des Spielers und der Zielposition unter Verwendung der Raycast-Funktion abgefeuert werden.

  1. Deklarieren Sie eine Konstante mit dem Namen MAX_LASER_DISTANCE oben im Skript und weisen Sie ihr den Wert 500 zu, oder einen von Ihnen gewählten Bereich für den Laserblaster.

    local UserInputService = game:GetService("UserInputService")
    local tool = script.Parent
    local MAX_MOUSE_DISTANCE = 1000
    local MAX_LASER_DISTANCE = 500
  2. Erstellen Sie eine Funktion namens fireWeapon unter der Funktion getWorldMousePosition.

  3. Rufen Sie getWorldMousePosition auf und weisen Sie das Ergebnis einer Variablen mit dem Namen mousePosition zu. Dies wird die Zielposition für den Raycast sein.

    -- Kein Objekt wurde getroffen, also berechnen Sie die Position am Ende des Strahls
    return screenToWorldRay.Origin + directionVector
    end
    end
    local function fireWeapon()
    local mouseLocation = getWorldMousePosition()
    end
    local function toolEquipped()
    tool.Handle.Equip:Play()
    end

Diesmal wird der Richtungsvektor für die Raycast-Funktion die Richtung vom Standort des Werkzeugs des Spielers zur Zielposition darstellen.

  1. Deklarieren Sie eine Variable mit dem Namen targetDirection und berechnen Sie den Richtungsvektor, indem Sie die Werkzeugposition von mouseLocation subtrahieren.

  2. Normalisieren Sie den Vektor, indem Sie seine Unit-Eigenschaft verwenden. Dies gibt ihm eine Größe von 1, was es einfach macht, ihn später mit einer Länge zu multiplizieren.

    local function fireWeapon()
    local mouseLocation = getWorldMousePosition()
    -- Berechnen Sie einen normalisierten Richtungsvektor und multiplizieren Sie ihn mit der Laserreichweite
    local targetDirection = (mouseLocation - tool.Handle.Position).Unit
    end
  3. Deklarieren Sie eine Variable mit dem Namen directionVector und weisen Sie ihr den targetDirection multipliziert mit der MAX_LASER_DISTANCE zu.

    local targetDirection = (mouseLocation - tool.Handle.Position).Unit
    -- Die Richtung, um die Waffe abzufeuern, multipliziert mit einer maximalen Entfernung
    local directionVector = targetDirection * MAX_LASER_DISTANCE
    end

Ein RaycastParams-Objekt kann verwendet werden, um zusätzliche Parameter für die Raycast-Funktion zu speichern. Es wird in Ihrem Laserblaster verwendet, um sicherzustellen, dass der Raycast nicht versehentlich mit dem Spieler kollidiert, der die Waffe abfeuert. Alle Teile, die in der FilterDescendantsInstances-Eigenschaft eines RaycastParams-Objekts enthalten sind, werden im Raycast ignoriert.

  1. Fahren Sie mit der Funktion fireWeapon fort und deklarieren Sie eine Variable namens weaponRaycastParams. Weisen Sie ihr ein neues RaycastParams-Objekt zu.

  2. Erstellen Sie eine Tabelle, die den lokalen Charakter des Spielers enthält, und weisen Sie sie der weaponRaycastParams.FilterDescendantsInstances-Eigenschaft zu.

  3. Raycast von der Position des Werkzeuggriffs des Spielers in eine Richtung zur directionVector. Denken Sie daran, diesmal weaponRaycastParams als Argument hinzuzufügen. Weisen Sie dies einer Variablen mit dem Namen weaponRaycastResult zu.

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local tool = script.Parent
local MAX_MOUSE_DISTANCE = 1000
local MAX_LASER_DISTANCE = 500
local function getWorldMousePosition()
local function fireWeapon()
local mouseLocation = getWorldMousePosition()
-- Berechnen Sie einen normalisierten Richtungsvektor und multiplizieren Sie ihn mit der Laserreichweite
local targetDirection = (mouseLocation - tool.Handle.Position).Unit
-- Die Richtung, um die Waffe abzufeuern, multipliziert mit einer maximalen Entfernung
local directionVector = targetDirection * MAX_LASER_DISTANCE
-- Ignorieren Sie den Charakter des Spielers, um zu verhindern, dass er sich selbst verletzt
local weaponRaycastParams = RaycastParams.new()
weaponRaycastParams.FilterDescendantsInstances = {Players.LocalPlayer.Character}
local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
end

Schließlich müssen Sie überprüfen, ob die Raycast-Operation einen Wert zurückgegeben hat. Wenn ein Wert zurückgegeben wird, wurde ein Objekt vom Strahl getroffen und ein Laser kann zwischen der Waffe und dem Trefferort erstellt werden. Wenn nichts zurückgegeben wurde, muss die endgültige Position berechnet werden, um den Laser zu erstellen.

  1. Deklarieren Sie eine leere Variable mit dem Namen hitPosition.

  2. Verwenden Sie eine if-Anweisung, um zu überprüfen, ob weaponRaycastResult einen Wert hat. Wenn ein Objekt getroffen wurde, weisen Sie weaponRaycastResult.Position hitPosition zu.

    local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
    -- Überprüfen Sie, ob zwischen der Start- und Endposition Objekte getroffen wurden
    local hitPosition
    if weaponRaycastResult then
    hitPosition = weaponRaycastResult.Position
    end
  3. Wenn weaponRaycastResult keinen Wert hat, berechnen Sie die Endposition des Raycasts, indem Sie die Position des Werkzeuggriffs mit der directionVector addieren. Weisen Sie dies hitPosition zu.

    local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
    -- Überprüfen Sie, ob zwischen der Start- und Endposition Objekte getroffen wurden
    local hitPosition
    if weaponRaycastResult then
    hitPosition = weaponRaycastResult.Position
    else
    -- Berechnen Sie die Endposition basierend auf der maximalen Laserreichweite
    hitPosition = tool.Handle.Position + directionVector
    end
    end
  4. Navigieren Sie zur Funktion toolActivated und rufen Sie die Funktion fireWeapon auf, damit der Laser jedes Mal abgefeuert wird, wenn das Werkzeug aktiviert wird.

    local function toolActivated()
    tool.Handle.Activate:Play()
    fireWeapon()
    end

Überprüfen Sie das getroffene Objekt

Um herauszufinden, ob das vom Laser getroffene Objekt Teil des Charakters eines Spielers oder nur ein Stück Landschaft ist, müssen Sie nach einem Humanoid suchen, da jeder Charakter einen hat.

Zuerst müssen Sie das Charaktermodell finden. Wenn ein Teil des Charakters getroffen wurde, können Sie nicht davon ausgehen, dass der Elternteil des getroffenen Objekts der Charakter ist. Der Laser könnte ein Körperteil, ein Zubehör oder ein Werkzeug getroffen haben, die alle in verschiedenen Teilen der Hierarchie des Charakters zu finden sind.

Sie können FindFirstAncestorOfClass verwenden, um ein Charaktermodell-Ahnen des vom Laser getroffenen Objekts zu finden, falls eines existiert. Wenn Sie ein Modell finden und es einen Humanoiden enthält, können Sie in den meisten Fällen davon ausgehen, dass es sich um einen Charakter handelt.

  1. Fügen Sie den hervorgehobenen Code unten in die if-Anweisung von weaponRaycastResult ein, um zu überprüfen, ob ein Charakter getroffen wurde.

    -- Überprüfen Sie, ob zwischen der Start- und Endposition Objekte getroffen wurden
    local hitPosition
    if weaponRaycastResult then
    hitPosition = weaponRaycastResult.Position
    -- Die Instanz, die getroffen wurde, wird ein Kind eines Charaktermodells sein
    -- Wenn ein Humanoid im Modell gefunden wird, ist es wahrscheinlich der Charakter eines Spielers
    local characterModel = weaponRaycastResult.Instance:FindFirstAncestorOfClass("Model")
    if characterModel then
    local humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    print("Spieler getroffen")
    end
    end
    else
    -- Berechnen Sie die Endposition basierend auf der maximalen Laserreichweite
    hitPosition = tool.Handle.Position + directionVector
    end

Jetzt sollte der Laserblaster Spieler getroffen im Ausgabe-Fenster ausgeben, jedes Mal, wenn die Raycast-Operation einen anderen Spieler trifft.

Testen mit mehreren Spielern

Zwei Spieler werden benötigt, um zu testen, ob der Waffenraycast andere Spieler findet, also müssen Sie einen lokalen Server starten. Siehe Multi-Client-Simulation für Anweisungen.

Testen Sie auf einem Client, indem Sie den anderen Spieler mit der Waffe anvisieren und darauf klicken. "Spieler getroffen" sollte jedes Mal in der Ausgabe angezeigt werden, wenn ein Spieler getroffen wird.

Finden Sie die Laserposition

Der Blaster sollte einen roten Lichtstrahl auf sein Ziel abfeuern. Die Funktion dafür wird in einem ModuleScript sein, damit sie später in anderen Skripten wiederverwendet werden kann. Zuerst muss das Skript die Position finden, an der der Laserstrahl gerendert werden soll.

  1. Erstellen Sie ein ModuleScript mit dem Namen LaserRenderer, das unter StarterPlayerScripts in StarterPlayer angeordnet ist.

  2. Öffnen Sie das Skript und benennen Sie die Modultabelle in den Namen des Skripts LaserRenderer um.

  3. Deklarieren Sie eine Variable mit dem Namen SHOT_DURATION mit einem Wert von 0.15. Dies wird die Zeit (in Sekunden) sein, die der Laser sichtbar ist.

  4. Erstellen Sie eine Funktion von LaserRenderer mit dem Namen createLaser mit zwei Parametern, die toolHandle und endPosition genannt werden.

    local LaserRenderer = {}
    local SHOT_DURATION = 0.15 -- Zeit, die der Laser sichtbar ist
    -- Erstellen Sie einen Laserstrahl von einer Startposition zu einer Endposition
    function LaserRenderer.createLaser(toolHandle, endPosition)
    end
    return LaserRenderer
  5. Deklarieren Sie eine Variable mit dem Namen startPosition und setzen Sie die Position-Eigenschaft von toolHandle als ihren Wert. Dies wird die Position des Laserblasters des Spielers sein.

  6. Deklarieren Sie eine Variable mit dem Namen laserDistance und subtrahieren Sie endPosition von startPosition, um den Unterschied zwischen den beiden Vektoren zu finden. Verwenden Sie die Magnitude-Eigenschaft davon, um die Länge des Laserstrahls zu erhalten.

    function LaserRenderer.createLaser(toolHandle, endPosition)
    local startPosition = toolHandle.Position
    local laserDistance = (startPosition - endPosition).Magnitude
    end
  7. Deklarieren Sie eine laserCFrame-Variable, um die Position und Orientierung des Laserstrahls zu speichern. Die Position muss der Mittelpunkt des Anfangs und des Endes des Strahls sein. Verwenden Sie CFrame.lookAt, um ein neues CFrame zu erstellen, das sich an startPosition befindet und auf endPosition zeigt. Multiplizieren Sie dies mit einem neuen CFrame mit einem Z-Achsenwert von der Hälfte des negativen laserDistance, um den Mittelpunkt zu erhalten.

    function LaserRenderer.createLaser(toolHandle, endPosition)
    local startPosition = toolHandle.Position
    local laserDistance = (startPosition - endPosition).Magnitude
    local laserCFrame = CFrame.lookAt(startPosition, endPosition) * CFrame.new(0, 0, -laserDistance / 2)
    end

Erstellen Sie das Laserteil

Jetzt, da Sie wissen, wo Sie einen Laserstrahl erstellen sollen, müssen Sie den Strahl selbst hinzufügen. Dies kann einfach mit einem Neon-Teil erfolgen.

  1. Deklarieren Sie eine Variable laserPart und weisen Sie ihr eine neue Part-Instanz zu.

  2. Setzen Sie die folgenden Eigenschaften von laserPart:

    1. Größe: Vector3.new(0.2, 0.2, laserDistance)
    2. CFrame: laserCFrame
    3. Verankert: true
    4. Kann kollidieren: false
    5. Farbe: Color3.fromRGB(225, 0, 0) (eine kräftige rote Farbe)
    6. Material: Enum.Material.Neon
  3. Fügen Sie laserPart zu Workspace hinzu.

  4. Fügen Sie das Teil zum Debris-Dienst hinzu, damit es nach der Anzahl der Sekunden in der SHOT_DURATION-Variablen entfernt wird.

    function LaserRenderer.createLaser(toolHandle, endPosition)
    local startPosition = toolHandle.Position
    local laserDistance = (startPosition - endPosition).Magnitude
    local laserCFrame = CFrame.lookAt(startPosition, endPosition) * CFrame.new(0, 0, -laserDistance / 2)
    local laserPart = Instance.new("Part")
    laserPart.Size = Vector3.new(0.2, 0.2, laserDistance)
    laserPart.CFrame = laserCFrame
    laserPart.Anchored = true
    laserPart.CanCollide = false
    laserPart.Color = Color3.fromRGB(225, 0, 0)
    laserPart.Material = Enum.Material.Neon
    laserPart.Parent = workspace
    -- Fügen Sie den Laserstrahl zum Debris-Dienst hinzu, um entfernt und bereinigt zu werden
    Debris:AddItem(laserPart, SHOT_DURATION)
    end

Jetzt ist die Funktion zum Rendern des Laserstrahls abgeschlossen, sie kann vom ToolController aufgerufen werden.

  1. Deklarieren Sie oben im ToolController-Skript eine Variable mit dem Namen LaserRenderer und fordern Sie das LaserRenderer-ModuleScript an, das sich in PlayerScripts befindet.

    local UserInputService = game:GetService("UserInputService")
    local Players = game:GetService("Players")
    local LaserRenderer = require(Players.LocalPlayer.PlayerScripts.LaserRenderer)
    local tool = script.Parent
  2. Rufen Sie am Ende der Funktion fireWeapon die LaserRenderer-Funktion createLaser auf, indem Sie den Werkzeuggriff und hitPosition als Argumente verwenden.

    -- Berechnen Sie die Endposition basierend auf der maximalen Laserreichweite
    hitPosition = tool.Handle.Position + directionVector
    end
    LaserRenderer.createLaser(tool.Handle, hitPosition)
    end
  3. Testen Sie die Waffe, indem Sie auf die Schaltfläche Spielen klicken. Ein Laserstrahl sollte sichtbar sein zwischen der Waffe und der Maus, wenn das Werkzeug aktiviert wird.

Kontrollieren Sie die Feuerrate der Waffe

Waffen benötigen eine Verzögerung zwischen jedem Schuss, um zu verhindern, dass Spieler in kurzer Zeit zu viel Schaden verursachen. Dies kann gesteuert werden, indem überprüft wird, ob genügend Zeit seit dem letzten Schuss vergangen ist.

  1. Deklarieren Sie eine Variable oben im ToolController mit dem Namen FIRE_RATE. Dies wird die minimale Zeit zwischen jedem Schuss sein. Geben Sie ihr einen Wert Ihrer Wahl; dieses Beispiel verwendet 0.3 Sekunden.

  2. Deklarieren Sie eine weitere Variable darunter mit dem Namen timeOfPreviousShot mit einem Wert von 0. Dies speichert die letzte Zeit, zu der der Spieler geschossen hat, und wird mit jedem Schuss aktualisiert.

    local MAX_MOUSE_DISTANCE = 1000
    local MAX_LASER_DISTANCE = 300
    local FIRE_RATE = 0.3
    local timeOfPreviousShot = 0
  3. Erstellen Sie eine Funktion mit dem Namen canShootWeapon ohne Parameter. Diese Funktion wird überprüfen, wie viel Zeit seit dem vorherigen Schuss vergangen ist, und true oder false zurückgeben.

    local FIRE_RATE = 0.3
    local timeOfPreviousShot = 0
    -- Überprüfen Sie, ob genügend Zeit seit dem letzten Schuss vergangen ist
    local function canShootWeapon()
    end
    local function getWorldMousePosition()
  4. Deklarieren Sie innerhalb der Funktion eine Variable mit dem Namen currentTime; weisen Sie ihr das Ergebnis des Aufrufs der tick()-Funktion zu. Dies gibt zurück, wie viel Zeit seit dem 1. Januar 1970 (einem willkürlichen Datum, das häufig zur Berechnung der Zeit verwendet wird) vergangen ist.

  5. Subtrahieren Sie timeOfPreviousShot von currentTime und geben Sie false zurück, wenn das Ergebnis kleiner als FIRE_RATE ist; andernfalls geben Sie true zurück.

    -- Überprüfen Sie, ob genügend Zeit seit dem letzten Schuss vergangen ist
    local function canShootWeapon()
    local currentTime = tick()
    if currentTime - timeOfPreviousShot < FIRE_RATE then
    return false
    end
    return true
    end
  6. Am Ende der Funktion fireWeapon aktualisieren Sie timeOfPreviousShot jedes Mal, wenn die Waffe abgefeuert wird, mit tick.

    hitPosition = tool.Handle.Position + directionVector
    end
    timeOfPreviousShot = tick()
    LaserRenderer.createLaser(tool.Handle, hitPosition)
    end
  7. Innerhalb der Funktion toolActivated erstellen Sie eine if-Anweisung und rufen canShootWeapon auf, um zu überprüfen, ob die Waffe abgefeuert werden kann.

    local function toolActivated()
    if canShootWeapon() then
    tool.Handle.Activate:Play()
    fireWeapon()
    end
    end

Wenn Sie den Blaster testen, sollten Sie feststellen, dass es unabhängig davon, wie schnell Sie klicken, immer eine kurze Verzögerung von 0,3 Sekunden zwischen jedem Schuss gibt.

Spieler schädigen

Clients können andere Clients nicht direkt schädigen; der Server muss dafür verantwortlich sein, Schaden zuzufügen, wenn ein Spieler getroffen wird.

Clients können ein RemoteEvent verwenden, um dem Server mitzuteilen, dass ein Charakter getroffen wurde. Diese sollten in ReplicatedStorage gespeichert werden, wo sie sowohl für den Client als auch für den Server sichtbar sind.

  1. Erstellen Sie einen Ordner in ReplicatedStorage mit dem Namen Events.

  2. Fügen Sie ein RemoteEvent in den Events-Ordner ein und benennen Sie es DamageCharacter.

  3. Erstellen Sie in ToolController am Anfang des Skripts Variablen für ReplicatedStorage und den Events-Ordner.

    local UserInputService = game:GetService("UserInputService")
    local Players = game:GetService("Players")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local LaserRenderer = require(Players.LocalPlayer.PlayerScripts.LaserRenderer)
    local tool = script.Parent
    local eventsFolder = ReplicatedStorage.Events
    local MAX_MOUSE_DISTANCE = 1000
    local MAX_LASER_DISTANCE = 500
  4. Ersetzen Sie die "Spieler getroffen"-Ausgabeanweisung in fireWeapon durch eine Zeile Luau, um das DamageCharacter-Remote-Event mit der characterModel-Variablen als Argument auszulösen.

    local characterModel = weaponRaycastResult.Instance:FindFirstAncestorOfClass("Model")
    if characterModel then
    local humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    eventsFolder.DamageCharacter:FireServer(characterModel, hitPosition)
    end
    end
    else
    -- Berechnen Sie die Endposition basierend auf der maximalen Laserreichweite
    hitPosition = tool.Handle.Position + directionVector
    end

Der Server muss den Spieler, der getroffen wurde, schädigen, wenn das Ereignis ausgelöst wird.

  1. Fügen Sie ein Skript in ServerScriptService ein und benennen Sie es ServerLaserManager.

  2. Deklarieren Sie eine Variable mit dem Namen LASER_DAMAGE und setzen Sie sie auf 10 oder einen Wert Ihrer Wahl.

  3. Erstellen Sie eine Funktion mit dem Namen damageCharacter mit zwei Parametern, die playerFired und characterToDamage genannt werden.

  4. Innerhalb der Funktion finden Sie den Humanoiden des Charakters und subtrahieren LASER_DAMAGE von seiner Gesundheit.

  5. Verbinden Sie die Funktion damageCharacter mit dem DamageCharacter-Remote-Event im Events-Ordner.

    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local eventsFolder = ReplicatedStorage.Events
    local LASER_DAMAGE = 10
    function damageCharacter(playerFired, characterToDamage)
    local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    -- Gesundheit vom Charakter entfernen
    humanoid.Health -= LASER_DAMAGE
    end
    end
    -- Verbinden Sie Ereignisse mit den entsprechenden Funktionen
    eventsFolder.DamageCharacter.OnServerEvent:Connect(damageCharacter)
  6. Testen Sie den Blaster mit 2 Spielern, indem Sie einen lokalen Server starten. Wenn Sie den anderen Spieler erschießen, wird dessen Gesundheit um den Wert verringert, der LASER_DAMAGE zugewiesen wurde.

Rendern Sie die Laserstrahlen anderer Spieler

Derzeit wird der Laserstrahl vom Client erstellt, der die Waffe abfeuert, sodass nur dieser ihn sehen kann.

Wenn der Laserstrahl auf dem Server erstellt wird, können ihn alle sehen. Es würde jedoch eine kleine Verzögerung zwischen dem Schießen des Clients und dem Empfang der Informationen über den Schuss durch den Server geben. Dies würde bedeuten, dass der Client, der die Waffe abfeuert, eine Verzögerung zwischen der Aktivierung der Waffe und dem Erscheinen des Laserstrahls sehen würde; die Waffe würde sich dadurch verzögert anfühlen.

Um dieses Problem zu lösen, wird jeder Client seine eigenen Laserstrahlen erstellen. Das bedeutet, dass der Client, der die Waffe abfeuert, den Laserstrahl sofort sieht. Andere Clients werden eine kleine Verzögerung erleben, zwischen dem Zeitpunkt, an dem ein anderer Spieler schießt, und dem Erscheinen eines Strahls. Dies ist das beste Szenario: Es gibt keine Möglichkeit, den Laser eines Clients schneller an andere Clients zu kommunizieren.

Shooter-Client

Zuerst muss der Client dem Server mitteilen, dass er einen Laser abgefeuert hat und die Endposition bereitstellen.

  1. Fügen Sie ein RemoteEvent in den Events-Ordner in ReplicatedStorage ein und benennen Sie es LaserFired.

  2. Suchen Sie die Funktion fireWeapon im ToolController-Skript. Am Ende der Funktion lösen Sie das LaserFired-Remote-Event mit hitPosition als Argument aus.

    hitPosition = tool.Handle.Position + directionVector
    end
    timeOfPreviousShot = tick()
    eventsFolder.LaserFired:FireServer(hitPosition)
    LaserRenderer.createLaser(tool.Handle, hitPosition)
    end

Der Server

Der Server muss jetzt das Ereignis empfangen, dass der Client einen Laser abgefeuert hat, und allen Clients die Start- und Endposition des Laserstrahls mitteilen, damit sie ihn ebenfalls rendern können.

  1. Erstellen Sie in dem ServerLaserManager-Skript eine Funktion mit dem Namen playerFiredLaser über damageCharacter mit zwei Parametern, die playerFired und endPosition genannt werden.

  2. Verbinden Sie die Funktion mit dem LaserFired-Remote-Event.

    -- Benachrichtigen Sie alle Clients, dass ein Laser abgefeuert wurde, damit sie den Laser anzeigen können
    local function playerFiredLaser(playerFired, endPosition)
    end
    -- Verbinden Sie Ereignisse mit den entsprechenden Funktionen
    eventsFolder.DamageCharacter.OnServerEvent:Connect(damageCharacter)
    eventsFolder.LaserFired.OnServerEvent:Connect(playerFiredLaser)

Der Server benötigt die Startposition des Lasers. Dies könnte vom Client gesendet werden, aber es ist am besten, dem Client, wo immer möglich, nicht zu vertrauen. Die Position des Werkzeuggriffs des Charakters wird die Startposition sein, sodass der Server sie von dort aus finden kann.

  1. Erstellen Sie eine Funktion getPlayerToolHandle über der Funktion playerFiredLaser mit einem Parameter namens player.

  2. Verwenden Sie den folgenden Code, um nach dem Werkzeug des Spielers zu suchen und das Griffobjekt zurückzugeben.

    local LASER_DAMAGE = 10
    -- Finden Sie den Griff des Werkzeugs, das der Spieler hält
    local function getPlayerToolHandle(player)
    local weapon = player.Character:FindFirstChildOfClass("Tool")
    if weapon then
    return weapon:FindFirstChild("Handle")
    end
    end
    -- Benachrichtigen Sie alle Clients, dass ein Laser abgefeuert wurde, damit sie den Laser anzeigen können
    local function playerFiredLaser(playerFired, endPosition)

Der Server kann jetzt FireAllClients auf dem LaserFired-Remote-Event aufrufen, um die Informationen zu senden, die erforderlich sind, um den Laser an die Clients zu rendern. Dazu gehören der Spieler, der den Laser abgefeuert hat (damit der Client für diesen Spieler den Laser nicht zweimal rendert), der Griff des Blasters (der als Startposition für den Laser dient) und die Endposition des Lasers.

  1. Rufen Sie in der Funktion playerFiredLaser die Funktion getPlayerToolHandle mit playerFired als Argument auf und weisen Sie den Wert einer Variablen mit dem Namen toolHandle zu.

  2. Wenn toolHandle existiert, lösen Sie das LaserFired-Ereignis für alle Clients mit playerFired, toolHandle und endPosition als Argumente aus.

    -- Benachrichtigen Sie alle Clients, dass ein Laser abgefeuert wurde, damit sie den Laser anzeigen können
    local function playerFiredLaser(playerFired, endPosition)
    local toolHandle = getPlayerToolHandle(playerFired)
    if toolHandle then
    eventsFolder.LaserFired:FireAllClients(playerFired, toolHandle, endPosition)
    end
    end

Rendern auf den Clients

Jetzt, da FireAllClients aufgerufen wurde, erhält jeder Client ein Ereignis vom Server, um einen Laserstrahl zu rendern. Jeder Client kann das LaserRenderer-Modul von früher wiederverwenden, um den Laserstrahl mit der Position des Werkzeugs und dem vom Server gesendeten Endpositionswert zu rendern. Der Spieler, der den Laserstrahl ursprünglich abgefeuert hat, sollte dieses Ereignis ignorieren, da er sonst 2 Laser sehen würde.

  1. Erstellen Sie ein LocalScript in StarterPlayerScripts mit dem Namen ClientLaserManager.

  2. Importieren Sie das LaserRenderer-Modul.

  3. Erstellen Sie eine Funktion mit dem Namen createPlayerLaser mit den Parametern playerWhoShot, toolHandle und endPosition.

  4. Verbinden Sie die Funktion mit dem LaserFired-Remote-Event im Events-Ordner.

  5. In der Funktion verwenden Sie eine if-Anweisung, um zu überprüfen, ob playerWhoShot nicht gleich dem LocalPlayer ist.

  6. Innerhalb der if-Anweisung rufen Sie die Funktion createLaser aus dem LaserRenderer-Modul auf, indem Sie toolHandle und endPosition als Argumente verwenden.

    local Players = game:GetService("Players")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local LaserRenderer = require(script.Parent:WaitForChild("LaserRenderer"))
    local eventsFolder = ReplicatedStorage.Events
    -- Zeigen Sie den Laser eines anderen Spielers an
    local function createPlayerLaser(playerWhoShot, toolHandle, endPosition)
    if playerWhoShot ~= Players.LocalPlayer then
    LaserRenderer.createLaser(toolHandle, endPosition)
    end
    end
    eventsFolder.LaserFired.OnClientEvent:Connect(createPlayerLaser)
  7. Testen Sie den Blaster mit 2 Spielern, indem Sie einen lokalen Server starten. Positionieren Sie jeden Client auf verschiedenen Seiten Ihres Monitors, damit Sie beide Fenster gleichzeitig sehen können. Wenn Sie auf einem Client schießen, sollten Sie den Laser auf dem anderen Client sehen.

Soundeffekte

Der Schuss-Soundeffekt wird derzeit nur auf dem Client abgespielt, der das Projektil abfeuert. Sie müssen den Code zum Abspielen des Sounds verschieben, damit auch andere Spieler ihn hören.

  1. Navigieren Sie im ToolController-Skript zur Funktion toolActivated und entfernen Sie die Zeile, die den Aktivierungssound abspielt.

    local function toolActivated()
    if canShootWeapon() then
    fireWeapon()
    end
    end
  2. Am Ende der Funktion createLaser in LaserRenderer deklarieren Sie eine Variable mit dem Namen shootingSound und verwenden Sie die FindFirstChild()-Methode von toolHandle, um nach dem Activate-Sound zu suchen.

  3. Verwenden Sie eine if-Anweisung, um zu überprüfen, ob shootingSound existiert; wenn ja, rufen Sie seine Play()-Funktion auf.

    laserPart.Parent = workspace
    -- Fügen Sie den Laserstrahl zum Debris-Dienst hinzu, um entfernt und bereinigt zu werden
    Debris:AddItem(laserPart, SHOT_DURATION)
    -- Spielen Sie den Schuss-Sound der Waffe ab
    local shootingSound = toolHandle:FindFirstChild("Activate")
    if shootingSound then
    shootingSound:Play()
    end
    end

Sichern Sie Remotes mit Validierung

Wenn der Server die Daten aus eingehenden Anfragen nicht überprüft, kann ein Hacker Remote-Funktionen und -Ereignisse missbrauchen und sie verwenden, um gefälschte Werte an den Server zu senden. Es ist wichtig, serverseitige Validierung zu verwenden, um dies zu verhindern.

In seiner aktuellen Form ist das DamageCharacter-Remote-Event sehr anfällig für Angriffe. Hacker könnten dieses Ereignis verwenden, um jeden Spieler zu schädigen, den sie wollen, ohne ihn zu treffen.

Validierung ist der Prozess, bei dem überprüft wird, ob die an den Server gesendeten Werte realistisch sind. In diesem Fall muss der Server:

  • Überprüfen, ob die Entfernung zwischen dem Spieler und der Position, die vom Laser getroffen wurde, innerhalb einer bestimmten Grenze liegt.
  • Raycast zwischen der Waffe, die den Laser abgefeuert hat, und der Trefferposition, um sicherzustellen, dass der Schuss möglich war und nicht durch Wände ging.

Client

Der Client muss dem Server die Position senden, die vom Raycast getroffen wurde, damit er überprüfen kann, ob die Entfernung realistisch ist.

  1. Navigieren Sie in ToolController zur Zeile, in der das DamageCharacter-Remote-Event in der Funktion fireWeapon ausgelöst wird.

  2. Fügen Sie hitPosition als Argument hinzu.

    if characterModel then
    local humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    eventsFolder.DamageCharacter:FireServer(characterModel, hitPosition)
    end
    end

Server

Der Client sendet jetzt einen zusätzlichen Parameter über das DamageCharacter-Remote-Event, sodass der ServerLaserManager angepasst werden muss, um ihn zu akzeptieren.

  1. Fügen Sie im ServerLaserManager-Skript der Funktion damageCharacter einen hitPosition-Parameter hinzu.

    function damageCharacter(playerFired, characterToDamage, hitPosition)
    local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    -- Gesundheit vom Charakter entfernen
    humanoid.Health -= LASER_DAMAGE
    end
    end
  2. Unter der Funktion getPlayerToolHandle erstellen Sie eine Funktion mit dem Namen isHitValid mit drei Parametern: playerFired, characterToDamage und hitPosition.

    end
    local function isHitValid(playerFired, characterToDamage, hitPosition)
    end

Die erste Überprüfung wird die Entfernung zwischen der Trefferposition und dem getroffenen Charakter sein.

  1. Deklarieren Sie eine Variable mit dem Namen MAX_HIT_PROXIMITY oben im Skript und weisen Sie ihr den Wert 10 zu. Dies wird die maximale Entfernung sein, die zwischen dem Treffer und dem Charakter erlaubt ist. Eine Toleranz ist erforderlich, da sich der Charakter möglicherweise leicht bewegt hat, seit der Client das Ereignis ausgelöst hat.

    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local eventsFolder = ReplicatedStorage.Events
    local LASER_DAMAGE = 10
    local MAX_HIT_PROXIMITY = 10
  2. In der Funktion isHitValid berechnen Sie die Entfernung zwischen dem Charakter und der Trefferposition. Wenn die Entfernung größer als MAX_HIT_PROXIMITY ist, geben Sie false zurück.

    local function isHitValid(playerFired, characterToDamage, hitPosition)
    -- Validieren Sie die Entfernung zwischen dem getroffenen Charakter und der Trefferposition
    local characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitude
    if characterHitProximity > MAX_HIT_PROXIMITY then
    return false
    end
    end

Die zweite Überprüfung wird einen Raycast zwischen der abgefeuerten Waffe und der Trefferposition beinhalten. Wenn der Raycast ein Objekt zurückgibt, das nicht der Charakter ist, können Sie davon ausgehen, dass der Schuss nicht gültig war, da etwas den Schuss blockiert hat.

  1. Kopieren Sie den folgenden Code, um diese Überprüfung durchzuführen. Geben Sie am Ende der Funktion true zurück: Wenn sie das Ende erreicht, haben alle Überprüfungen bestanden.

    local function isHitValid(playerFired, characterToDamage, hitPosition)
    -- Validieren Sie die Entfernung zwischen dem getroffenen Charakter und der Trefferposition
    local characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitude
    if characterHitProximity > 10 then
    return false
    end
    -- Überprüfen Sie, ob durch Wände geschossen wird
    local toolHandle = getPlayerToolHandle(playerFired)
    if toolHandle then
    local rayLength = (hitPosition - toolHandle.Position).Magnitude
    local rayDirection = (hitPosition - toolHandle.Position).Unit
    local raycastParams = RaycastParams.new()
    raycastParams.FilterDescendantsInstances = {playerFired.Character}
    local rayResult = workspace:Raycast(toolHandle.Position, rayDirection * rayLength, raycastParams)
    -- Wenn eine Instanz getroffen wurde, die nicht der Charakter ist, ignorieren Sie den Schuss
    if rayResult and not rayResult.Instance:IsDescendantOf(characterToDamage) then
    return false
    end
    end
    return true
    end
  2. Deklarieren Sie eine Variable in der Funktion damageCharacter mit dem Namen validShot. Weisen Sie ihr das Ergebnis eines Aufrufs der Funktion isHitValid mit drei Argumenten zu: playerFired, characterToDamage und hitPosition.

  3. In der untenstehenden if-Anweisung fügen Sie einen and-Operator hinzu, um zu überprüfen, ob validShot true ist.

    function damageCharacter(playerFired, characterToDamage, hitPosition)
    local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")
    local validShot = isHitValid(playerFired, characterToDamage, hitPosition)
    if humanoid and validShot then
    -- Gesundheit vom Charakter entfernen
    humanoid.Health -= LASER_DAMAGE
    end
    end

Jetzt ist das DamageCharacter-Remote-Event sicherer und verhindert die meisten Spieler, es auszunutzen. Beachten Sie, dass einige böswillige Spieler oft Wege finden, um die Validierung zu umgehen; die Sicherung von Remote-Events ist eine kontinuierliche Anstrengung.

Ihr Laserblaster ist jetzt vollständig, mit einem grundlegenden Treffererkennungssystem, das Raycasting verwendet. Versuchen Sie das Erkennen von Benutzereingaben-Tutorial, um herauszufinden, wie Sie eine Nachladeaktion zu Ihrem Laserblaster hinzufügen können, oder erstellen Sie eine unterhaltsame Karte und testen Sie Ihren Laserblaster mit anderen Spielern!

Endgültiger Code

ToolController

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LaserRenderer = require(Players.LocalPlayer.PlayerScripts.LaserRenderer)
local tool = script.Parent
local eventsFolder = ReplicatedStorage.Events
local MAX_MOUSE_DISTANCE = 1000
local MAX_LASER_DISTANCE = 500
local FIRE_RATE = 0.3
local timeOfPreviousShot = 0
-- Überprüfen Sie, ob genügend Zeit seit dem letzten Schuss vergangen ist
local function canShootWeapon()
local currentTime = tick()
if currentTime - timeOfPreviousShot < FIRE_RATE then
return false
end
return true
end
local function getWorldMousePosition()
local mouseLocation = UserInputService:GetMouseLocation()
-- Erstellen Sie einen Strahl von der 2D-Mausposition
local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
-- Der Einheitsrichtungsvektor des Strahls multipliziert mit einer maximalen Entfernung
local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
-- Raycast von der Ursprungsposition des Strahls in Richtung seiner Richtung
local raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)
if raycastResult then
-- Geben Sie den 3D-Schnittpunkt zurück
return raycastResult.Position
else
-- Kein Objekt wurde getroffen, also berechnen Sie die Position am Ende des Strahls
return screenToWorldRay.Origin + directionVector
end
end
local function fireWeapon()
local mouseLocation = getWorldMousePosition()
-- Berechnen Sie einen normalisierten Richtungsvektor und multiplizieren Sie ihn mit der Laserreichweite
local targetDirection = (mouseLocation - tool.Handle.Position).Unit
-- Die Richtung, um die Waffe abzufeuern, multipliziert mit einer maximalen Entfernung
local directionVector = targetDirection * MAX_LASER_DISTANCE
-- Ignorieren Sie den Charakter des Spielers, um zu verhindern, dass er sich selbst verletzt
local weaponRaycastParams = RaycastParams.new()
weaponRaycastParams.FilterDescendantsInstances = {Players.LocalPlayer.Character}
local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
-- Überprüfen Sie, ob zwischen der Start- und Endposition Objekte getroffen wurden
local hitPosition
if weaponRaycastResult then
hitPosition = weaponRaycastResult.Position
-- Die Instanz, die getroffen wurde, wird ein Kind eines Charaktermodells sein
-- Wenn ein Humanoid im Modell gefunden wird, ist es wahrscheinlich der Charakter eines Spielers
local characterModel = weaponRaycastResult.Instance:FindFirstAncestorOfClass("Model")
if characterModel then
local humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")
if humanoid then
eventsFolder.DamageCharacter:FireServer(characterModel, hitPosition)
end
end
else
-- Berechnen Sie die Endposition basierend auf der maximalen Laserreichweite
hitPosition = tool.Handle.Position + directionVector
end
timeOfPreviousShot = tick()
eventsFolder.LaserFired:FireServer(hitPosition)
LaserRenderer.createLaser(tool.Handle, hitPosition)
end
local function toolEquipped()
tool.Handle.Equip:Play()
end
local function toolActivated()
if canShootWeapon() then
fireWeapon()
end
end
tool.Equipped:Connect(toolEquipped)
tool.Activated:Connect(toolActivated)

LaserRenderer

local LaserRenderer = {}
local Debris = game:GetService("Debris")
local SHOT_DURATION = 0.15 -- Zeit, die der Laser sichtbar ist
-- Erstellen Sie einen Laserstrahl von einer Startposition zu einer Endposition
function LaserRenderer.createLaser(toolHandle, endPosition)
local startPosition = toolHandle.Position
local laserDistance = (startPosition - endPosition).Magnitude
local laserCFrame = CFrame.lookAt(startPosition, endPosition) * CFrame.new(0, 0, -laserDistance / 2)
local laserPart = Instance.new("Part")
laserPart.Size = Vector3.new(0.2, 0.2, laserDistance)
laserPart.CFrame = laserCFrame
laserPart.Anchored = true
laserPart.CanCollide = false
laserPart.Color = Color3.fromRGB(255, 0, 0)
laserPart.Material = Enum.Material.Neon
laserPart.Parent = workspace
-- Fügen Sie den Laserstrahl zum Debris-Dienst hinzu, um entfernt und bereinigt zu werden
Debris:AddItem(laserPart, SHOT_DURATION)
-- Spielen Sie den Schuss-Sound der Waffe ab
local shootingSound = toolHandle:FindFirstChild("Activate")
if shootingSound then
shootingSound:Play()
end
end
return LaserRenderer

ServerLaserManager

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local eventsFolder = ReplicatedStorage.Events
local LASER_DAMAGE = 10
local MAX_HIT_PROXIMITY = 10
-- Finden Sie den Griff des Werkzeugs, das der Spieler hält
local function getPlayerToolHandle(player)
local weapon = player.Character:FindFirstChildOfClass("Tool")
if weapon then
return weapon:FindFirstChild("Handle")
end
end
local function isHitValid(playerFired, characterToDamage, hitPosition)
-- Validieren Sie die Entfernung zwischen dem getroffenen Charakter und der Trefferposition
local characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitude
if characterHitProximity > MAX_HIT_PROXIMITY then
return false
end
-- Überprüfen Sie, ob durch Wände geschossen wird
local toolHandle = getPlayerToolHandle(playerFired)
if toolHandle then
local rayLength = (hitPosition - toolHandle.Position).Magnitude
local rayDirection = (hitPosition - toolHandle.Position).Unit
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {playerFired.Character}
local rayResult = workspace:Raycast(toolHandle.Position, rayDirection * rayLength, raycastParams)
-- Wenn eine Instanz getroffen wurde, die nicht der Charakter ist, ignorieren Sie den Schuss
if rayResult and not rayResult.Instance:IsDescendantOf(characterToDamage) then
return false
end
end
return true
end
-- Benachrichtigen Sie alle Clients, dass ein Laser abgefeuert wurde, damit sie den Laser anzeigen können
local function playerFiredLaser(playerFired, endPosition)
local toolHandle = getPlayerToolHandle(playerFired)
if toolHandle then
eventsFolder.LaserFired:FireAllClients(playerFired, toolHandle, endPosition)
end
end
function damageCharacter(playerFired, characterToDamage, hitPosition)
local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")
local validShot = isHitValid(playerFired, characterToDamage, hitPosition)
if humanoid and validShot then
-- Gesundheit vom Charakter entfernen
humanoid.Health -= LASER_DAMAGE
end
end
-- Verbinden Sie Ereignisse mit den entsprechenden Funktionen
eventsFolder.DamageCharacter.OnServerEvent:Connect(damageCharacter)
eventsFolder.LaserFired.OnServerEvent:Connect(playerFiredLaser)

ClientLaserManager

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LaserRenderer = require(Players.LocalPlayer.PlayerScripts:WaitForChild("LaserRenderer"))
local eventsFolder = ReplicatedStorage.Events
-- Zeigen Sie den Laser eines anderen Spielers an
local function createPlayerLaser(playerWhoShot, toolHandle, endPosition)
if playerWhoShot ~= Players.LocalPlayer then
LaserRenderer.createLaser(toolHandle, endPosition)
end
end
eventsFolder.LaserFired.OnClientEvent:Connect(createPlayerLaser)
©2026 Roblox Corporation. Roblox, das Roblox-Logo und "Powering Imagination" gehören zu unseren eingetragenen und nicht eingetragenen Markenzeichen in den USA und anderen Ländern.