In diesem Tutorial lernen Sie, wie Sie einen Laser vom Blaster in Creating Player Tools und entdecken, ob er einen Spieler:intrifft.
Raycasting, um Kollisionen zu finden
Raycasting erstellt einen unsichtbaren Strahl von einer Startposition in eine bestimmte Richtung mit einer bestimmten Länge. Wenn der Strahl mit Objekten oder Terrain auf seinem Weg kollidiert, gibt er Informationen über die Kollision zurück, z. B. die Position und das Objekt, mit dem der Strahl kollidiert.
Die Maus Position finden
Bevor ein Laser geschossen werden kann, musst du zuerst wissen, wo der Spieler zielt. Dies kann durch Raycasting von der 2D-Maus-Position des Spieler:inauf dem Bildschirm direkt vor der Kamera in die Weltkollidieren. Der Laser wird mit dem Zielen des Spielers mit der Maus kollidieren.
Öffnen Sie das ToolController -Skript innerhalb des Blaster-Tools von Creating Player Tools. Wenn Sie dieses Tutorial noch nicht abgeschlossen haben, können Sie das Blaster-Modell herunterladen und es in StarterPack einfügen.
In der oberen Zeile des Skript, das. PL: die Skriptsdeklarieren Sie eine Konstante namens MAX_MOUSE_DISTANCE mit einem Wert von 1000 .
Erstellen Sie eine Funktion namens getWorldMousePosition.
local tool = script.Parentlocal MAX_MOUSE_DISTANCE = 1000local function getWorldMousePosition()endlocal function toolEquipped()tool.Handle.Equip:Play()endlocal function toolActivated()tool.Handle.Activate:Play()end-- Verbinde Ereignisse mit passenden Funktionentool.Equipped:Connect(toolEquipped)tool.Activated:Connect(toolActivated)Verwenden Sie die GetMouseLocation-Funktion von UserInputService, um die 2D-Mausposition des Spieler:inauf dem Bildschirm zu erhalten. Weisen Sie dies einer Variable mit dem Namen mouseLocation zu.
local UserInputService = game:GetService("UserInputService")local tool = script.Parentlocal MAX_MOUSE_DISTANCE = 1000local function getWorldMousePosition()local mouseLocation = UserInputService:GetMouseLocation()end
Nun ist die 2D-Maus-Position bekannt, seine X und Y Eigenschaften können als Argumente für die Class.Camera:ViewportPointToRay() -Funktion verwendet werden, die einen 1> Datatype.Ray1> vom Bildschirm in die Welterstellt.
Verwende die X und Y Eigenschaften von mouseLocation als Argumente für die 1> Class.Camera:ViewportPointToRay()|ViewportPointToRay()1> Funktion. Weise dies einer Variable namens 4> screenToWorldRay4> zu.
local function getWorldMousePosition()local mouseLocation = UserInputService:GetMouseLocation()-- Erstellen Sie einen Strahl aus der 2D-Maus-Positionlocal screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)end
Es ist Zeit, die Funktion Raycast zu verwenden, um zu überprüfen, ob der Strahl ein Objekt trifft. Dies erfordert eine Startposition und einen Vektorkraft: In diesem Beispiel verwenden Sie die Eigenschaften und Richtungsvektoren 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 musst du den Richtungsvektor um MAX_MOUSE_DISTANCE multiplizieren.
Erkläre eine Variable namens DirectionVector und weise dem Wert screenToWorldRay.Direction mit Multiplikator MAX_MOUSE_DISTANCE zu.
local function getWorldMousePosition()local mouseLocation = UserInputService:GetMouseLocation()-- Erstellen Sie einen Strahl aus der 2D-Maus位置local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)-- Die Einheitsteuerungsrichtung des Strahls, der mit einer maximalen Distanz multipliziert wirdlocal directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCERufen Sie die Raycast Funktion des Arbeitsbereichs auf, indem Sie die Eingabe-Eigenschaft von screenToWorldRay als ersten Argument und 1> durationVector1> als zweiten übergeben. Verweisen Sie auf diesen Variablen mit dem Namen 4> raycastResult4>.
local function getWorldMousePosition()local mouseLocation = UserInputService:GetMouseLocation()-- Erstellen Sie einen Strahl aus der 2D-Maus位置local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)-- Die Einheitsteuerungsrichtung des Strahls, der mit einer maximalen Distanz multipliziert wirdlocal directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE-- Raycast von der Ray-Herkunft in Richtung seiner Richtunglocal raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)
Kollisionsinformationen
Wenn die Raycast-Operation ein Objekt durch den Strahl getroffen findet, wird eine RaycastResult zurückgegeben, die Informationen über die Kollision zwischen dem Strahl und dem Objekt enthält.
RaycastResult-Eigenschaft | Beschreibung |
---|---|
Instanz | Die BasePart oder Terrain Zelle, in der der Strahl kreuzte. |
Position | Wo sich die Intersektion befindet; Normalerweise ein Punkt direkt auf der Oberfläche eines Teils oder Gelände. |
Material | Das Material an der Kollisionsstelle. |
Normal | Der normale Vektor des interessierten Gesichts. Dies kann verwendet werden, um zu bestimmen, in welche Richtung das Gesicht zeigt. |
Die Position Eigenschaft wird die Position des Objekts sein, über das die Maus mit der Maus positioniert ist. Wenn die Maus nicht über ein Objekt innerhalb einer MAX_MOUSE_DISTANCE Range schwebt, wird raycastResult null sein.
Erstellen Sie ein if- Statement, um zu überprüfen, ob raycastResult existiert.
Wenn raycastResult einen Wert hat, geben Sie seine Position Eigenschaftenzurück.
Wenn raycastResult null ist, finden Sie das Ende des Raycast. Berechnen Sie die 3D-Position der Maus, indem Sie screenToWorldRay.Origin und directionVector zusammen fügen.
local function getWorldMousePosition()
local mouseLocation = UserInputService:GetMouseLocation()
-- Erstellen Sie einen Strahl aus der 2D-Maus位置
local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
-- Die Einheitsteuerungsrichtung des Strahls, der mit einer maximalen Distanz multipliziert wird
local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
-- Raycast von der Ray-Herkunft in Richtung seiner Richtung
local raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)
if raycastResult then
-- Kehre den 3D-Punkt der Intersektion zurück
return raycastResult.Position
else
-- Kein Objekt wurde getroffen, so dass die Position am Ende des Strahls berechnet wird
return screenToWorldRay.Origin + directionVector
end
end
Feuern Sie auf das Ziel
Da die 3D-Mausposition bekannt ist, kann sie als Zielposition verwendet werden, um einen Laser auf das Ziel zu feuern. Ein zweiter Strahl kann zwischen der Waffe des Spieler:inund der Zielposition mit der Strahlenwurf-Funktion kastiert werden.
Erkläre eine Konstante namens MAX_LASER_DISTANCE an der Spitze des Skripts und weise sie auf 500 oder deine gewählte Reichweite für den Laserblaster zu.
local UserInputService = game:GetService("UserInputService")local tool = script.Parentlocal MAX_MOUSE_DISTANCE = 1000local MAX_LASER_DISTANCE = 500Erstellen Sie eine Funktion namens fireWeapon unter der getWorldMousePosition Funktion.
Rufen Sie getWorldMousePosition auf und weisen Sie das Ergebnis an eine Variable namens mousePosition zu. Dies wird die Zielposition für Raycast sein.
-- Kein Objekt wurde getroffen, so dass die Position am Ende des Strahls berechnet wirdreturn screenToWorldRay.Origin + directionVectorendendlocal function fireWeapon()local mouseLocation = getWorldMousePosition()endlocal function toolEquipped()tool.Handle.Equip:Play()end
Diesmal wird der Richtungsvektor für die Raycast-Funktion die Richtung vom Werkzeug des Spieler:inzur Zielposition repräsentieren.
Erkläre eine Variable namens targetDirection und berechne den Richtungsvektor, indem du die Toolposition von mouseLocation abziehst.
Normalisieren Sie den Vector, indem Sie seine Eigenschaftenverwenden. Dies gibt ihm eine Größe von 1, was es einfach macht, später um eine Länge zu multiplizieren.
local function fireWeapon()local mouseLocation = getWorldMousePosition()-- Berechnen Sie einen normalisierten Richtungsvektor und multiplizieren Sie ihn durch Laser-Entfernunglocal targetDirection = (mouseLocation - tool.Handle.Position).UnitendErkläre eine Variable namens DirectionVector und weise ihr den targetDirection Multiplikator mit der MAX_LASER_DISTANCE zu.
local targetDirection = (mouseLocation - tool.Handle.Position).Unit-- Die Richtung, in die die Waffe abgefeuert werden soll, multipliziert durch eine maximale Entfernunglocal directionVector = targetDirection * MAX_LASER_DISTANCEend
Ein RaycastParams-Objekt kann verwendet werden, um zusätzliche Parameter für die Funktion raycast zu speichern. Es wird in deinem Laserblaster verwendet, um sicherzustellen, dass der Raycast nicht mit dem Spieler, der die Waffe feuert, versehentlich kollidiert. Alle Teile, die in der Eigenschaft Datatype.RaycastParams.Filter
Fortsetzen Sie die Funktion fireWeapon und erklären Sie eine Variable namens weaponRaycastParams . Weisen Sie einem neuen RaycastParams-Objekt zu.
Erstellen Sie eine Tabelle, die den lokalen Charakter des Spieler:inenthält, und weisen Sie ihn an die weaponRaycastParams.FilterDescendantsInstancesEigenschaftenzu.
Raycast von der Spieler:in, in eine Richtung in Richtung des directionVector. Denken Sie daran, dieses Mal weaponRaycastParams als Argument hinzuzufügen. Zuordnen Sie dies an eine Variable namens weaponRaycastResult.
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 durch Laser-Entfernung
local targetDirection = (mouseLocation - tool.Handle.Position).Unit
-- Die Richtung, mit der die Waffe abgefeuert wird, multipliziert durch eine maximale Entfernung
local directionVector = targetDirection * MAX_LASER_DISTANCE
-- Ignoriere den Charakter des Spieler:in, um ihn daran zu hindern, sich selbst zu schaden
local weaponRaycastParams = RaycastParams.new()
weaponRaycastParams.FilterDescendantsInstances = {Players.LocalPlayer.Character}
local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
end
Schließlich musst du überprüfen, dass die Raycast-Operation einen Wert zurückgegeben hat. Wenn ein Wert zurückgegeben wird, wurde ein Objekt von dem Laser getroffen und ein Laser zwischen der Waffe und dem Treffort erstellt. Wenn nichts zurückgegeben wurde, muss die endgültige Position berechnet werden, um den Laser zu erstellen.
Erklären Sie eine leere Variable namens hitPosition .
Verwenden Sie eine if-Anweisung, um zu überprüfen, ob weaponRaycastResult einen Wert hat. Wenn ein Objekt getroffen wurde, weisen Sie weaponRaycastResult.Position an 2> hitPosition2> .
local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)-- Überprüfen Sie, ob irgendwelche Objekte zwischen der Start- und Endposition getroffen wurdenlocal hitPositionif weaponRaycastResult thenhitPosition = weaponRaycastResult.PositionendWenn weaponRaycastResult keinen Wert hat, berechnen Sie die Endposition des Raycast, indem Sie die Position des Werkzeuggriffs mit dem numberDirectionVector zusammenfügen. Weisen Sie dies an directionVector zu.
local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)-- Überprüfen Sie, ob irgendwelche Objekte zwischen der Start- und Endposition getroffen wurdenlocal hitPositionif weaponRaycastResult thenhitPosition = weaponRaycastResult.Positionelse-- Berechnen Sie die Endposition basierend auf der maximalen Laser-EntfernunghitPosition = tool.Handle.Position + directionVectorendendNavigate to the toolActivated function and call the fireWeapon function, so that the laser fires each time the tool is activated.
local function toolActivated()tool.Handle.Activate:Play()fireWeapon()end
Objekt-Treffer überprüfen
Um zu finden, ob das von dem Laser getroffene Objekt Teil eines Charakters des Spieler:inist oder nur ein Teil der Szenerie, musst du nach einem Humanoid suchen, da jeder Charakter eines hat.
Zuerst musst du das Charaktermodell finden. Wenn ein Teil des Charakters getroffen wurde, kannst du nicht davon ausgehen, dass der Elternteil des Objekts getroffen wurde. Der Laser könnte einen Körperteil, ein Zubehör oder ein Tooltreffen, alle von denen sich in verschiedenen Teilen der Charakterniere befinden.
Sie können FindFirstAncestorOfClass verwenden, um ein Charaktermodell-Vorläufer des Objekts zu finden, das vom Laser getroffen wurde, wenn es vorhanden ist. Wenn Sie ein Modell finden und es ein Humanoid enthält, können Sie es in der Regel als Charakter annehmen.
Fügen Sie den markierten Code unten zu der weaponRaycastResult if Anweisung hinzu, um zu überprüfen, ob ein Charakter getroffen wurde.
-- Überprüfen Sie, ob irgendwelche Objekte zwischen der Start- und Endposition getroffen wurdenlocal hitPositionif weaponRaycastResult thenhitPosition = weaponRaycastResult.Position-- Die zu treffende Instanz wird ein Kind eines Modellsein-- Wenn ein Humanoid im Modell gefunden wird, ist es wahrscheinlich der Charakter eines Spieler:inlocal characterModel = weaponRaycastResult.Instance:FindFirstAncestorOfClass("Model")if characterModel thenlocal humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")if humanoid thenprint("Player hit")endendelse-- Berechnen Sie die Endposition basierend auf der maximalen Laser-EntfernunghitPosition = tool.Handle.Position + directionVectorend
Jetzt sollte der Laserblaster jedes Mal, wenn die Raycast-Operation einen anderen Spieler:intrifft, Player hit zur Ausgabe-Fenster drucken.
Testen mit mehreren Spielern
Zwei Spieler sind erforderlich, um zu testen, ob die Waffenraycast andere Spieler findet, sodass Sie einen lokalen Server starten müssen.
Wählen Sie die Test -Registerkarte in Studio.
Stellen Sie sicher, dass die Dropdown-Liste auf "2 Spieler" eingestellt ist und klicken Sie auf die Schaltfläche "Starten", um einen lokalen Server mit 2 Clients zu starten mit 3 Fenstern. Das erste Fenster wird sein. Das andere Fenster wird die Clients für Player1 und Player2 sein.
Auf einem Client testen Sie das andere Spieler mit der Waffe, indem Sie auf sie klicken. "Player hat" sollte jedes Mal angezeigt werden, wenn ein Spieler erschossen wird.
Weitere Informationen finden Sie unter der Registerkarte Test hier.
Die Laserposition finden
Der Blaster sollte einen roten Lichtstrahl auf sein Ziel abfeuern. Die Funktion für dieses wird in einem ModuleScript sein, sodass sie später in anderen Skripts wiederverwendet werden kann. Zuerst muss das Skript den Ort finden, an dem der Laserstrahl gerendert werden soll.
Erstellen Sie ein ModuleScript mit dem Namen LaserRenderer , der unter StarterPlayer.Scripts unter StarterPlayer übergeordnet ist.
Öffnen Sie das Skript und benennen Sie die Modul-Tabelle in den Namen des Skripts LaserRender .
Erkläre eine Variable namens SHOT_DURATION mit einem Wert von 0.15 . Dies wird die Zeit sein, die der Laser für sichtbar ist (in Sekunden).
Erstellen Sie eine Funktion von LaserRender namens createLaser mit zwei Parametern wie toolHandle und endPosition .
local LaserRenderer = {}local SHOT_DURATION = 0.15 -- Zeit, für die der Laser sichtbar ist-- Erstellen Sie einen Laserstrahl von einer Startposition in Richtung einer Endpositionfunction LaserRenderer.createLaser(toolHandle, endPosition)endreturn LaserRendererErkläre eine Variable namens startPosition und setze die Eigenschaft Position von toolHandle als ihren Wert. Dies wird die Position des Lasers des Spieler:insein.
Erkläre eine Variable namens laserDistance und subtrahiere endPosition von startPosition, um den Unterschied zwischen den beiden Vektoren zu finden. Verwende die Eigenschaft 1> Magnitude1> von dieser, um die Länge des Laserstrahls zu erhalten.
function LaserRenderer.createLaser(toolHandle, endPosition)local startPosition = toolHandle.Positionlocal laserDistance = (startPosition - endPosition).MagnitudeendErkläre eine laserCFrame Variable, um die Position und Ausrichtung des Laserstrahls zu speichern. Die Position muss der Mitte des Starts und Ends des Laserstrahls sein. Verwende CFrame.lookAt , um einen neuen CFrame
function LaserRenderer.createLaser(toolHandle, endPosition)local startPosition = toolHandle.Positionlocal laserDistance = (startPosition - endPosition).Magnitudelocal laserCFrame = CFrame.lookAt(startPosition, endPosition) * CFrame.new(0, 0, -laserDistance / 2)end
Erstellen der Laser-Teil
Jetzt, da Sie wissen, wo Sie einen Laserstrahl erstellen müssen, müssen Sie den Strahl selbst hinzufügen. Dies kann mit einem Neon-Teil leicht getan werden.
Erkläre eine Variable laserPart und weise ihr eine neue Part Instanz zu.
Setzen Sie die folgenden Eigenschaften von laserPart :
- Größe : Vector3.new(0.2, 0.2, laserDistance)
- CFrame : laserCFrame
- Verankert : true
- Kann kollidieren : fals
- Farbe : Color3.fromRGB(225, 0, 0) (eine starke rote Farbe)
- Material : Enum.Material.Neon
Elternteil laserPart zu Workspace .
Fügen Sie das Teil dem Debris -Dienst hinzu, damit es nach der Anzahl der Sekunden in der SHOT_DURATION Variable entfernt wird.
function LaserRenderer.createLaser(toolHandle, endPosition)local startPosition = toolHandle.Positionlocal laserDistance = (startPosition - endPosition).Magnitudelocal 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 = laserCFramelaserPart.Anchored = truelaserPart.CanCollide = falselaserPart.Color = Color3.fromRGB(225, 0, 0)laserPart.Material = Enum.Material.NeonlaserPart.Parent = workspace-- Fügen Sie Laserstrahl dem Debris-Dienst hinzu, um entfernt und sauber zu werdenDebris:AddItem(laserPart, SHOT_DURATION)end
Jetzt ist die Funktion, den Laserstrahl zu rendern, fertig, sie kann von dem ToolController aufgerufen werden.
In der obersten Zeile des Skript, das. PL: die Skripts, declare eine Variable namens LaserRenderer und erfordere das LaserRenderer-ModulScript, das in PlayerScripts befindet sich.
local UserInputService = game:GetService("UserInputService")local Players = game:GetService("Players")local LaserRenderer = require(Players.LocalPlayer.PlayerScripts.LaserRenderer)local tool = script.ParentAt the bottom of the fireWeapon function, call the LaserRender createLaser function using the tool handle and hitPosition as arguments.
-- Berechnen Sie die Endposition basierend auf der maximalen Laser-EntfernunghitPosition = tool.Handle.Position + directionVectorendLaserRenderer.createLaser(tool.Handle, hitPosition)endTesten Sie die Waffe, indem Sie auf die Schaltfläche Spielen klicken. Ein Laserstrahl sollte zwischen der Waffe und der Maus sichtbar sein, wenn das Werkzeug aktiviert ist.
Waffenfeuerrate steuern
Waffen benötigen eine Verzögerung zwischen jedem Schuss, um die Spieler daran zu hindern, zu viel Schaden in einer kurzen Zeit zu verursachen. Dies kann durch den Check kontrolliert werden, ob genug Zeit seit dem letzten Feuer eines Spielers vergangen ist.
Erklären Sie eine Variable oben in der ToolController mit dem Namen FIRE_RATE . Dies wird die minimale Zeit zwischen jedem Schuss sein. Gib ihm einen Wert deiner Wahl; dieses Beispiel verwendet 0.3 Sekunden.
Erkläre eine weitere Variable unterhalb mit dem Namen timeOfPreviousShot mit einem Wert von 0 . Dies speichert das letzte Mal, dass der Spieler feuert, und wird mit jedem Schuss aktualisiert.
local MAX_MOUSE_DISTANCE = 1000local MAX_LASER_DISTANCE = 300local FIRE_RATE = 0.3local timeOfPreviousShot = 0Erstellen Sie eine Funktion namens kannShootWeapon mit keine Parametern. Diese Funktion wird betrachten, wie viel Zeit seit dem letzten Schuss vergangen ist und die Rückgabe wahr oder falsch ist.
local FIRE_RATE = 0.3local timeOfPreviousShot = 0-- Überprüfen, ob genug Zeit vergangen ist, seitdem der vorherige Schuss abgefeuert wurdelocal function canShootWeapon()endlocal function getWorldMousePosition()In der Funktion declare a variable namens currentTime ; weise dem Ergebnis der Aufrufe der Funktion tick() zu. Dies gibt an, wie viel Zeit seit dem 1. Januar 1970 (ein beliebiges Datum, das weit verbreitet verwendet wird, um die Zeit zu berechnen) verstrichen ist.
Subtrahiere den timeOfPreviousShot von currentTime und gib false zurück, wenn das Ergebnis kleiner als 1> FIRE_RATE1> ist; ansonsten gib 4> true4> zurück.
-- Überprüfen, ob genug Zeit vergangen ist, seitdem der vorherige Schuss abgefeuert wurdelocal function canShootWeapon()local currentTime = tick()if currentTime - timeOfPreviousShot < FIRE_RATE thenreturn falseendreturn trueendAm Ende der Funktion fireWeapon aktualisieren Sie timeOfPreviousShot jedes Mal, wenn die Waffe mit tick abgefeuert wird.
hitPosition = tool.Handle.Position + directionVectorendtimeOfPreviousShot = tick()LaserRenderer.createLaser(tool.Handle, hitPosition)endIn der toolActivated Funktion erstellen Sie ein if Statistik und rufen Sie canShootWeapon auf, um zu überprüfen, ob die Waffe abgefeuert werden kann.
local function toolActivated()if canShootWeapon() thentool.Handle.Activate:Play()fireWeapon()endend
Wenn Sie den Blaster testen, sollten Sie finden, dass, egal wie schnell Sie klicken, immer eine kurze 0,3 Sekunden Verzögerung zwischen jedem Schuss.
Schaden am Spieler
Clients können anderen Clients nicht direkt Schaden zufügen; Der Server muss für die Ausgabe von Schaden verantwortlich sein, wenn ein Spieler getroffen wird.
Clients können ein RemoteEvent verwenden, um dem Server zu sagen, 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.
Erstellen Sie einen Ordner in ReplicatedStorage namens Events.
Fügen Sie ein RemoteEvent in den Events-Ordner ein und benennen Sie es SchadensCharakter .
In ToolController , erstellen Sie Variablen am Beginn des Skripts für ReplicatedStorage und die 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.Parentlocal eventsFolder = ReplicatedStorage.Eventslocal MAX_MOUSE_DISTANCE = 1000local MAX_LASER_DISTANCE = 500Ersetzen Sie die "Player hit" druck statement in fireWeapon mit einer Reihe von Lua, um das SchadensCharacter Remote-Ereignis mit der 1> characterModel -Variable als Argument zu feuern.
local characterModel = weaponRaycastResult.Instance:FindFirstAncestorOfClass("Model")if characterModel thenlocal humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")if humanoid theneventsFolder.DamageCharacter:FireServer(characterModel)endendelse-- Berechnen Sie die Endposition basierend auf der maximalen Laser-EntfernunghitPosition = tool.Handle.Position + directionVectorend
Der Server muss Schaden am Spieler verursachen, der getroffen wurde, wenn das Ereignis ausgelöst wird.
Fügen Sie ein Skript in ServerScriptService ein und nennen Sie es ServerLaserManager.
Erkläre eine Variable namens LASER_DAMAGE und setze sie auf 10 oder einen Wert deiner Wahl.
Erstellen Sie eine Funktion namens damageCharacter mit zwei Parametern wie playerFired und characterToDamage .
In der Funktion finden Sie den Charakter's Humanoid und subtrahieren Sie LASER_DAMAGE von seiner Gesundheit.
Verbinden Sie die Funktion damageCharacter mit dem damageCharacter Remote-Ereignis im Ordner Ereignisse.
local ReplicatedStorage = game:GetService("ReplicatedStorage")local eventsFolder = ReplicatedStorage.Eventslocal LASER_DAMAGE = 10function damageCharacter(playerFired, characterToDamage)local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")if humanoid then-- Leben vom Charakter entfernenhumanoid.Health -= LASER_DAMAGEendend-- Verbinde Ereignisse mit passenden FunktioneneventsFolder.DamageCharacter.OnServerEvent:Connect(damageCharacter)Testen Sie den Blaster mit 2 Spielern, indem Sie einen lokalen Server starten. Wenn Sie den anderen Spieler:inschießen, wird seine Gesundheit um die zugewiesene Zahl LASER_DAMAGE verringert.
Other Player's Laserstrahlen rendern
Derzeit wird der Laserstrahl vom Client erstellt, der die Waffe feuert, so dass nur sie den Laserstrahl sehen können.
Wenn der Laserstrahl auf dem Server erstellt wurde, dann würde jeder ihn sehen können. jedoch, es würde eine kleine Verzögerung zwischen dem Client, der die Waffe schießt, und dem Server geben, der die Information über den Schuss erhält. Dies würde bedeuten, dass der Client, der die Waffe schießt, eine Verzögerung sehen würde, zwischen dem Zeitpunkt, an dem sie die Waffe aktivieren und sehen, und dem Zeitpunkt, an dem sie den Laserstrahl erhalten.
Um dieses Problem zu lösen, wird jedes Client seine eigenen Laserstrahlen erstellen. Dies bedeutet, dass der Client, der die Waffe schießt, sofort den Laserstrahl sieht. Andere Clients erleben eine kleine Verzögerung zwischen der Zeit, in der ein anderer Spieler schießt und ein Laser erscheint. Dies ist das beste Fall-Szenario: Es gibt keine Möglichkeit, einen Client's Laser an andere Clients zu übermitteln.
Client des Schießers
Zuerst muss der Client dem Server sagen, dass er einen Laser abgefeuert hat und die Endposition bereitgestellt.
Fügen Sie einen RemoteEvent in den Events-Ordner in ReplicatedStorage ein und benennen Sie ihn LaserFired .
Suchen Sie die Funktion fireWeapon im Skript, das. PL: die Skripts. Am Ende der Funktion feuern Sie das LaserFired-Remote-Ereignis mit 1> hitPosition1> als Argumentan.
hitPosition = tool.Handle.Position + directionVectorendtimeOfPreviousShot = tick()eventsFolder.LaserFired:FireServer(hitPosition)LaserRenderer.createLaser(tool.Handle, hitPosition)end
Der Server
Der Server muss jetzt das Ereignis erhalten, das der Client abgefeuert hat, und allen Clients die Start- und Endposition des Laserstrahls mitteilen, damit sie ihn auch rendern können.
Im ServerLaserManager Skript, das. PL: die Skripts, erstellen Sie eine Funktion namens playerFiredLaser über damageCharacter mit zwei Parametern wie 1> playerFired1> und 4> endPosition4>.
Verbinden Sie die Funktion mit dem LaserFired Remote-Ereignis.
-- Benachrichtigen Sie alle Clients, dass ein Laser abgefeuert wurde, damit sie den Laser anzeigen könnenlocal function playerFiredLaser(playerFired, endPosition)end-- Verbinde Ereignisse mit passenden FunktioneneventsFolder.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 zu vertrauen, wo möglich. Die Waffengriffposition des Charakters wird die Startposition sein, so dass der Server sie von dort aus finden kann.
Erstellen Sie eine Funktion getPlayerToolHandle über der Funktion playerFiredLaser mit einem Parameter namens player.
Verwenden Sie den folgenden Code, um den Charakter des Spieler:innach der Waffe zu suchen und das Handling-Objekt zurückzugeben.
local LASER_DAMAGE = 10-- Finden Sie die Griff des Werkzeugs, das der Spieler hältlocal function getPlayerToolHandle(player)local weapon = player.Character:FindFirstChildOfClass("Tool")if weapon thenreturn weapon:FindFirstChild("Handle")endend-- Benachrichtigen Sie alle Clients, dass ein Laser abgefeuert wurde, damit sie den Laser anzeigen könnenlocal function playerFiredLaser(playerFired, endPosition)
Der Server kann jetzt auf dem LaserFired Remote-Ereignis FireAllClients aufrufen, um die Informationen zu senden, die erforderlich sind, um den Laser an die Clients zu rendern. Dies beinhaltet den 1> Spieler1>, der den Laser abgefeuert hat (so dass der Client für diesen Spieler nicht den Laser zweimal rendern muss), den 4> Griff des Blasters
In der playerFiredLaser-Funktion rufen Sie die getPlayerToolHandle-Funktion mit playerFired als Argument auf und weisen den Wert an eine Variable namens 1> toolHandle1> zu.
Wenn toolHandle existiert, fire das LaserFired-Ereignis für alle Clients mit playerFired , toolHandle und 1> endPosition1> als Argumente.
-- Benachrichtigen Sie alle Clients, dass ein Laser abgefeuert wurde, damit sie den Laser anzeigen könnenlocal function playerFiredLaser(playerFired, endPosition)local toolHandle = getPlayerToolHandle(playerFired)if toolHandle theneventsFolder.LaserFired:FireAllClients(playerFired, toolHandle, endPosition)endend
Rendern auf den Clients
Jetzt FireAllClients wurde aufgerufen, jedes Client wird ein Ereignis vom Server erhalten, um einen Laserstrahl zu rendern. Jeder Client kann das Laserformer-Modul von früher wiederverwenden, um den Laserstrahl mit dem Schalter position und Endposition des Tool, die vom Server gesendet wird, zu rendern. Der Spieler, der den Laserstrahl zuerst gesendet hat, sollte dieses Ereignis ignorieren, sonst sehen Sie 2 Las
Erstellen Sie ein lokales Skript in StarterPlayerScripts, die ClientLaserManager heißen.
Im Skript, das. PL: die Skriptsbenötigen Sie das Laserrency-Render-Modul .
Erstellen Sie eine Funktion namens createPlayerLaser mit den Parametern playerWhoShot , toolHandle und 1> endPosition1>.
Verbinden Sie die Funktion mit dem LaserFired Remote-Ereignis in der Registerkarte Events.
In der Funktion verwenden Sie eine if Anweisung, um zu überprüfen, ob playerWhoShot nicht gleich ist 1> des lokalen Spielers.
In der if-Anweisung, rufen Sie die Funktion createLaser aus dem LaserRender-Modul mit toolHandle und endPosition als Argumente auf.
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 Spieler:inanlocal function createPlayerLaser(playerWhoShot, toolHandle, endPosition)if playerWhoShot ~= Players.LocalPlayer thenLaserRenderer.createLaser(toolHandle, endPosition)endendeventsFolder.LaserFired.OnClientEvent:Connect(createPlayerLaser)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 einen Client schießen, sollten Sie den Laser auf der anderen Seite des Monitors sehen.
Soundeffekte
Der Schießeffekt spielt derzeit nur auf dem Client, der das Projektil schießt. Du musst den Code bewegen, um den Sound zu spielen, damit andere Spieler ihn auch hören können.
Im ToolController -Skript navigiere zur toolActivated -Funktion und entferne die Zeile, die den Aktivieren-Sound wiedergibt.
local function toolActivated()if canShootWeapon() thenfireWeapon()endendIn der unteren Hälfte der createLaser -Funktion in LaserRender , declare eine Variable namens schießensound und verwende die Methode 2>Class.Instance:FindFirstChild()|FindFirstChild()2> , um nach dem 5> Aktivieren5>-Sound zu suchen.
Verwenden Sie eine if Anweisung, um zu überprüfen, ob shootingSound existiert; wenn es so ist, rufen Sie seine Play-Funktion auf.
laserPart.Parent = workspace-- Fügen Sie Laserstrahl dem Debris-Dienst hinzu, um entfernt und sauber zu werdenDebris:AddItem(laserPart, SHOT_DURATION)-- Spielen Sie den Schuss des Waffenklangslocal shootingSound = toolHandle:FindFirstChild("Activate")if shootingSound thenshootingSound:Play()endend
Verriegelung von Fernzündungen mit der Überprüfung
Wenn der Server keine Daten von eingehenden Anfragen überprüft, kann ein Hacker entfernte Funktionen und Ereignisse missbrauchen und sie verwenden, um gefälschte Werte auf den Server zu senden. Es ist wichtig, Server-seitige Überprüfung zu verwenden, um dies zu verhindern.
In seiner aktuellen Form ist das SchadensCharacter- Remote-Ereignis sehr verwundbar gegen Angriffe. Hacker könnten dieses Ereignis verwenden, um jeden Spieler im Spiel zu schaden, ohne sie zu schießen.
Die Überprüfung ist der Prozess, bei dem überprüft wird, ob die Werte, die an den Server gesendet werden, realistisch sind. In diesem Fall muss der Server:
- Überprüfen Sie, ob die Entfernung zwischen dem Spieler und der Position, die vom Laser getroffen wird, innerhalb eines bestimmten Grenzbereichs liegt.
- Raycast zwischen der Waffe, die den Laser abgefeuert hat, und der Schussposition, um sicherzustellen, dass der Schuss möglich ist und nicht durch irgendwelche Wände geht.
Client
Der Client muss den Server die Position senden, die vom Raycast getroffen wird, damit er die Reichweite realistisch überprüfen kann.
In ToolController navigieren Sie zur Zeile, in der das Remote-Ereignis für Schaden im fireWeapon-Funktionsbereich ausgeführt wird.
Füge hitPosition als Argument hinzu.
if characterModel thenlocal humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")if humanoid theneventsFolder.DamageCharacter:FireServer(characterModel, hitPosition)endend
Server
Der Client sendet jetzt einen zusätzlichen Parallel über das Schaden-Charakter-Remote-Ereignis, sodass der ServerLaserManager angepasst werden muss, um ihn anzunehmen.
Im ServerLaserManagerSkript, das. PL: die Skriptsfügen Sie einen hitPosition-Parameter an die damageCharacter-Funktion hinzu.
function damageCharacter(playerFired, characterToDamage, hitPosition)local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")if humanoid then-- Leben vom Charakter entfernenhumanoid.Health -= LASER_DAMAGEendendUnter der getPlayerToolHandle-Funktion erstellen Sie eine Funktion namens isHitValid mit drei Parametern: playerFired, 2> characterToDamage2> und 5> hitPosition5>.
endlocal function isHitValid(playerFired, characterToDamage, hitPosition)end
Der erste Check wird die Distance zwischen der Position des Treffers und dem Charakter Treffer sein.
Erkläre eine Variable namens MAX_HIT_PROXIMITY an der Spitze des Skripts und weise ihr einen Wert von 10 zu. Dies wird die maximale Distanz zwischen dem Treffer und dem Charakter sein. Ein Toleranz ist erforderlich, da der Charakter seit der Client-Feuerung des Ereignisses etwas versetzt sein kann.
local ReplicatedStorage = game:GetService("ReplicatedStorage")local eventsFolder = ReplicatedStorage.Eventslocal LASER_DAMAGE = 10local MAX_HIT_PROXIMITY = 10In der isHitValid Funktion berechnen Sie die Entfernung zwischen dem Charakter und der Treffposition. Wenn die Entfernung größer als MAX_HIT_PROXIMITY ist, dann geben Sie false zurück.
local function isHitValid(playerFired, characterToDamage, hitPosition)-- Überprüfen Sie die Entfernung zwischen dem Charakter Treffer und der Trefferpositionlocal characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitudeif characterHitProximity > MAX_HIT_PROXIMITY thenreturn falseendend
Die zweite Prüfung beinhaltet eine Raycast zwischen der Waffe, die abgefeuert wurde, und der Treffposition. Wenn die Raycast ein Objekt zurückgibt, das nicht der Charakter ist, können Sie davon ausgehen, dass der Schuss ungültig ist, da etwas den Schuss blockiert.
Kopiere den Code unten, um diesen überprüfenauszuführen. Return true am Ende der Funktion: Wenn es das beendenerreicht, haben alle Checks bestanden.
local function isHitValid(playerFired, characterToDamage, hitPosition)-- Überprüfen Sie die Entfernung zwischen dem Charakter Treffer und der Trefferpositionlocal characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitudeif characterHitProximity > 10 thenreturn falseend-- Überprüfen Sie, ob Sie durch Wände schießenlocal toolHandle = getPlayerToolHandle(playerFired)if toolHandle thenlocal rayLength = (hitPosition - toolHandle.Position).Magnitudelocal rayDirection = (hitPosition - toolHandle.Position).Unitlocal 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 war, dann ignoriere den Schussif rayResult and not rayResult.Instance:IsDescendantOf(characterToDamage) thenreturn falseendendreturn trueendErkläre eine Variable in der damageCharacter Funktion namens validShot , die das Ergebnis eines Anrufs zur isHitValid Funktion mit drei Argumenten zuweist: 1> playerFired1>, 4> characterToDamage4> und 7> hitPosition7>.
In der folgenden if-Anweisung fügen Sie einen und Operator hinzu, um zu überprüfen, ob validShot. wahr ist.
function damageCharacter(playerFired, characterToDamage, hitPosition)local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")local validShot = isHitValid(playerFired, characterToDamage, hitPosition)if humanoid and validShot then-- Leben vom Charakter entfernenhumanoid.Health -= LASER_DAMAGEendend
Nun ist das SchadensCharacter-Remote-Ereignis sicherer und wird die meisten Spieler davon abhalten, es zu missbrauchen. Beachten Sie, dass einige böswillige Spieler oft Möglichkeiten finden, um die Überprüfung zu umgehen; das Gewährleisten von Remote-Ereignissen ist ein kontinuierlicher Prozess.
Ihr Laserblaster ist jetzt fertig, mit einem grundlegenden Treffer-Erkennungssystem, das Raycasting verwendet. Versuchen Sie das Detecting User-Input Tutorial, um herauszufinden, wie Sie einen Neuladen-Aktion zu Ihrem Laserblaster hinzufügen können, oder erstellen Sie eine lustige Spielkarte und versuchen Sie Ihren Laserblaster mit anderen Spielern!
End-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, ob genug Zeit vergangen ist, seitdem der vorherige Schuss abgefeuert wurde
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 aus der 2D-Maus-Position
local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
-- Die Einheitsteuerungsrichtung des Strahls, der mit einer maximalen Distanz multipliziert wird
local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
-- Raycast von der roy's Ursprung in Richtung seiner Richtung
local raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)
if raycastResult then
-- Kehre den 3D-Punkt der Intersektion zurück
return raycastResult.Position
else
-- Kein Objekt wurde getroffen, so dass die Position am Ende des Strahls berechnet wird
return screenToWorldRay.Origin + directionVector
end
end
local function fireWeapon()
local mouseLocation = getWorldMousePosition()
-- Berechnen Sie einen normalisierten Richtungsvektor und multiplizieren Sie ihn durch Laser-Entfernung
local targetDirection = (mouseLocation - tool.Handle.Position).Unit
-- Die Richtung, in die die Waffe abgefeuert werden soll, multipliziert durch eine maximale Entfernung
local directionVector = targetDirection * MAX_LASER_DISTANCE
-- Ignoriere den Charakter des Spieler:in, um ihn daran zu hindern, sich selbst zu schaden
local weaponRaycastParams = RaycastParams.new()
weaponRaycastParams.FilterDescendantsInstances = {Players.LocalPlayer.Character}
local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
-- Überprüfen Sie, ob irgendwelche Objekte zwischen der Start- und Endposition getroffen wurden
local hitPosition
if weaponRaycastResult then
hitPosition = weaponRaycastResult.Position
-- Die zu treffende Instanz wird ein Kind eines Modellsein
-- Wenn ein Humanoid im Modell gefunden wird, ist es wahrscheinlich der Charakter eines Spieler:in
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 Laser-Entfernung
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, für die der Laser sichtbar ist
-- Erstellen Sie einen Laserstrahl von einer Startposition in Richtung 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 Laserstrahl dem Debris-Dienst hinzu, um entfernt und sauber zu werden
Debris:AddItem(laserPart, SHOT_DURATION)
-- Spielen Sie den Schuss des Waffenklangs
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 die 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)
-- Überprüfen Sie die Entfernung zwischen dem Charakter Treffer und der Trefferposition
local characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitude
if characterHitProximity > MAX_HIT_PROXIMITY then
return false
end
-- Überprüfen Sie, ob Sie durch Wände schießen
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 war, dann ignoriere 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
-- Leben vom Charakter entfernen
humanoid.Health -= LASER_DAMAGE
end
end
-- Verbinde Ereignisse mit passenden 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 Spieler:inan
local function createPlayerLaser(playerWhoShot, toolHandle, endPosition)
if playerWhoShot ~= Players.LocalPlayer then
LaserRenderer.createLaser(toolHandle, endPosition)
end
end
eventsFolder.LaserFired.OnClientEvent:Connect(createPlayerLaser)