How would I make a hit location?

  1. What do you want to achieve? Keep it simple and clear!
    I want to make a hit location like this in the image below:

  2. What is the issue? Include screenshots / videos if possible!
    I do not know how to make it.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I couldn’t find any.

Here is my local script:

--// Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")

--// Run Service
local Heartbeat = RunService.Heartbeat

--// Camera
local Camera = workspace.CurrentCamera

--// Tool
local Tool = script.Parent

--// Player
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")

--// Body Parts
local UpperTorso = Character.UpperTorso
local Root = Character.HumanoidRootPart

--// Mouse
local Mouse = Player:GetMouse()
local DefaultMouseIcon = Mouse.Icon

--// Tool Configuration
local ToolConfigurationFolder = ReplicatedStorage["TPS-GunSystem"].ToolConfiguration
local ToolConfigFolder = ToolConfigurationFolder:FindFirstChild(Tool.Name)

--// Tool Config Folder Children
local Config = require(ToolConfigFolder.Config)
local AnimationsFolder = ToolConfigFolder.Animations
local SoundsFolder = ToolConfigFolder.Sounds

--// Folders
local RemotesFolder = ReplicatedStorage["TPS-GunSystem"].RemoteEvents
local AssetsFolder = ReplicatedStorage["TPS-GunSystem"].Assets
local GUIFolder = AssetsFolder.GUI

--// Sounds
local FireSND = Tool.Handle:WaitForChild("Fire")
local ReloadSND = Tool.Handle:WaitForChild("Reload")
local EquipSND = Tool.Handle:WaitForChild("Equip")
local AimUpSND = Tool.Handle:WaitForChild("AimUp")
local AimDownSND = Tool.Handle:WaitForChild("AimDown")

--// Camera POS
local CameraPOS = "Right"

--// Animations
--local EquipAnim = Humanoid.Animator:LoadAnimation(AnimationsFolder.Equip)
local AimAnim = Humanoid.Animator:LoadAnimation(AnimationsFolder.Aim)
local FireAnim = Humanoid.Animator:LoadAnimation(AnimationsFolder.Fire)
local IdleAnim = Humanoid.Animator:LoadAnimation(AnimationsFolder.Idle)
local ReloadAnim = Humanoid.Animator:LoadAnimation(AnimationsFolder.Reload)

--// FOV (FIELD OF VIEW)
local DefaultFOV = Camera.FieldOfView
local AimFOV = Config.AimFOV
local AimSpeed = Config.AimSpeed

--// Tool Folders
local ValuesFolder = Tool:WaitForChild("Values")

--// Defauly Humanoid Rotation
local DefaultHumanoidRotation = Humanoid.AutoRotate

--// Values Children
local CurrentAmmoVal = ValuesFolder.CurrentAmmo
local MaxAmmoVal = ValuesFolder.MaxAmmo

--// Values Children Value Changer
CurrentAmmoVal.Value = Config.CurrentAmmo
MaxAmmoVal.Value = Config.MaxAmmo

--// Settings
local BodyDamage = Config.BodyDamage
local HeadDamage = Config.HeadDamage
local BulletSpread = Config.BulletSpread
local FireRate = Config.FireRate
local BulletDrop = Config.BulletDrop
local FireModeName = ""

-- Select fire mode name
if Config.FireMode == 1 then
    FireModeName = "Semi"
elseif Config.FireMode == 2 then
    FireModeName = "Auto"
elseif Config.FireMode == 3 then
    FireModeName = "Shotgun"
elseif Config.FireMode == 4 then
    FireModeName = "Sniper"
end

--// Variables
local isAimming = false
local isReloading = false
local canFire = true
local MB1Held = false
local isEquipped = false

--// Tweens
local AimTweenInfo = TweenInfo.new(AimSpeed, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, 0, false, 0)
local RecoilTweenInfo = TweenInfo.new(.05, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, 0, false, 0)
local ChangeShoulder = TweenInfo.new(.35, Enum.EasingStyle.Quad, Enum.EasingDirection.Out, 0, false, 0)

