In basic, this module supplies an API that allows you to use raycasting that simulates physics for bullets. I think the easiest example would be to give you a rather brief script, since my original post explains it already. In the case that this kind of explanation isn’t what you wanted, just let me know and I’ll fix it up.
If you look at reply #15 I have a picture of a ray firing off with physics. Each one of those black cones is a segment. This module basically splits up the path of a bullet into tiny segments whose length is based on the speed of the projectile and how long the latest Heartbeat took (which allows it to accommodate for lag). Each of these segments is an individual hitscan test over a short range. They are fired off sequentially based on velocity and time. One of the immediate concerns I may see is that extremely fast bullets have long rays, but the frame-rate Roblox is limited at will make it not perceivable by players, so it works pretty well even with extremely fast bullets.
Let’s say you have a sniper rifle, something with a very high-speed projectile. You’d start off with a script a little something like what follows to handle the rifle’s function.
The script is lengthy (not overkill) so I’m going to wrap it into a details section. I’ve written functions that explain what each part is doing via comments so hopefully it should clarify a lot of stuff.
I forgot to append my API to the original post, as I did do documentation for this system. Sorry about that. You can have a look at it here: https://github.com/XanTheDragon/FastCastAPIDocs/wiki
Click to view
local FastCastModule = require(wherever the module is)
local SniperCaster = FastCastModule.new()
SniperCaster.Gravity = 5 --Add a slight bullet drop at 5 studs/sec^2 (game gravity is 196.2 by default)
SniperCaster.ExtraForce = Vector3.new() --You can set this to apply wind so that you can offset the bullet
function RayChanged(Origin, SegmentStart, Direction, Length)
--As mentioned in the API, this function will fire every heartbeat, or when a new ray segment is calculated.
--Origin is the start of the ray, where the muzzle is. SegmentStart is the start of the current segment.
--Likewise, direction and length are the direction + length of the current segment.
--Each one of the black cones in the image I referred you to is a segment.
--In this function, you might update a tracer part by setting its CFrame or update anything else that may appear visually based on the bullet.
--You can also use this function for something like playing a bullet near-miss sound!
end
function OnHit(Part, Position, Normal, Material)
--This function will run when the ray hits something. The parameters returned are self-explanatory, but for the sake of good practice I'll explain anyway
--Part is the part that got hit (will be nil if the ray reaches the end of its distance.)
--Position is the position of either the hit or the point of the ray when it ends.
--Normal is the surface normal of the part hit (this will be a zero-vector if Part is nil)
--Material is the material of the part hit (this will be Enum.Material.Air if Part is nil)
--Here, you might damage the player that got hit or do anything else involving when the bullet hits something.
end
--Now that you've set up the way the caster should work, you can connect its events to the two functions above.
SniperCaster.LengthChanged:Connect(RayChanged)
SniperCaster.RayHit:Connect(OnHit)
--After the setup of the caster is done as shown above, you can use this to fire your gun:
local BulletSpeed = 1600
local MaximumDistance = 1000
function FireWeapon(MuzzleEndPosition, FireDirection)
--Some arbitrary function that will fire the gun. This might be paired to something in a Tool's Activated event.
SniperCaster:Fire(MuzzleEndPosition, FireDirection * MaximumDistance, BulletSpeed)
end