Hi, I’m looking to find out how to shoot projectiles in the middle of a GUI like a gun sight. I have searched a way on the forum without success. My current script allows me to shoot in the middle but depending on the zoom or unzoom of the screen then it may not be really accurate. Thanks for your help
You can use ViewportSize to get the size of the viewport, and then use that to calculate the center of the viewport.
local viewportSize = game.Workspace.CurrentCamera.ViewportSize
local center = viewportSize / 2
You can use that to calculate the direction of the raycast, and then use that to calculate the position of the projectile.
local ray = Ray.new(game.Workspace.CurrentCamera.CFrame.p, game.Workspace.CurrentCamera.CFrame.lookVector)
local hit, position = game.Workspace:FindPartOnRayWithIgnoreList(ray, {game.Workspace.CurrentCamera})
local projectile = Instance.new("Part")
projectile.Anchored = true
projectile.CFrame = CFrame.new(position)
projectile.Velocity = game.Workspace.CurrentCamera.CFrame.lookVector * 50
projectile.Parent = game.Workspace
If you want to make it so that the projectile is fired from the center of the screen, you can use the ScreenPointToRay method of Camera to get the ray from the center of the screen.
local ray = game.Workspace.CurrentCamera:ScreenPointToRay(center.X, center.Y)
I tested your script but it doesn’t really fit what I need. In fact I would like the projectile to come out directly from the “weapon” position and to have a trajectory towards the Gui. You can see on the video below that depending on how I zoom the screen, the projectile will go more or less in the center. I would like to know if there is a way to detect the center of the Gui (in a 3d version) and that the projectile goes in its direction.
Thanks again for your help and here is the video :
If ever someone go here i have find the good. solution.
function LancePierre(actionName, inputState, inputObject)
if dbPierre == false and canshot then
dbPierre = true
local pierre = rs.Vehicule.LancePierre.Pierre:Clone()
pierre.Position = plr.Character.RightHand.CFrame * Vector3.new(0,-0.1,-2)
pierre.Anchored = true
local TweenArme = ts:Create(pierre, TweenInfoArme, {
CFrame = plr.Character.Head.CFrame + camera.CFrame.LookVector * 20 + Vector3.new(0,5,0)})
TweenArme:Play()
pierre.Parent = workspace.Route.Players[plr.Name].Balles
task.wait(0.1)
pierre.Anchored = false
pierre.VectorForce.Force = camera.CFrame.lookVector * 2500 + Vector3.new(0,850,0)
task.wait(0.3)
dbPierre = false
spawn(LancePierre)
task.wait(0.4)
if pierre:FindFirstChild('VectorForce') then
pierre.VectorForce.Enabled = false
end
task.wait(0.6)
pierre:Destroy()
end
end
The tweenService will center the projectile directly in front of the player according to the camera lookvector, so that the trajectory of the ball can be perfectly straight and reach the middle of the Gui (it still depending of the camera zoom/dezoom but way better than before). You will have to modify some values according to the position of your Gui and the position of the starting point of the projectile. Here ‘Pierre’ is the projectile
To shoot projectiles accurately in the middle of a GUI, you need to take into account the position of the GUI and the position of the crosshair on the screen.
Here’s an example script that you can modify to fit your needs:
-- Get the player's camera
local camera = game.Workspace.CurrentCamera
-- Create a Part to represent the crosshair
local crosshair = Instance.new("Part")
crosshair.Name = "Crosshair"
crosshair.Shape = Enum.PartType.Ball
crosshair.Size = Vector3.new(0.2, 0.2, 0.2)
crosshair.Color = Color3.new(1, 0, 0)
crosshair.Anchored = true
crosshair.CanCollide = false
crosshair.Transparency = 0.5
crosshair.Parent = game.Workspace
-- Create a function to update the crosshair position
local function updateCrosshairPosition()
-- Get the position of the GUI element
local guiPosition = UDim2.new(0.5, 0, 0.5, 0)
-- Calculate the position of the crosshair on the screen
local viewportSize = camera.ViewportSize
local crosshairPosition = Vector2.new(viewportSize.X * guiPosition.X.Scale + guiPosition.X.Offset,
viewportSize.Y * guiPosition.Y.Scale + guiPosition.Y.Offset)
-- Convert the screen position to a 3D world position
local ray = camera:ViewportPointToRay(crosshairPosition.X, crosshairPosition.Y, 0)
local _, hitPos = game.Workspace:FindPartOnRay(ray, game.Workspace, false, true)
-- Update the position of the crosshair
crosshair.Position = hitPos
end
-- Connect the function to update the crosshair position when the camera changes
camera:GetPropertyChangedSignal("ViewportSize"):Connect(updateCrosshairPosition)
-- Call the function to initially position the crosshair
updateCrosshairPosition()
-- Create a function to fire the projectile
local function fireProjectile()
local projectile = game.ReplicatedStorage.Projectile:Clone()
projectile.Position = plr.Character.RightHand.CFrame * Vector3.new(0,-0.3,-2)
projectile.VectorForce.Force = (crosshair.Position - projectile.Position).Unit * 2500
projectile.Parent = workspace.Route.Players[plr.Name].Balles
end
-- Bind the function to a mouse click event
game.Players.LocalPlayer:GetMouse().Button1Down:Connect(fireProjectile)
This script creates a Part to represent the crosshair and positions it based on the position of a GUI element in the center of the screen. It then calculates the position of the crosshair on the screen and converts it to a 3D world position using a ray cast. The script then fires a projectile towards the position of the crosshair when the player clicks the left mouse button.
You can modify the script to fit your specific needs by changing the position of the GUI element and adjusting the firing logic to match your projectile.