I Cannot throw this Object

Hello Everyone!,

So, I want to make a Throwable Tool Object (Ball or other item), So i tried to script myself and it went horribly wrong and at this point i even forgot what was i Typing,

So, I want a Tool That goes where the Player’s mouse is pointed at and it should go smooth.
I want to achieve a smooth, at constant speed Object that reaches its target!

At this point i have only tried Assembly Linear Velocity, Velocity (which is DEPRECATED) , body Velocity (Which is also DEPRECATED ( it did work but it was not smooth ), Tween Service (to make the ball go in smooth direction but it did not work) and normal CFrame positions which all failed because they either did not work or i might have not have implemented correctly. The ball might not be smooth because it is a script and running by the server but still i want other player to see too.

I have written this script:

(Script)

local LevelIncreaseRemote = game.ReplicatedStorage.LevelIncrease
local Tool = script.Parent
local Ball = Tool.Handle
local MouseLoc = Tool:WaitForChild("MouseLoc",10)
local PlayerCommunicate = game.ReplicatedStorage.HitBall
local db = false

-- Velocity power
local VelocityPower = 150

function FiretheBall(direction)
	db = true

	local vCharacter = Tool.Parent
	local vPlayer = game.Players:GetPlayerFromCharacter(vCharacter)

	local ball = Tool:FindFirstChild("Handle"):Clone()       

	local spawnPos = vCharacter.PrimaryPart.Position
	

	spawnPos  = spawnPos + (direction * 5)
	
	-- Animation
	local Throwanimation = vPlayer.Character:FindFirstChild("Humanoid"):LoadAnimation(script.Throw)
	Throwanimation:Play()
	task.wait(0.8)

	-- Throwing
	ball.Position = spawnPos
	ball.AssemblyLinearVelocity = direction * VelocityPower
	ball.Locked = true
	ball.Name = "ThrownSnowball"
	ball.Transparency = 0
	ball.CanCollide = true
	ball.Parent = workspace

	-- Trails
	local Attachment0 = Instance.new("Attachment", ball); Attachment0.Position = Vector3.new(-0.5,0,0); Attachment0.Orientation = Vector3.new(0,180,0)    
	local Attachment1 = Instance.new("Attachment", ball); Attachment1.Position = Vector3.new(0.5,0,0); Attachment1.Orientation = Vector3.new(0,0,0)    
	local Trail = Instance.new("Trail", ball); Trail.Attachment0 = Attachment0; Trail.Attachment1 = Attachment1

	
	
	--damage function--
	ball.Touched:Connect(function(hit)
		ball.CanCollide = false
		
		local human = hit:FindFirstChild("Humanoid") or hit.Parent:FindFirstChild("Humanoid")
		
    	if human and hit.Parent.Name ~= Tool.Parent.Name then
			human.Health = 0
			task.wait(1)
			human.Health = 100
			-- Give Rewards to the Plyaer who threw
			LevelIncreaseRemote:Fire(vPlayer)
			local HitPlayer = game.Players:GetPlayerFromCharacter(hit.Parent)
			-- Will Change the Player's Team 
			PlayerCommunicate:FireClient(HitPlayer, "Hunters")
			ball:Destroy()
		else
			ball:Destroy()
		end
		
		if wait(5) and Tool.Parent ~= vPlayer.Backpack then
			db = false
			Ball.Transparency = 0
		end
		
	end)
end

Tool.Enabled = true


function onActivated()
	Tool.Enabled = false
	local character = Tool.Parent
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	Ball.Transparency = 1
	-- The Mouse event is giving the Directions
	local targetPos = MouseLoc:InvokeClient(game:GetService("Players"):GetPlayerFromCharacter(character))
	local lookAt = (targetPos - character.Head.Position).unit
	FiretheBall(lookAt)
	wait(2)
	Tool.Enabled = true
end


Tool.Activated:Connect(onActivated)

Local script

--Connect to Remote Function
local Tool = script.Parent

local MouseLoc = Tool:WaitForChild("MouseLoc")

function MouseLoc.OnClientInvoke()
	return game:GetService("Players").LocalPlayer:GetMouse().Hit.p
end
2 Likes

Here is a good resource about creating throwable objects with proper motion:

Also as a sidenote I recommend not using RemoteFunctions OnClientInvoke. This can be abused to never trigger causing some shaky behaviors. I much more recommend on the localscript make Tool.Activated that uses RemoteEvent to fire the mouse hit position and activates the throwing. Much safer :smiley:

2 Likes

Hi!,

So i tried to comprehend what the document was saying and i even tried to implement it but i do not think it worked out because of the complexity. Also it is for Advance version of Projectile Engine, i do want a simple Projectile Engine just like the game “Sno day” if you might have played it!

Understandable :smiley:. I can give a simple code example once I get home. Would you be able to update the scripts showing what you have so far so I can start from there?

1 Like

Yeah so this is the script i have made:
it also do contains the script that the document has told

local Time = 1
local HumanRootPart
local Ball = script.Parent:WaitForChild("Handle")
local Tool  = script.Parent
local mouse
local Remote = script.Parent.RemoteEvent

Remote.OnServerEvent:Connect(function(player, GetMouse)
	HumanRootPart = player.Character:WaitForChild("HumanoidRootPart")
	mouse = GetMouse
end)


local function OnActivated()
	local Gravity = Vector3.new(0, -game.Workspace.Gravity, 0)
	local X0 = HumanRootPart.CFrame * Vector3.new(0, 2, -2)

	-- calculate the Velocity needed to reach the Target
	local Velocity0 = (mouse.Hit.p - X0 - 0.5*Gravity*Time*Time)/Time
	print(Velocity0)
	print((0.5*Gravity*Time*Time)/Time)

	-- Throwing the Ball
	local BallClone = Ball:Clone()
	BallClone.Velocity = Velocity0
	BallClone.CFrame = CFrame.new(X0)
	BallClone.CanCollide = true
	BallClone.Parent = game.Workspace
	
	-- I will add the rest of the script later
end


Tool.Activated:Connect(OnActivated)

the local script will just give the player and player:Getmouse() from the remote event

Alrighty, I actually just finished creating the code example just before you sent this :smiley: . Your code is very close, but the only change you’d need to do is to call OnActivated after mouse = GetMouse and remove the Tool.Activated from the server script. That and mouse.Hit.p needs to be changed to just mouse.

Here is the example setup I made but feel free to modify it to your needs:
kuva

-- SnowballServer
local Tool = script.Parent

local ThrowRemote = Tool.Throw
local Handle = Tool.Handle

local ThrowTime = 1

ThrowRemote.OnServerEvent:Connect(function(TargetPlayer: Player, Target: Vector3)
	local Character: Model | Instance = Tool.Parent
	local Player = game.Players:GetPlayerFromCharacter(Character)
	-- Exploiter could make someone else throw balls so we make sure its the correct player
	if Player and Player == TargetPlayer and Character:IsA("Model") and Character.PrimaryPart then
		local RootPart = Character.PrimaryPart
		local GravityVector = Vector3.new(0,-game.Workspace.Gravity,0)
		
		local StartPos = Handle.Position
		local Velocity = (Target - StartPos - 0.5 * GravityVector * ThrowTime * ThrowTime) / ThrowTime
		
		local NewBall = Handle:Clone()
		NewBall:ClearAllChildren()
		NewBall.AssemblyLinearVelocity = Velocity
		NewBall.CanTouch = true
		
		NewBall.Touched:Connect(function(Part: BasePart)
			if Part:IsDescendantOf(Character) then
				return
			end
			-- Do something, Damage?
			NewBall:Destroy()
		end)
		
		NewBall.Parent = workspace
		NewBall:SetNetworkOwner(Player)
	end
end)
-- Localscript

local Player = game.Players.LocalPlayer
local Mouse = Player:GetMouse()

local Tool = script.Parent

local ThrowRemote = Tool.Throw

Tool.Activated:Connect(function()
	ThrowRemote:FireServer(Mouse.Hit.Position)
end)

Hope this simple example helps. If you got any more questions, feel free to ask! :smiley:

2 Likes

Thanks For Your Assistance!,

I do have a problem, How could i set the range or the speed of the ball, and Sometimes the touches event delays as even if the ball does not touch the Surface it is still going to destroy the ball without ever reaching the surface to touch, Now i think this might happen because there is a delay between the server and the client and when the ball touches the surface it delays in the client, And also because of this problem as the ball is in workspace, This makes the movement unsmooth which makes it jitter, I do read a document where they have said that you need to change the Ball movement’s to only visible to client and if other players also want to see it then we need to use the FireallClient method? But i still do not know what this might cause to do and how to implement it?

Also either can i use Tween service to smooth out the motion?

To achieve a smooth, constant speed object that reaches its target, you can use the BodyPosition class. Although it is deprecated, it can still be used for this purpose.

-- Create a part to act as the throwable object
local throwable = Instance.new("Part")
throwable.Size = Vector3.new(1, 1, 1)
throwable.BrickColor = BrickColor.new("Bright blue")
throwable.Parent = workspace

-- Create a BodyPosition object and parent it to the throwable part
local bodyPosition = Instance.new("BodyPosition")
bodyPosition.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
bodyPosition.Parent = throwable

-- Function to throw the object
local function throwObject(mouse)
    -- Calculate the direction from the player's mouse position
    local direction = (mouse.Hit.p - throwable.Position).unit
    
    -- Set the target position for the BodyPosition object
    bodyPosition.Position = throwable.Position + direction * 50 -- Adjust the distance as needed
    
    -- Enable the BodyPosition object to start moving the throwable part
    bodyPosition:Apply()
end

-- Connect the throwObject function to the MouseButton1Click event of the player's mouse
game.Players.LocalPlayer:GetMouse().MouseButton1Click:Connect(throwObject)

We create a part called “throwable” and a BodyPosition object called “bodyPosition”. When the player clicks the left mouse button, the throwObject function is called. It calculates the direction from the player’s mouse position to the throwable part, sets the target position for the BodyPosition object, and enables it to start moving the throwable part towards the target position.

Note that this implementation is server-sided, so other players will also see the throwable object move smoothly.

2 Likes

I believe this is caused by the networkOwner changing or being something other then the client who threw it. Have you tried to setting it just like in the example code I gave you?

NewBall:SetNetworkOwner(Player)

As for speed, you could calculate the distance from your character to the target and divide it by a “throw speed” to calculate how many seconds it should travel. You can then assign this value to Time in your code. Example:

local ThrowSpeed = 30
local Time = (mouse - X0).Magnitude / ThrowSpeed
-- Math below

Same for range, you can just deem that the distance is too far away and not throw the ball. Hope this helps! :smiley:

1 Like

Hey, Can i use Align Positon rather than BodyPosition because in the roblox Documentation it is Deprecated and no longer use.

Hello!,

It works perfectly but there is one problem, So when i click only on a part, it activates and if i click in the sky or any place where a part does not exists, It will spawn the ball and second is that if i click on any part or player rather than going straight or like a normal object it goes highly up then lands on the part or the object!.

For Clicking in the sky, my best suggestion is to have the range check filter that out since this way of math we calculate the trajectory based on where it should land.

For when the ball goes too high up, I recommend lowering the time. The lower the time, the more “straight” it goes!

Hope these help! If you have any more questions, feel free to ask me :smiley:

2 Likes

Like Can you please give a example of Range Check filter?

Sure!

local Distance = (mouse - X0).Magnitude
if Distance < 100 then -- 100 means max 100 studs away you can throw. Change it to what you need
    -- Do stuff here
end
1 Like

Hello!,

So i tried and modified the script by implementing the code and it did not work out, Any other Method or way to overcome this situation?

Hello! Can you show what you got so far? And your problem was being able to throw too far away?

It is the just the same, I have added your range filter code but the problem is that if the distance is above 100 it does not work. I have also modified for the above situation but it also does not work. I think the main problem here is that the ball needs somewhere to land at, if the pointer is pointing at a place where there is nothing to land upon then it errors. Also why do we need to add extra formulas and other stuff when we can use velocity or Changing the CFrame?

Hello!

I seem to have misunderstood your original request for the throwing system :smiley:. If I’m understanding correctly (now) you wish to have a throwing system where instead of clicking on where you want the ball to land, you wish to have a throwing system where it throws to the general direction of where you are aiming. As you mentioned, this kind of system doesn’t require any fancy formulas like the one I gave you before.

Here is the updated code I used to make this:

-- ServerScript

local Tool = script.Parent
local Handle = Tool.Handle

Tool.Throw.OnServerEvent:Connect(function(TargetPlayer: Player, Direction: Vector3)
	local Character: Model | Instance = Tool.Parent
	local Player = game.Players:GetPlayerFromCharacter(Character)
	if Player and Player == TargetPlayer and Character:IsA("Model") and Character.PrimaryPart then
		
		local NewBall = Handle:Clone()
		NewBall:ClearAllChildren()
		NewBall.AssemblyLinearVelocity = Direction.Unit * 100 -- Change throw speed here
		NewBall.CanTouch = true
		
		NewBall.Touched:Connect(function(Part: BasePart)
			if Part:IsDescendantOf(Character) then
				return
			end
			-- Do something, Damage?
			NewBall:Destroy()
		end)
		
		NewBall.Parent = workspace
		NewBall:SetNetworkOwner(Player)
	end
end)
-- Localscript

local Player = game.Players.LocalPlayer
local Mouse = Player:GetMouse()

local Tool = script.Parent

local ThrowRemote = Tool.Throw

Tool.Activated:Connect(function()
	ThrowRemote:FireServer(Mouse.UnitRay.Direction)
end)

Hopefully this is more of what you are looking for :smiley:

1 Like

Thanks For the Solution!,

I know, I am annoying you at this point but there is just one small problem here, The Ball goes quite offside when pointed somewhere, Let’s say that i am pointing straight, the ball would go a little right rather than at exact Mouse Look Vector

NewBall.AssemblyLinearVelocity = (Direction.Unit + Vector3.new(-0.03,0,0) )* 300

I tried to modify a little bit by changing where the ball is directed to. It does work until i turn back, then the ball direction just goes left now,

No problem :smiley:. Regarding the shifting, it might be due to us setting the start position off the snowball to be the where the hand holds it. You can try adjusting the start position to be for example the head or humanoid root part.

Hopefully that should resolve it :smiley: Feel free to let me know if you have anything else!

1 Like