How to approach bullet tracers? (Ex: Phantom Forces bullet tracers)

Does this look like the Bullet trails you wanted?
robloxapp-20211222-2352392.wmv (1.4 MB)
Huh I realize there’s a dot if the bullet is far, You could use a script to make a dot glow increase with time. Or with how far the player is?

3 Likes

FastCast doesn’t help with bullet tracers, I don’t really like using people’s modules/creations for my games, I like making my own systems so I can understand/learn them. But thank you for suggesting!

2 Likes

Unfortunately trails don’t work for me, the visual bullet changes position per frame/heartbeat.

Bumping this. Looking for a solution as well.

6 Likes

Bumping the topic, still looking for a solution!

2 Likes

Bumping the topic again, I haven’t gotten a solution to this, sorry if I sound impatient.

2 Likes

Have you looked at other open source/free model gun systems?

I know FE gun kit the modified version from uses trails for their bullets and also fast cast which is what I’m currently using (just the assets not the code)

1 Like

Sorry for the late reply, I searched a gun kit that has exactly the bullet tracers I need, but I can’t seem to get it work on my game, of course, I didn’t copy and paste it.

The error on the output is: attempt to perform arithmetic (sub) on Vector3 and nil
Code:

function module.create(Origin, Character, Direction, Speed)
	local CameraCFrame = workspace.CurrentCamera.CFrame
	local t0, p0, v0, av0, rot0, offset
	local Connection
	local Wind
	local BulletVisual = game.ReplicatedFirst.VisualBullet:Clone()
	local Beam = BulletVisual:WaitForChild("Beam")
	BulletRaycastParam.FilterDescendantsInstances = {BulletVisual, workspace.Projectiles, Character, workspace.Camera}
	local Lifetime = 0
	local Hits = BulletVisual.Hits
	BulletVisual.CFrame = Origin
	local StartCF = BulletVisual.CFrame
	local Direction = Origin.LookVector
	local Position = StartCF.Position
	local Attachment0 = BulletVisual.Beam.Attachment0
	local Attachment1 = BulletVisual.Beam.Attachment1
	BulletVisual.Parent = workspace.Projectiles
	local w0 = BulletVisual.CFrame.Position - Origin.Position
	local Time = os.clock()
	local t1, p1, v1 = os.clock(), CFrame.new():PointToObjectSpace(CameraCFrame.Position, w0)
	t0 = os.clock()
	av0 = Vector3.new(3, 0, 0)
	rot0 = BulletVisual and (BulletVisual.CFrame - BulletVisual.CFrame.p) or CFrame.new()
	offset = Vector3.new()	
	local function update(w2, t2, size, bloom, brightness, DT)
		local t2 = os.clock()
		local p2 = CFrame.new():PointToObjectSpace(CameraCFrame.Position, w2)
		local v2
		if t0 then
			v2 = 2 / (t2 - t1) * (p2 - p1) - (p2 - p0) / (t2 - t0) "problem"
		else
			v2 = (p2 - p1) / (t2 - t1)
			v1 = v2
		end
		t0, v0, p0 = t1, v1, p1
		t1, v1, p1 = t2, v2, p2
		local dt = t1 - t0
		local m0 = v0.Magnitude
		local m1 = v1.Magnitude
		Beam.CurveSize0 = dt / 3 * m0
		Beam.CurveSize1 = dt / 3 * m1
		Attachment0.Position = CameraCFrame * p0
		Attachment1.Position = CameraCFrame * p1
		if m0 > 1.0E-8 then
			Attachment0.Axis = CFrame.new():VectorToWorldSpace(CameraCFrame.Position, v0 / m0)
		end
		if m1 > 1.0E-8 then
			Attachment1.Axis = CFrame.new():VectorToWorldSpace(CameraCFrame.Position, v1 / m1)
		end
		local dist0 = -p0.z
		local dist1 = -p1.z
		if dist0 < 0 then
			dist0 = 0
		end
		if dist1 < 0 then
			dist1 = 0
		end
		local w0 = size + bloom * dist0
		local w1 = size + bloom * dist1
		local l = ((p1 - p0)*Vector3.new(1, 1, 0)).Magnitude
		local tr = 1 - 4 * size * size / ((w0 + w1) * (2 * l + w0 + w1)) * brightness
		Beam.Width0 = w0
		Beam.Width1 = w1
		Beam.Transparency = NumberSequence.new(tr)
	end
	Connection = RunService.RenderStepped:Connect(function(Delta)
		if BulletVisual then
			Direction *= Speed/2
			BulletVisual.Position += Direction
			update((BulletVisual.Position - Origin.Position), Time, 0.1, 0.005, 400, Delta)
		end
		local RaycastResult = workspace:Raycast(BulletVisual.Position, Direction, BulletRaycastParam)
		if RaycastResult ~= nil then
			local Inst = RaycastResult.Instance
			local RayPos = RaycastResult.Position
			local RayNormal = RaycastResult.Normal
			if Inst.Parent:FindFirstChildWhichIsA("Humanoid") then 
				BulletVisual:Destroy()
				if Connection then
					Connection:Disconnect()
					Connection = nil
				end
			else
				BulletVisual:Destroy()
				if Connection then
					Connection:Disconnect()
					Connection = nil
				end
				Hits.Value += 1 
				if Hits.Value == 1 then
					--local reflect = (Direction - (2 * Direction:Dot(RayNormal) * RayNormal))
					--local reflect = reflect((RayPos - BulletVisual.CFrame.Position), RayNormal)
					--Direction = reflect
					if BulletVisual then
						BulletVisual:Destroy()
						if Connection then
							Connection:Disconnect()
							Connection = nil
						end
					end
				end
			end
		end
		Lifetime += Delta
		if (Lifetime > 3.5) then
			BulletVisual:Destroy()
			if Connection then
				Connection:Disconnect()
				Connection = nil
			end
		end
	end)
	
	return BulletVisual