local function OnCharacterAdded(character)
	Character = character
	Humanoid = character:WaitForChild("Humanoid")
	--// Tool Equipping
	Character.ChildAdded:Connect(function(Obj)
		if Obj == Tool then
			isEquipped = true
			UserInputService.MouseIconEnabled = false
			IdleAnim:Play()
			Humanoid.AutoRotate = true
			UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
			-- Equip Anim
			if Config.EquipAnim then
				--EquipAnim:Play()
			elseif not Config.EquipAnim then
				return
			end
		end
	end)

	--// Tool UnEquipping
	Character.ChildRemoved:Connect(function(Obj)
		if Obj == Tool then
			isEquipped = false
			local tween = TweenService:Create(Humanoid, ChangeShoulder, {["CameraOffset"] = Vector3.new(0, 0, 0)})
			tween:Play()
			UserInputService.MouseIconEnabled = true
			Humanoid.AutoRotate = DefaultHumanoidRotation
			UserInputService.MouseBehavior = Enum.MouseBehavior.Default
			Mouse.Icon = DefaultMouseIcon
			IdleAnim:Stop()
			TweenService:Create(Camera, AimTweenInfo, {["FieldOfView"] = DefaultFOV}):Play()
			if isReloading then
				ReloadAnim:Stop()
				ReloadSND:Stop()
				isReloading = false
				CurrentAmmoVal.Value = CurrentAmmoVal.Value
			end
			if isAimming then
				AimAnim:Stop()
			end
			-- UnEquip Anim
			if Config.UnEquipAnim then
				--EquipAnim:Play()
			elseif not Config.UnEquipAnim then
				return
			end
		end
	end)
end
task.spawn(OnCharacterAdded, Character)

--// Aim
function Aim()
	isAimming = true
	UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
	AimUpSND:Play()
	AimAnim:Play()
	IdleAnim:Stop()
	TweenService:Create(Camera, AimTweenInfo, {["FieldOfView"] = AimFOV}):Play()
end

