Mouse.Hit.Position is faulty

Im trying to make a gun system using fascast but the Mouse.Hit.Position is faulty for some reason

External Media

these are the things i tried
mouse.Hit.p (literally makes it go to right and not follow the mouse at all)
raycasting mouse.hit.p (same thing)
currentcamera.CFrame.LookVector * 1000
mouse.Hit.LookVector * 1000 (makes the gun direction just a little tiny bit to mouse)
(mouse.Hit.Position - tool.Handle.position) --works fine but the vector is a bit more upper than the mouse position

game.ReplicatedStorage.Game.Events.Fire.OnClientEvent:Connect(function(plr1,direction,startposition,wepsettings,tool)
	local ignoretable = {ignoretable_Early}
	table.insert(ignoretable,tool.Parent)
	
castparams.FilterDescendantsInstances = ignoretable
if plr1 == plr then
CastingHitbox:Fire(startposition,mouse.Hit.Position,wepsettings.Velocity,castbehavior)	
else
CastingHitbox:Fire(startposition,direction,wepsettings.Velocity,castbehavior)	
end
		
	weaponsettings = wepsettings
	tableofimportant.Shooter = plr1
	
local MuzzlePosition = tool.Handle.Muzzle :: Attachment
task.spawn(
	function()
	
		
				local getmuzzleparticles = Particles_Common.Muzzle:GetChildren()
				for i = 1,#getmuzzleparticles do
					task.wait()
					local clone = getmuzzleparticles[i]:Clone() :: ParticleEmitter
					clone.Parent = MuzzlePosition
					clone.Enabled = false
					clone:Emit(1)
					game:GetService("Debris"):AddItem(clone,3)
				end
	
end)


end)
1 Like

The mouse is deprecated. Try out raycasting. It’ll give you access to the position of the intersection, the direction of the surface your mouse is hitting, and the instance your mouse is hitting. It should be less buggy.

userinputservice:GetMouseLocation()

-- not sure if this is the exact name. if it is not, it is super similar.
workspace.CurrentCamera:ViewportToWorldPoint()

Can we see your calculation of your bullet spawning and finding the direction to actually go in?

like this?

local mouseloc = game:GetService(“UserInputService”):GetMouseLocation()
local direction = workspace.CurrentCamera:ViewportPointToRay(mouseloc.X,mouseloc.Y,0)

bullets spawns here:


which then the bullet goes to direction of mouse Position (Mouse.Hit.Position)

Right, but can you show me the code that you use for the bullet to move to the end point? There’s nothing wrong with using Mouse.Hit.Position, even if it is somewhat outdated. I assume it’s an issue embedded somewhere in your code like I mentioned.

i used mouselocation and viewpointtoray and now its closer to the mouse but its still off

External Media

Im using a module called Fastcast:Redux For It
so i dont know which part it is that since the bullet is just updating the position the ray is going in
FastCastRedux.VisualizeCasts = false
local weaponsettings
local tableofimportant = {
Shooter = nil;
}
local bulletsfolder = workspace.Debris.Bullets

local castparams = RaycastParams.new()
castparams.FilterType = Enum.RaycastFilterType.Exclude
castparams.IgnoreWater = true
castparams.CollisionGroup = “Hitbox”

local castbehavior = FastCastRedux.newBehavior()
castbehavior.RaycastParams = castparams
castbehavior.MaxDistance = FastCastRedux.MaxDistance
castbehavior.AutoIgnoreContainer = false

castbehavior.Acceleration = Vector3.new(0,-10,0)

castbehavior.CosmeticBulletContainer = bulletsfolder
castbehavior.CosmeticBulletTemplate = game.ReplicatedStorage.Game.Colliders.Bullet
local CastingHitbox = FastCastRedux.new()
local function lengthchanged(ActiveCast, LastPoint, Direction, Length, Velocity, Bullet)
local bulletSize = Bullet.Size.Z / 2
local targetCFrame

	if not ActiveCast.UserData.Frames then
		ActiveCast.UserData.Frames = 0
		targetCFrame = CFrame.lookAt(LastPoint, LastPoint + Direction)
	else
		targetCFrame = CFrame.lookAt(LastPoint, LastPoint + Direction)
	end
	ActiveCast.UserData.Frames += 1
	Bullet.CFrame = targetCFrame