end
1 Like

Sorry but bumping the topic for the last time, I’m trying to use the code from a FE Gun kit dthecoolest suggested, the problem is above this reply.
The FE Gun Kit: LEGACY VIEWMODEL - Roblox

Looking back on it, well FE Gun kit is very confusing however they do provide a lot of interesting techniques provided you can understand them so don’t worry if you have difficulties with it.

For example the bullet tracer they use is also just a beam obtained by commenting out the bullet remove function and just copy and pasting the attachments and beam combo under particle framework into workspace for analysis

Also I noticed you tried to use in the above code and tried to apply to your own code.

Looks like a special technique was used to modify the axis in order to modify the curvature relative to the camera CFrame and how it is facing.

My attempt to understand update beam function in particle framework
        		local p2 = ptos(camcf, w2)
        		local v2
        		if t0 then
          			v2 = 2 / (t2 - t1) * (p2 - p1) - (p2 - p0) / (t2 - t0)
        		else
         			v2 = (p2 - p1) / (t2 - t1)
          			v1 = v2
       			end
        		t0, v0, p0 = t1, v1, p1
        		t1, v1, p1 = t2, v2, p2 
--t0 seems like time at 0 of projectile motion equation, similar variable naming

        		local dt = t1 - t0
        		local m0 = v0.Magnitude --Velocity magnitudes?
        		local m1 = v1.Magnitude
        		beam.CurveSize0 = dt / 3 * m0
        		beam.CurveSize1 = dt / 3 * m1
        		attach0.Position = camcf * p0 --Also relative to camera?
        		attach1.Position = camcf * p1
        		if m0 > 1.0E-8 then
--vtws = vectorToWorldSpace
--=CFrame.new().vectorToWorldSpace(someCameraCFrame)
--Axis effects curvature direction
         			attach0.Axis = vtws(camcf, v0 / m0)
        		end
        		if m1 > 1.0E-8 then
          			attach1.Axis = vtws(camcf, v1 / m1)
        		end

It’s best to just start from scratch

1 Like

Is it best to just copy and paste the assets then modify it anyways?

I would recommend using the beam texture ID as it’s a simple oval shaped texture with light around.

However for the math I would spent a lot more time in order to tidy it up and know how to modify it further.

Especially with testing the qualitative description of what your tracer needs to do with the code asepcts which is the hardest part.

For example:

Bullet faster = bullet velocity .Magnitude = more tracer = More beam size (Also dependent on framerate)

--m0 = magnitude of the bullets projectile velocity at that point in time,
--All that in just one line of code
beam.CurveSize0 = dt / 3 * m0

And for your main concern which is making sure the beam faces the camera properly, it’s to do with this line of code:

--vtws = vectorToWorldSpace
--camcf:VectorToWorldSpace(v1 / m1)
--If magnitude of the next velocity step is high then make it face the camera?
        		if m1 > 1.0E-8 then
          			attach1.Axis = vtws(camcf, v1 / m1)
        		end

Or you can just fast cast, with this bullet setup as well, just with a trail like @roby336 suggested, this is in thienbaos version with the new bullet.

This is false, even if you drag the trail it will cause the trail effect don’t just shoot down @roby336 idea without trying it first, rather try to understand why it doesn’t work.

TL;DR, There’s a loooot more you can do with beams and trails don’t just shoot down the ideas and limit yourself, try them out or see how others try them out.

17 Likes

I have an idea right now but i haven’t really try it. So basically its here:

local part = Instance.New("Part",workspace)
local a0 = Instance.New("Attachment",part)
local a1 = Instance.New("Attachment",part)
a0.Position = raycastOrigin.p
a1.Position = raycastOrigin.p

local tracer = Instance.new("Trail",part)
tracer.Attachment0 = a0
tracer.Attachment1 = a1

wait(.01)
a1.Position = raycastHit.p

It spawns a “trail” part and emits it (by changing the position). This type of bullet tracer will be simular to those of Rainbow Six: Siege though; where the tracers has no animation, just a fade in and fade out

1 Like

Did something very similar, just with a beam instead.

1 Like

I have used trails before, it works fine for bullets, this topic is solved now. Thank you to anyone that tried helping me!

1 Like

OH and also, for those who are wondering how I achieved this, I took the following modules from the FE gun kit: ProjectileHandler & ParticleFramework under the modules folder. (Make sure you get the Utilities module!)

Gun kit: LEGACY VIEWMODEL - Roblox

How I used the modules: (You don’t have to use ParticleFramework, only use the ProjectileHandler, but you will need ParticleFramework for it to work)


position and visualorigin is the Origin.

4 Likes

how i can call a function like that, because when i call projectile handler(), it results in an error

bumping this topic again, i have working bullet tracers but troubles with the origins, the beams start too far away sometimes (not always) and i want a solution for fixing this

I just put the trails in parts and add velocity to them, it’s pretty nice too

1 Like

Bumping this topic because I found another good method;

Unfortunately I cannot simulate the system where there is a dot when the camera isnt moving (yet), but I have found that finding control points on a bezier curve where the last 3 positions and the current position pass through looks pretty good; Example:

In order to make it move with the camera, you have to store positions that are relative to the camera (CurrentCamera.CFrame:PointToObjectSpace for example) and then you have to get the new position by translating it back into world space and doing your calculations with that variable. If you keep updating the old p0, p1, and p2 variables with the new object space coordinates, it should work.

I would explain the math behind getting control points, but unfortunately I did this a long time ago and I just wanted to quickly show my method. It’s mainly just algebra at the core

Here’s a Desmos graph with equations and a visualization: bezier refit | Desmos

4 Likes