PcoWSkbVqDnWTu_dm2ix
Hit Detection with Lasers
Part 2 - Firing Towards the Target
Hit Detection with Lasers
Part 2 - Firing Towards the Target

Now that the 3D mouse position is known, it can be used as a target position to fire a laser towards. A second ray can be cast between the player’s weapon and the target position using the Raycast function.

  1. Declare a constant called MAX_LASER_DISTANCE at the top of the script and assign it to 500, or your chosen range for the laser blaster.
    local UserInputService = game:GetService("UserInputService")
    
    local tool = script.Parent
    
    local MAX_MOUSE_DISTANCE = 1000
    local MAX_LASER_DISTANCE = 500
  2. Create a function called fireWeapon under the getWorldMousePosition function.
  3. Call getWorldMousePosition and assign the result to a variable named mousePosition. This will be the target position for raycast.
            -- No object was hit so calculate the position at the end of the ray
            return screenToWorldRay.Origin + directionVector
        end
    end
    
    local function fireWeapon()
        local mouseLocation = getWorldMousePosition()
    end
    
    local function toolEquipped()
        tool.Handle.Equip:Play()
    end

This time, the direction vector for the raycast function will represent the direction from the player’s tool position to the target location.

  1. Declare a variable named targetDirection and calculate the direction vector by subtracting the tool position from mouseLocation.
  2. Normalise the vector by using its Unit property. This gives it a magnitude of 1, which makes it easy to multiply by a length later.
    local function fireWeapon()
        local mouseLocation = getWorldMousePosition()
    
        -- Calculate a normalised direction vector and multiply by laser distance
        local targetDirection = (mouseLocation - tool.Handle.Position).Unit
    end
  3. Declare a variable named directionVector and assign to it the targetDirection multiplied by the MAX_LASER_DISTANCE.
        local targetDirection = (mouseLocation - tool.Handle.Position).Unit
    
        -- The direction to fire the weapon, multiplied by a maximum distance
        local directionVector = targetDirection * MAX_LASER_DISTANCE
    end

A RaycastParams object can be used to store additional parameters for the raycast function. It will be used in your laser blaster to make sure the raycast doesn’t accidentally collide with the player firing the weapon. Any parts included in the FilterDescentantsInstances property of a RaycastParams object will be ignored in the raycast.

  1. Continue the fireWeapon function and declare a variable called weaponRaycastParams. Assign a new RaycastParams object to it.
  2. Create a table containing the player’s local character and assign it to the weaponRaycastParams.FilterDescendantsInstances property.
  3. Raycast from the player’s tool handle position, in a direction towards the directionVector. Remember to add weaponRaycastParams as an argument this time. Assign this to a variable named 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()
   
    -- Calculate a normalised direction vector and multiply by laser distance
    local targetDirection = (mouseLocation - tool.Handle.Position).Unit
   
    -- The direction to fire the weapon multiplied by a maximum distance
    local directionVector = targetDirection * MAX_LASER_DISTANCE
   
    -- Ignore the player's character to prevent them from damaging themselves
    local weaponRaycastParams = RaycastParams.new()
    weaponRaycastParams.FilterDescendantsInstances = {Players.LocalPlayer.Character}
    local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
end

Finally, you’ll need to check that the raycast operation returned a value. If a value is returned, an object was hit by the ray and a laser can be created between the weapon and hit location. If nothing was returned, the final position needs to be calculated in order to create the laser.

  1. Declare an empty variable named hitPosition.
  2. Use an if statement to check whether weaponRaycastResult has a value. If an object was hit, assign weaponRaycastResult.Position to hitPosition.
        local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
    
        -- Check if any objects were hit between the start and end position
        local hitPosition
        if weaponRaycastResult then
            hitPosition = weaponRaycastResult.Position
        end
  3. If weaponRaycastResult has no value, calculate the end position of the raycast by adding together the position of the tool handle with the directionVector. Assign this to hitPosition.
        local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
    
        -- Check if any objects were hit between the start and end position
        local hitPosition
        if weaponRaycastResult then
            hitPosition = weaponRaycastResult.Position
        else
            -- Calculate the end position based on maximum laser distance
            hitPosition = tool.Handle.Position + directionVector
        end
    end
  4. Navigate 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

Checking the Object Hit

To find if the object hit by the laser is part of a player’s character or just a piece of scenery, you’ll need to look for a Humanoid, as every character has one.

First, you’ll need to find the character model. If a part of the character was hit, you cannot assume the parent of the object hit would be the character. The laser could have hit a body part, an accessory, or a tool, all of which are located in different parts of the character’s hierarchy.

You can use FindFirstAncestorOfClass to find a character model ancestor of the object hit by the laser, if one exists. If you find a model and it contains a humanoid, in most cases you can assume it’s a character.

  1. Add the highlighted code below to the weaponRaycastResult if statement to check if a character was hit.
        -- Check if any objects were hit between the start and end position
        local hitPosition
        if weaponRaycastResult then
            hitPosition = weaponRaycastResult.Position
        
            -- The instance hit will be a child of a character model
            -- If a humanoid is found in the model then it's likely a player's character
            local characterModel = weaponRaycastResult.Instance:FindFirstAncestorOfClass("Model")
            if characterModel then
                local humanoid = characterModel:FindFirstChild("Humanoid")
                if humanoid then
                    print("Player hit")
                end
            end
        else
            -- Calculate the end position based on maximum laser distance
            hitPosition = tool.Handle.Position + directionVector
        end

Now the laser blaster should print Player hit to the output window every time the raycast operation hits another player.

Testing with Multiple Players

Two players are needed to test if the weapon raycast is finding other players, so you need to start a local server.

  1. Select the Test tab in Studio.
  2. Make sure the players dropdown is set to ‘2 Players’ and click the Start button to start a local server with 2 clients. Three windows will appear. The first window will be the local server, the other windows will be the clients for Player1 and Player2.
  3. On one client, test shooting the other player with the weapon by clicking on them. “Player hit” should be displayed in the output each time a player is shot.

You can find out more about the Test tab here.


Previous Page Hit Detection with Lasers Next Page Rendering the Laser Beam