I am creating a raycast weapon system that casts a projectile to where the raycast hits or stops. I am using the distance equation to find the distance between the muzzle position of the weapon and the hit position to find the total distance between these two, I am then dividing this by the total speed of the projectile which is 4000. I hoped that this would allow me to calculate the time it would take for the projectile to get to the raycasts hit point so that it could then remove the bullet. Though this is not working correctly as the bullet is shown to go through the wall. Have I done something incorrectly?
This is the part of the code where it calculates this:
At first it seemed that it would work perfectly though it didnt. The two print statements “Position” and “bulletPart.Position” should be the exact same when the bullet is deleted. Though the bullet is visually seen going slightly through the wall. And the outputs are sometimes slightly to largely different.
To add on to this, we know there are much better ways to use raycasting in weapons and have done so many times but are just curious if this method would work
I tested this out in Studio out of curiousity, but unfortunately had the same results as you. I assume it’s to do with setting the MaxForce to math.huge, I had success when I tested it with a lower MaxForce:
-- test
local bulletPart = game.Workspace.Bullet
local muzzlePos = bulletPart.CFrame.p
local Position = bulletPart.CFrame * CFrame.new(0, 0, -200)
game.Workspace.Wall.CFrame = Position
Position = Position.p
local bv = bulletPart.BodyVelocity
bv.MaxForce = Vector3.new(1, 1, 1) * 1000
bulletPart.Anchored = false
wait()
local begin = time()
bv.Velocity = bulletPart.CFrame.lookVector * 400
bulletPart.Touched:connect(function ()
print(time() - begin, "time taken (s)")
end)
local v = bv.Velocity.magnitude
local t = (muzzlePos - Position).magnitude / v
delay(t, function ()
print("Deleted at time", t, "(s)")
bulletPart.Anchored = true
end)
Although, I am wondering why you’re using velocity as well as raycasting? It makes more sense for you to increment the bullet’s position using CFrame whilst raycasting incrementally.
local PROJECTILE_SPEED = 3 -- how fast projectile moves
local RAY_DISTANCE = 500 -- max distance it can travel
local PROJECTILE_DROP = 0 -- whether the bullet drops or not, needs to be negative number if you want it to drop
local fireBullet = (function (A, B, projectile, ignore_model, ignore_func)
ignore_func = ignore_func or (function () return false end)
if not projectile then
return
end
local shot_dir = B.lookVector * RAY_DISTANCE
local shot_ray = Ray.new(B.p, shot_dir)
local _, true_shot = game.Workspace:FindPartOnRay(shot_ray, ignore_model)
local drop = CFrame.Angles((math.random() * PROJECTILE_DROP) * 0.01, 0, 0)
projectile.Anchored = true
projectile.CFrame = CFrame.new(A.p, true_shot)
projectile.Parent = game.Workspace
local Dist, Hit, Pos, endPos, Surface = 0
repeat
local start = projectile.Position
end_pos = ((projectile.Position + (projectile.CFrame * drop).lookVector * PROJECTILE_SPEED) - projectile.Position).unit
local dir_ray = Ray.new(
start,
end_pos.unit * PROJECTILE_SPEED
)
Hit, Pos, Surface = game.Workspace:FindPartOnRay(dir_ray, ignore_model)
projectile.CFrame = CFrame.new(Pos, Pos + dir_ray.Direction)
Dist = Dist + PROJECTILE_SPEED
wait()
until (Hit and not ignore_func(Hit)) or Dist > RAY_DISTANCE
return {
distance = Dist;
hit = Hit;
hit_pos = Pos;
hit_surface = Surface;
projectile = projectile;
}
end)
With example usage:
-- example usage:
local ignore_these_hits = (function (part)
-- don't ignore anything unless it's called "ignore_me"
if part.Name == "ignore_me" then
return true
end
return false
end)
local hit_data = fireBullet(
CFrame.new(0, 5, 0), -- Start position of bullet (must be CFrame)
game.Workspace.CurrentCamera.CFrame, -- Player's camera position (must be CFrame)
game.Workspace.Bullet, -- Pass any bullet part
game.Worspace.Character, -- Pass a model you want it to ignore, e.g. the user's character that is shooting
ignore_these_hits -- Function for the raycasting to ignore any objects defined in the function as it shoots
)
if hit_data then
print("Bullet travelled:", hit_data.distance)
if hit_data.hit then
print("Bullet hit:", hit_data.hit, "at position:", hit_data.hit_pos, "on surface:", hit_data.hit_surface)
else
print("Bullet did not hit anything, landed at location:", hit_data.projectile.CFrame)
end
-- remove bullet
hit_data.projectile:Destroy()
end