end
CastingHitbox.LengthChanged:Connect(lengthchanged)

You should be using ScreenPointToRay instead of ViewportPointToRay if that is what you’re going with by the way, it accounts for the GUI inset which may be causing your slight offset.

I see, might be the direction argument the code is passing to move the bullet, seems like you can find it wherever the function LengthChanged is being called.

local function SendLengthChanged(cast: ActiveCast, lastPoint: Vector3, rayDir: Vector3, rayDisplacement: number, segmentVelocity: Vector3, cosmeticBulletObject: Instance?)
–cast.LengthChanged:Fire(cast, lastPoint, rayDir, rayDisplacement, segmentVelocity, cosmeticBulletObject)
cast.Caster.LengthChanged:Fire(cast, lastPoint, rayDir, rayDisplacement, segmentVelocity, cosmeticBulletObject)
end

– Simulate a raycast by one tick.
local function SimulateCast(cast: ActiveCast, delta: number, expectingShortCall: boolean)
assert(cast.StateInfo.UpdateConnection ~= nil, ERR_OBJECT_DISPOSED)
PrintDebug(“Casting for frame.”)
local latestTrajectory = cast.StateInfo.Trajectories[#cast.StateInfo.Trajectories]

local origin = latestTrajectory.Origin
local totalDelta = cast.StateInfo.TotalRuntime - latestTrajectory.StartTime
local initialVelocity = latestTrajectory.InitialVelocity
local acceleration = latestTrajectory.Acceleration

local lastPoint = GetPositionAtTime(totalDelta, origin, initialVelocity, acceleration)
local lastVelocity = GetVelocityAtTime(totalDelta, initialVelocity, acceleration)
local lastDelta = cast.StateInfo.TotalRuntime - latestTrajectory.StartTime

cast.StateInfo.TotalRuntime += delta

-- Recalculate this.
totalDelta = cast.StateInfo.TotalRuntime - latestTrajectory.StartTime

local currentTarget = GetPositionAtTime(totalDelta, origin, initialVelocity, acceleration)
local segmentVelocity = GetVelocityAtTime(totalDelta, initialVelocity, acceleration) 
local totalDisplacement = currentTarget - lastPoint -- This is the displacement from where the ray was on the last from to where the ray is now.

local rayDir = totalDisplacement.Unit * segmentVelocity.Magnitude * delta
local targetWorldRoot = cast.RayInfo.WorldRoot
local resultOfCast = targetWorldRoot:Raycast(lastPoint, rayDir, cast.RayInfo.Parameters)

local point = currentTarget
local part: Instance? = nil
local material = Enum.Material.Air
local normal = Vector3.new()

if (resultOfCast ~= nil) then
	point = resultOfCast.Position
	part = resultOfCast.Instance
	material = resultOfCast.Material
	normal = resultOfCast.Normal
end

local rayDisplacement = (point - lastPoint).Magnitude
-- For clarity -- totalDisplacement is how far the ray would have traveled if it hit nothing,
-- and rayDisplacement is how far the ray really traveled (which will be identical to totalDisplacement if it did indeed hit nothing)

SendLengthChanged(cast, lastPoint, rayDir.Unit, rayDisplacement, segmentVelocity, cast.RayInfo.CosmeticBulletObject)
cast.StateInfo.DistanceCovered += rayDisplacement

local rayVisualization: ConeHandleAdornment? = nil
if (delta > 0) then
	rayVisualization = DbgVisualizeSegment(CFrame.new(lastPoint, lastPoint + rayDir), rayDisplacement)
end


-- HIT DETECTED. Handle all that garbage, and also handle behaviors 1 and 2 (default behavior, go high res when hit) if applicable.
-- CAST BEHAVIOR 2 IS HANDLED IN THE CODE THAT CALLS THIS FUNCTION.

if part and part ~= cast.RayInfo.CosmeticBulletObject then
	local start = tick()
	PrintDebug("Hit something, testing now.")
	
	-- SANITY CHECK: Don't allow the user to yield or run otherwise extensive code that takes longer than one frame/heartbeat to execute.
	if (cast.RayInfo.CanPierceCallback ~= nil) then
		if expectingShortCall == false then
			if (cast.StateInfo.IsActivelySimulatingPierce) then
				cast:Terminate()
				error("ERROR: The latest call to CanPierceCallback took too long to complete! This cast is going to suffer desyncs which WILL cause unexpected behavior and errors. Please fix your performance problems, or remove statements that yield (e.g. wait() calls)")
				-- Use error. This should absolutely abort the cast.
			end
		end
		-- expectingShortCall is used to determine if we are doing a forced resolution increase, in which case this will be called several times in a single frame, which throws this error.
		cast.StateInfo.IsActivelySimulatingPierce = true
	end
	------------------------------
	
	if cast.RayInfo.CanPierceCallback == nil or (cast.RayInfo.CanPierceCallback ~= nil and cast.RayInfo.CanPierceCallback(cast, resultOfCast, segmentVelocity, cast.RayInfo.CosmeticBulletObject) == false) then
		PrintDebug("Piercing function is nil or it returned FALSE to not pierce this hit.")
		cast.StateInfo.IsActivelySimulatingPierce = false
		
		if (cast.StateInfo.HighFidelityBehavior == 2 and latestTrajectory.Acceleration ~= Vector3.new() and cast.StateInfo.HighFidelitySegmentSize ~= 0) then
			cast.StateInfo.CancelHighResCast = false -- Reset this here.
			
			if cast.StateInfo.IsActivelyResimulating then
				cast:Terminate()
				error("Cascading cast lag encountered! The caster attempted to perform a high fidelity cast before the previous one completed, resulting in exponential cast lag. Consider increasing HighFidelitySegmentSize.")
			end
			

			cast.StateInfo.IsActivelyResimulating = true
			
			-- This is a physics based cast and it needs to be recalculated.
			PrintDebug("Hit was registered, but recalculation is on for physics based casts. Recalculating to verify a real hit...")
			
			-- Split this ray segment into smaller segments of a given size.
			-- In 99% of cases, it won't divide evently (e.g. I have a distance of 1.25 and I want to divide into 0.1 -- that won't work)
			-- To fix this, the segments need to be stretched slightly to fill the space (rather than having a single shorter segment at the end)
			
			local numSegmentsDecimal = rayDisplacement / cast.StateInfo.HighFidelitySegmentSize -- say rayDisplacement is 5.1, segment size is 0.5 -- 10.2 segments
			local numSegmentsReal = math.floor(numSegmentsDecimal) -- 10 segments + 0.2 extra segments
			local realSegmentLength = rayDisplacement / numSegmentsReal -- this spits out 0.51, which isn't exact to the defined 0.5, but it's close
			
			-- Now the real hard part is converting this to time.
			local timeIncrement = delta / numSegmentsReal
			for segmentIndex = 1, numSegmentsReal do
				if cast.StateInfo.CancelHighResCast then
					cast.StateInfo.CancelHighResCast = false
					break
				end
				
				local subPosition = GetPositionAtTime(lastDelta + (timeIncrement * segmentIndex), origin, initialVelocity, acceleration)
				local subVelocity = GetVelocityAtTime(lastDelta + (timeIncrement * segmentIndex), initialVelocity, acceleration) 
				local subRayDir = subVelocity * delta
				local subResult = targetWorldRoot:Raycast(subPosition, subRayDir, cast.RayInfo.Parameters)
				
				local subDisplacement = (subPosition - (subPosition + subVelocity)).Magnitude
				
				if (subResult ~= nil) then
					local subDisplacement = (subPosition - subResult.Position).Magnitude
					local dbgSeg = DbgVisualizeSegment(CFrame.new(subPosition, subPosition + subVelocity), subDisplacement)
					if (dbgSeg ~= nil) then dbgSeg.Color3 = Color3.new(0.286275, 0.329412, 0.247059) end
					
					if cast.RayInfo.CanPierceCallback == nil or (cast.RayInfo.CanPierceCallback ~= nil and cast.RayInfo.CanPierceCallback(cast, subResult, subVelocity, cast.RayInfo.CosmeticBulletObject) == false) then
						-- Still hit even at high res
						cast.StateInfo.IsActivelyResimulating = false
						
						SendRayHit(cast, subResult, subVelocity, cast.RayInfo.CosmeticBulletObject)
						cast:Terminate()
						local vis = DbgVisualizeHit(CFrame.new(point), false)
						if (vis ~= nil) then vis.Color3 = Color3.new(0.0588235, 0.87451, 1) end
						return
					else
						-- Recalculating hit something pierceable instead.
						SendRayPierced(cast, subResult, subVelocity, cast.RayInfo.CosmeticBulletObject) -- This may result in CancelHighResCast being set to true.
						local vis = DbgVisualizeHit(CFrame.new(point), true)
						if (vis ~= nil) then vis.Color3 = Color3.new(1, 0.113725, 0.588235) end
						if (dbgSeg ~= nil) then dbgSeg.Color3 = Color3.new(0.305882, 0.243137, 0.329412) end
					end
				else
					local dbgSeg = DbgVisualizeSegment(CFrame.new(subPosition, subPosition + subVelocity), subDisplacement)
					if (dbgSeg ~= nil) then dbgSeg.Color3 = Color3.new(0.286275, 0.329412, 0.247059) end
					
				end
			end
			
			-- If the script makes it here, then it wasn't a real hit (higher resolution revealed that the low-res hit was faulty)
			-- Just let it keep going.
			cast.StateInfo.IsActivelyResimulating = false
		elseif (cast.StateInfo.HighFidelityBehavior ~= 1 and cast.StateInfo.HighFidelityBehavior ~= 3) then
			cast:Terminate()
			error("Invalid value " .. (cast.StateInfo.HighFidelityBehavior) .. " for HighFidelityBehavior.")
		else
			-- This is not a physics cast, or recalculation is off.
			PrintDebug("Hit was successful. Terminating.")
			SendRayHit(cast, resultOfCast, segmentVelocity, cast.RayInfo.CosmeticBulletObject)
			cast:Terminate()
			DbgVisualizeHit(CFrame.new(point), false)
			return
		end
	else
		PrintDebug("Piercing function returned TRUE to pierce this part.")
		if rayVisualization ~= nil then
			rayVisualization.Color3 = Color3.new(0.4, 0.05, 0.05) -- Turn it red to signify that the cast was scrapped.
		end
		DbgVisualizeHit(CFrame.new(point), true)
		
		local params = cast.RayInfo.Parameters
		local alteredParts = {}
		local currentPierceTestCount = 0
		local originalFilter = params.FilterDescendantsInstances
		local brokeFromSolidObject = false
		while true do
			-- So now what I need to do is redo this entire cast, just with the new filter list
							
			-- Catch case: Is it terrain?
			if resultOfCast.Instance:IsA("Terrain") then
				if material == Enum.Material.Water then
					-- Special case: Pierced on water?
					cast:Terminate()
					error("Do not add Water as a piercable material. If you need to pierce water, set cast.RayInfo.Parameters.IgnoreWater = true instead", 0)
				end
				warn("WARNING: The pierce callback for this cast returned TRUE on Terrain! This can cause severely adverse effects.")
			end
			
			if params.FilterType == Enum.RaycastFilterType.Blacklist then
				-- blacklist
				-- DO NOT DIRECTLY TABLE.INSERT ON THE PROPERTY
				local filter = params.FilterDescendantsInstances
				table.insert(filter, resultOfCast.Instance)
				table.insert(alteredParts, resultOfCast.Instance)
				params.FilterDescendantsInstances = filter
			else
				-- whitelist
				-- method implemeneted by custom table system
				-- DO NOT DIRECTLY TABLE.REMOVEOBJECT ON THE PROPERTY
				local filter = params.FilterDescendantsInstances
				table.removeObject(filter, resultOfCast.Instance)
				table.insert(alteredParts, resultOfCast.Instance)
				params.FilterDescendantsInstances = filter
			end
			
			SendRayPierced(cast, resultOfCast, segmentVelocity, cast.RayInfo.CosmeticBulletObject)
			
			-- List has been updated, so let's cast again.
			resultOfCast = targetWorldRoot:Raycast(lastPoint, rayDir, params)
			
			-- No hit? No simulation. Break.
			if resultOfCast == nil then
				break
			end
			
			if currentPierceTestCount >= MAX_PIERCE_TEST_COUNT then
				warn("WARNING: Exceeded maximum pierce test budget for a single ray segment (attempted to test the same segment " .. MAX_PIERCE_TEST_COUNT .. " times!)")
				break
			end
			currentPierceTestCount = currentPierceTestCount + 1;
			
			if cast.RayInfo.CanPierceCallback(cast, resultOfCast, segmentVelocity, cast.RayInfo.CosmeticBulletObject) == false then
				brokeFromSolidObject = true
				break
			end
		end
		
		-- Restore the filter to its default state.
		cast.RayInfo.Parameters.FilterDescendantsInstances = originalFilter
		cast.StateInfo.IsActivelySimulatingPierce = false
		
		if brokeFromSolidObject then
			-- We actually hit something while testing.
			PrintDebug("Broke because the ray hit something solid (" .. tostring(resultOfCast.Instance) .. ") while testing for a pierce. Terminating the cast.")
			SendRayHit(cast, resultOfCast, segmentVelocity, cast.RayInfo.CosmeticBulletObject)
			cast:Terminate()
			DbgVisualizeHit(CFrame.new(resultOfCast.Position), false)
			return
		end
		
		-- And exit the function here too.
	end
