Making a combat game with ranged weapons? FastCast may be the module for you!

This is a result of you having the rendering code run somewhere where the script will be destroyed (e.g. having it inside of a Tool). It may be better to have a LocalScript in StarterPlayerScripts handle the rendering. You can easily connect the client script of the gun to the render script via BindableEvents


how practical is it to make a single caster for the whole game inside a server script? my game doesn’t have many projectiles or fast travel speeds, i’l be mainly using it without physics, i saw your stress test video and according to that a single caster CAN handle all of my needs, what drawbacks should i expect? i’m aware of different settings for different weapons, but i’l have it change the settings before firing, and a custom function that resets all settings after firing.

The render script stops working all together after the player respawns when it is in StarterPlayerScripts. How would I combat this?

It may be worth having another example script with this implementation, since I think that almost all games will require the bullets to keep moving if the shooter dies.


Hmm… There is problem with a gun script, the example one. You can hit bullet with a bullet which creates FX effect and it is annoying, and weird, this solution fixed my problem and I want to share it with everyone here.

Entire Event:

function OnRayHit(HitPart, HitPoint, Normal, Material, CosmeticBulletObject)
	-- This function will be connected to the Caster's "RayHit" event.
	CosmeticBulletObject:Destroy() -- Destroy the cosmetic bullet.
	if HitPart and HitPart.Parent then -- Test if we hit something
		if HitPart.Name ~= CosmeticBullet.Name then -- Check if bullet didn't hit bullet (it happens, so why not?)
			local Humanoid = HitPart.Parent:FindFirstChildOfClass("Humanoid") -- Is there a humanoid?
			if Humanoid then
				Humanoid:TakeDamage(10) -- Damage.
			MakeParticleFX(HitPoint, Normal) -- Particle FX

Separate part:

if HitPart.Name ~= CosmeticBullet.Name then -- Check if bullet didn't hit bullet (it happens, so why not?)


Make sure to create unique name for bullet so it doesn’t give false positives:

CosmeticBullet.Name = "BulletUniqueName" 

If you think there is possibility of false positive then just do this:

Put if HitPart.Name ~= CosmeticBullet.Name then -- Check if bullet didn't hit bullet (it happens, so why not?) before FX effect instead before Humanoid check thingy.

Oh yeah, I had forgotten to fix this. That said, your method will unfortunately not work – OnRayHit is called after the ray actually hits something and stops, so the bullet won’t continue, it’ll just not spark but will still disappear and stop simulating.

The intended method to fix this is to use the IgnoreDescendantsInstance property of Casters. Put all bullets in some model or folder within the workspace, and set the property to reference that model or folder.


Hey everyone!

I just did a complete rewrite of this module from scratch. Shoutouts to @evaera for giving me the sort of wake-up call for some mistakes I made in the module’s code.

It is now far cleaner, far more optimized, and generally better all around.

Today marks the release of FastCast V8.0.0, or better yet, FastCast: Redux V1.0.0! Let me know if you run into any issues. The example gun has been updated as well.



Any reason why you left the IgnoreWater parameter out? It defaults to false so all raycasts will detect water.

Do you have plans to support bigger hitboxes? For example, making a custom sphere or box cast for bigger hitboxes.

EDIT: Also, could you maybe put it on github, I like to just look at code before I download something.

I hadn’t thought of it. I can append that.

Have a look at the replies – I already answered that. See reply #38 and my response to it.

Again, read the thread. I already have a GitHub URL in it.

1 Like

@0_1195 I’ve just released version 8.1.0 which takes in an ignoreWater parameter. Check the API for info :smile:


You forgot the 3rd argument in the MandateType(ignoreWater, "boolean", true) function on line 161.
It results in this error bad argument #2 (string expected, got boolean)

Should probably be something like this:
MandateType(ignoreWater, "boolean", "ignoreWater", true)


That’s what I get for being tired while making that! Thanks lol. It’s patched now.

1 Like

Is there any way to add a blacklist to hats?

You would need to iterate through all of the characters in your game (and connect to every player’s CharacterAdded event to detect when they respawn) and add all of the accessories to a table. Pass this table into FireWithBlacklist.

What I do for hats is assign them to a collision group that can’t collide with anything


This is great! Makes it hella easier to create ranged weapons

Really loving it so far, and it’s quite easy if you know what you’re doing as well!
For those who doesn’t understand how to use this module, or can’t visualize how to use it, I’ll try my best to explain how I set mine up.


  1. FireScript (LocalScript, does the main shooting, no projectile handler, duh!)
  2. ProjectileHandler (LocalScript, does the client side projectile visual render)
  3. ServerHandler (Script, does the server side projectile contact)


  1. FireEvent (RemoteEvent, used to tell the server to fire)
  2. ClientProjectile (BindableEvent, used by the caster to create an instant client sided projectile visual)
  3. ReplicateProjectile (RemoteEvent, used by the server to tell other clients to create their side of projectile visuals)


  1. FireScript fires 2 things: ClientProjectile and FireEvent.
  2. ProjectileHandler listens for the ClientProjectile and runs the function VisualSetup that runs FastCast:Fire(origin, direction, velocity, bulletVisual), updating the visual position using FastCast.LengthChanged and destroying the bulletVisual with FastCast.RayHit.
  3. ServerHandler simultaneously listens for the FireEvent that runs FastCast:Fire(origin, direction, velocity), listening for the bullet hit using FastCast.RayHit. Directly after firing, the server then does ReplicateProjectile:FireAllClients(initialPlayer, …).
  4. ProjectileHandler listens for the ReplicateProjectile and runs the same function VisualSetup, but first checks if initalPlayer ~= LocalPlayer to avoid creating a second delayed visual.

In a nutshell: Client tells the server to shoot. Client also handles their own and others’ projectiles in one script, updating visual via LengthChanged. Server runs the identical fire function the client does, but handles the projectile connection via RayHit.

Remember, yours doesn’t have to be exactly like mine, this is just the general usage and will vary depending on how your gameplay framework is made.
You can find the arguments/parameters that are passed on the github link provided.


The question is… Are we going to get that penetration system :thinking:

I’ve been occupied with a lot of other stuff

I have a primary workflow set out, and the basic gist is that the user will specify a callback function that returns true or false (true for “yes it did hit”, false for “no, keep going”)

One thing I want to mandate is that this function must never yield as this disrupts the flow of the cast. I don’t quite know how to do this off the top of my head.

1 Like