Help with some math

so i made a gun that tweens its bullets to the set direction. I make a ray and then get the information i need, and then i make a part and tween it to where i want it to. When the tween completes, i process what the ray hit wether if its a humanoid or not, and then do what it needs to do.

Seems simple, i just make it tween 0.1 seconds, but that would change the velocity of the bullets. For example, when i shoot it at something close like a wall, the bullet can reach the wall in 0.1 seconds. And when i shoot it at the sky, it also takes 0.1 seconds to reach its destination.

What i want to achieve is the bullet to tween to its destination with the same velocity every time, regardless of its distance. I want the time of the tween to vary between how far the bullets destination is, to make my guns a tad bit realistic.

Heres what i made so far (Local Script):

--determining source and direction
		local source = handle.BulletSpawn.WorldPosition
		local predirection = mouse.Hit.p
			
		local distance = (source - predirection).magnitude
		local xac = math.random(-5,5)
		local yac = math.random(-3,5)
		local zac = math.random(-2,5)
		local offset = Vector3.new(
			xac,
			yac,
			zac
		) * distance / stats.Accuracy -- the more the accurate
			
		local direction = predirection + offset
		local bulletspeed = stats.BulletSpeed
		
		--creating ray and display bullets
		local ignorelist = {}
		for i,v in pairs(workspace:GetDescendants()) do
			if v:IsA("BasePart") and (v.Transparency == 1 or v.Name == "Bullet" or v.Parent:IsA("Accessory") or (v.Parent:FindFirstChild("Humanoid") and v.Name == "HumanoidRootPart" and v.Parent.Humanoid.Health <= 0) or v.Parent.Name == "WeaponGiver" or v.CanCollide == false) and not v.Parent:FindFirstChild("Humanoid") then
				table.insert(ignorelist, v)
			end
		end
		
		local ray = Ray.new(source, (direction - source).unit * 500)
		local hit, pos = workspace:FindPartOnRayWithIgnoreList(ray, ignorelist, false, true)
		
		spawn(function()
			local part = Instance.new("Part")
			part.Name = "Bullet"
			part.CanCollide = false
			part.Anchored = true
			part.Massless = true
			part.Transparency = 1
			
			
			local at0 = Instance.new("Attachment")
			at0.Position = Vector3.new(0,0.15,0)
			at0.Parent = part
			local at1 = Instance.new("Attachment")
			at1.Position = Vector3.new(0,-0.15,0)
			at1.Parent = part
			
			local trail = handle.BulletTrail:Clone()
			trail.Attachment0 = at0
			trail.Attachment1 = at1
			trail.Parent = part
			
			part.Parent = workspace
			part.Position = handle.BulletSpawn.WorldPosition
			local bultween = ts:Create(part, TweenInfo.new(0.1, Enum.EasingStyle.Linear), {CFrame = CFrame.new(pos)})
			bultween:Play()
			
			bultween.Completed:Connect(function()
				if hit and hit.Parent:FindFirstChild("Humanoid") then
					if hit.Parent.Humanoid.Health <= 0 then return end
					local dmg = stats.Damage
					if hit.Name == "Head" then
						dmg = dmg * stats.Headshot
					end
					game.ReplicatedStorage.Remotes.WeaponRemotes.DamagePlayer:FireServer(dmg, hit.Parent, nil, stats.Lines1, stats.Lines2)
				end
				part:Destroy()
			end)
		end)

no errors btw, its just weird to see bullets flying so fast. I dont think ive reached this far in learning math to do something like this ;-; Any help would be appreciated

A tweens speed is proportional to the goal it has set.

Consider adjusting the range. Get the .unit of your direction multiplies by a number for range =)

1 Like

You can use the physics formula time = distance / velocity to calculate the time your tween will take. All you need to do is plug in the distance (pos - part.Position).Magnitude and your desired velocity e.g. 500 studs per second and you will get the desired result.

I have tried this, but it acts differently when i aim for the sky
https://gyazo.com/4539b1119b4f6748f34a0d165da954d7
heres what i did:

--determining source and direction
		local source = handle.BulletSpawn.WorldPosition
		local predirection = mouse.Hit.p
			
		local distance = (source - predirection).magnitude
		local xac = math.random(-5,5)
		local yac = math.random(-3,5)
		local zac = math.random(-2,5)
		local offset = Vector3.new(
			xac,
			yac,
			zac
		) * distance / stats.Accuracy -- the more the accurate
			
		local direction = predirection + offset
		local bulletspeed = stats.BulletSpeed --returns 1000
		distance = (source - direction).magnitude
	
		local secspeed = distance / (bulletspeed)
		
		--creating ray and displae
		local ignorelist = {}
		for i,v in pairs(workspace:GetDescendants()) do
			if v:IsA("BasePart") and (v.Transparency == 1 or v.Name == "Bullet" or v.Parent:IsA("Accessory") or (v.Parent:FindFirstChild("Humanoid") and v.Name == "HumanoidRootPart" and v.Parent.Humanoid.Health <= 0) or v.Parent.Name == "WeaponGiver" or v.CanCollide == false) and not v.Parent:FindFirstChild("Humanoid") then
				table.insert(ignorelist, v)
			end
		end
		
		local ray = Ray.new(source, (direction - source).unit * 500)
		local hit, pos = workspace:FindPartOnRayWithIgnoreList(ray, ignorelist, false, true)
		
		spawn(function()
			local part = Instance.new("Part")
			part.Name = "Bullet"
			part.CanCollide = false
			part.Anchored = true
			part.Massless = true
			part.Transparency = 1
			
			
			local at0 = Instance.new("Attachment")
			at0.Position = Vector3.new(0,0.15,0)
			at0.Parent = part
			local at1 = Instance.new("Attachment")
			at1.Position = Vector3.new(0,-0.15,0)
			at1.Parent = part
			
			local trail = handle.BulletTrail:Clone()
			trail.Attachment0 = at0
			trail.Attachment1 = at1
			trail.Parent = part
			
			part.Parent = workspace
			part.Position = handle.BulletSpawn.WorldPosition
			local bultween = ts:Create(part, TweenInfo.new(secspeed, Enum.EasingStyle.Linear), {CFrame = CFrame.new(pos)})
			bultween:Play()
			
			bultween.Completed:Connect(function()
				if hit and hit.Parent:FindFirstChild("Humanoid") then
					if hit.Parent.Humanoid.Health <= 0 then return end
					local dmg = stats.Damage
					if hit.Name == "Head" then
						dmg = dmg * stats.Headshot
					end
					game.ReplicatedStorage.Remotes.WeaponRemotes.DamagePlayer:FireServer(dmg, hit.Parent, nil, stats.Lines1, stats.Lines2)
				end
				part:Destroy()
			end)
		end)

Tweens are proportional to their goal, if you want a constant speed just do range/duration = velocity

Consider manually changing the CFrame instead of using tweenservice!

You need to calculate the speed using the pos variable instead of the mouse position. This is because the max distance of mouse.Hit and a Ray with length 500 are different, so you end up using the time to reach mouse max distance (which is 1000+) for a distance which is actually 500 studs.

I recommend using a tick timer. E.g. the time it should take the bullet to reach its goals is distance/speed, add that time onto tick() and repeat lerping the bullet until tick() == your maxtick. use lerp which is relative to 0 - 1 e.g. when tick() is 75% of the way done, the percentage of the lerp should be 0.75. You can get this with (current tick - starting tick)/ (your added tick - starting tick) * 1. This will make the bullet always lerp at a consistent speed irrelevant to cast distance.

I see. It works fine now! Thank you :slightly_smiling_face:

1 Like