end

if (cast.StateInfo.DistanceCovered >= cast.RayInfo.MaxDistance) then
	-- SendRayHit(cast, nil, segmentVelocity, cast.RayInfo.CosmeticBulletObject)
	cast:Terminate()
	DbgVisualizeHit(CFrame.new(currentTarget), false)
end

end
i found this inside FastCastRedux > ActiveCast

also the mouse.Hit.Position worked fine in my other game which uses fastcast again but for some reason it does this in this one (could it be the viewmodel?)

Show me your code on the server for the receiving end of the remote you called CastingHitbox, the one you showed in your original post.

game.ReplicatedStorage.Game.Events.Fire.OnServerEvent:Connect(function(plr,direction,startposition,wepsettings,tool)

  game.ReplicatedStorage.Game.Events.Fire:FireAllClients(plr,direction,startposition,wepsettings,tool)
  ---audio
  local handle = tool:FindFirstChild("Handle")
  local fireaudio = Instance.new("Sound",handle)
  fireaudio.Volume = wepsettings.FireAudioVolume
  fireaudio.RollOffMode = wepsettings.FireAudioType
  fireaudio.RollOffMaxDistance = wepsettings.FireAudioMaxDistance
  fireaudio.SoundId = "rbxassetid://".. wepsettings.FireAudioIds[math.random(1,#wepsettings.FireAudioIds)]
  fireaudio:Play()
  game:GetService("Debris"):AddItem(fireaudio,fireaudio.TimeLength)

end)

game.ReplicatedStorage.Game.Events.Hit.OnServerEvent:Connect(function(plr,targetchar,hit,hitposition,wepsettings)
local targethum = targetchar:FindFirstChildWhichIsA(“Humanoid”)
if hit.Name == “Head” then
targethum:TakeDamage(wepsettings.Damage * wepsettings.HeadshotMultiplier)
else
targethum:TakeDamage(wepsettings.Damage)
end
print(hit.Name)
GoreMod.Gib(wepsettings.LimbDamage[hit.Name],hit,hitposition)

end)

this is inside the server which just fires all clients

the client:


local startposition = handle.Fire.WorldPosition
		if uis.KeyboardEnabled then
			local direction = (Mouse.Hit.p - weapon.Handle.Position)
			
			game.ReplicatedStorage.Game.Events.Fire:FireServer(direction,startposition,wepsettings,weapon)
			
		else
			game.ReplicatedStorage.Game.Events.Fire:FireServer(workspace.CurrentCamera.CFrame.LookVector * 1000,startposition,wepsettings,weapon)
		end

Yeah. Let me know how that goes.

i replied on 6th message if you didnt see it

Apologies. I can’t get to trying to see the issue at the moment, but try subtracting the topbar inset from the mouse position. If it gets worse, try it the other way around and add it instead.

local position = userinputservice:GetMouseLocation() - guiservice:GetGuiInset()

theres no noticable changes so far