--// UnAim
function UnAim()
	isAimming = false
	local tween = TweenService:Create(Humanoid, ChangeShoulder, {["CameraOffset"] = Vector3.new(0, 0, 0)})
	tween:Play()
	Humanoid.AutoRotate = true
	Mouse.Icon = DefaultMouseIcon
	AimDownSND:Play()
	AimAnim:Stop()
	IdleAnim:Play()
	TweenService:Create(Camera, AimTweenInfo, {["FieldOfView"] = DefaultFOV}):Play()
	Character.TorsoMovement.Disabled = true
	local TweenInformation = TweenInfo.new(
		0.25, -- Time
		Enum.EasingStyle.Sine, -- EasingStyle
		Enum.EasingDirection.Out, -- EasingDirection
		0, -- RepeatCount (when less than zero the tween will loop indefinitely)
		false, -- Reverses (tween will reverse once reaching it's goal)
		0 -- DelayTime
	)
	local TweenWaist = TweenService:Create(Character.UpperTorso.Waist, TweenInformation, {C0 = CFrame.new(0,0.2,0)})
	TweenWaist:Play()
end

--// Reload
function Reload()
	UnAim()
	isReloading = true
	RemotesFolder.ReplicateSound:FireServer(ReloadSND)
	IdleAnim:Stop()
	AimAnim:Stop()
	ReloadAnim:Play()
	wait(ReloadAnim.Length)
	RemotesFolder.Reload:FireServer()
	if isEquipped == true then
		IdleAnim:Play()
		CurrentAmmoVal.Value = MaxAmmoVal.Value
	end
	isReloading = false
end

--// Fire - Semi
function Fire_SemiAuto()
	if CurrentAmmoVal.Value > 0 then
		RemotesFolder.Fire:FireServer()
		FireAnim:Play()
		local tween = TweenService:Create(workspace.CurrentCamera, RecoilTweenInfo, {CFrame = workspace.CurrentCamera.CFrame * CFrame.Angles(Config.Recoil, 0, 0)}):Play()
		CurrentAmmoVal.Value -= 1

		local rayOrigin = Tool:WaitForChild("Handle").FirePoint.WorldPosition
		local rayDirection = (Mouse.Hit.p - Tool:WaitForChild("Handle").FirePoint.WorldPosition).Unit * Config.MaxBulletDistance

		local raycastParams = RaycastParams.new()
		raycastParams.FilterDescendantsInstances = {Tool.Handle, Tool.ModelDetails:GetChildren(), Character}
		raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
		local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

		local Beam = Instance.new("Part", workspace)
		Beam.FormFactor = "Custom"
		Beam.Transparency = 1
		Beam.Anchored = true
		Beam.Locked = true
		Beam.CanCollide = false
		Beam.Name = "Bullet"

		local Distance = (Tool:WaitForChild("Handle").FirePoint.WorldPosition - Mouse.Hit.p).magnitude
		Beam.Size = Vector3.new(0.05, 0.05, Distance)
		Beam.CFrame = CFrame.new(Tool:WaitForChild("Handle").FirePoint.WorldPosition, Mouse.Hit.p) * CFrame.new(0, 0, -Distance / 2)

		game:GetService("Debris"):AddItem(Beam, 0.05)
		if raycastResult then
			local DetectedHumanoid = raycastResult.Instance.Parent:FindFirstChild("Humanoid")
			if not DetectedHumanoid then
				DetectedHumanoid = raycastResult.Instance.Parent.Parent:FindFirstChild("Humanoid")
			end
			if DetectedHumanoid then
				RemotesFolder.HitHumanoid:FireServer(DetectedHumanoid, raycastResult.Instance, raycastResult.Position)
				if Config.Hitmark then
					SoundsFolder:WaitForChild("Hitmark"):Play()
				end
			end
		end
	elseif CurrentAmmoVal.Value == 0 or CurrentAmmoVal.Value < 0 then
		Tool:WaitForChild("Handle").NoAmmoClick:Play()
	end
end

--// User Input Service
UserInputService.InputBegan:Connect(function(input, gameProccessed)
	if input.UserInputType == Enum.UserInputType.MouseButton2 and Character:FindFirstChild(Tool.Name) then
		if not isReloading and isEquipped then
			Aim()
		end
	end
	
	if input.KeyCode == Enum.KeyCode.E then
		CameraPOS = "Right"
	elseif input.KeyCode == Enum.KeyCode.Q then
		CameraPOS = "Left"
	end
	
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		MB1Held = true
		if isAimming and canFire and not isReloading then
			if FireModeName == "Semi" then
				canFire = false
				Fire_SemiAuto()
				wait(FireRate)
				canFire = true
			elseif FireModeName == "Auto" then
				while MB1Held do
					Fire_SemiAuto()
					wait(FireRate)
				end
			elseif FireModeName == "Shotgun" then
				
			elseif FireModeName == "Sniper" then
				
			end
		end
	end
	if input.KeyCode == Enum.KeyCode.R and isReloading == false and isEquipped == true and CurrentAmmoVal.Value < MaxAmmoVal.Value then
		Reload()
	end
end)

UserInputService.InputEnded:Connect(function(input, gameProccessed)
	if input.UserInputType == Enum.UserInputType.MouseButton2 and Character:FindFirstChild(Tool.Name) then
		UnAim()
	end
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		MB1Held = false
	end
end)


Character.Humanoid.Died:Connect(function()
	Camera.FieldOfView = DefaultFOV
	UserInputService.MouseBehavior = Enum.MouseBehavior.Default
	local camLv = Camera.CFrame.lookVector
	local camRotation = math.atan2(-camLv.X, -camLv.Z)
	Character.Humanoid.AutoRotate = false
end)

RunService.RenderStepped:Connect(function()
	if isAimming then
		local camLv = Camera.CFrame.lookVector
		local camRotation = math.atan2(-camLv.X, -camLv.Z)
		local tweenInfo = TweenInfo.new(
			0.01, -- Time
			Enum.EasingStyle.Sine, -- EasingStyle
			Enum.EasingDirection.Out, -- EasingDirection
			0, -- RepeatCount (when less than zero the tween will loop indefinitely)
			false, -- Reverses (tween will reverse once reaching it's goal)
			0 -- DelayTime
		)
		local tween = TweenService:Create(Root, tweenInfo, {CFrame = CFrame.new(Root.Position) * CFrame.Angles(0, camRotation, 0)})
		tween:Play()
	end
	if CameraPOS == "Right" and isAimming then
		local tween = TweenService:Create(Humanoid, ChangeShoulder, {["CameraOffset"] = Vector3.new(2.5, 0, 0)})
		tween:Play()
	elseif CameraPOS == "Left" and isAimming then
		local tween = TweenService:Create(Humanoid, ChangeShoulder, {["CameraOffset"] = Vector3.new(-2.5, 0, 0)})
		tween:Play()
	end
end)
1 Like

raycast from the gun to your direction then if it hits something move a gui on your screen to that hit position using workspace.CurrentCamera:WorldSpaceToScreenPoint

make sure the hit gui has its anchor point at 0.5, 0.5

world space to screen point code from the developer hub

local camera = workspace.CurrentCamera
local worldPoint = Vector3.new(0, 10, 0)
local vector, onScreen = camera:WorldToScreenPoint(worldPoint)
 
local screenPoint = Vector2.new(vector.X, vector.Y)
local depth = vector.Z

should not show gui if ray hit is not on screen

Yeah, but I want it to be on the hit location when I’m aimming and when I unaim, the hit location goes away.

then check if you are aiming if not make the gui invisble and dont raycast

1 Like