Skip to main content
FastCast2 Cover

Roblox Luau GitHub release DevForum

FastCast2

Unofficial continuation of FastCast for Roblox

An improved version of FastCast with Parallel scripting, more extensions, and statically typed.
A powerful modern projectile library

FastCast2 It's a Roblox projectile library powered by VMsDispatcher designed to simulate thousands of projectiles without relying on physics replication.

Because FastCast is no longer actively maintained by EtiTheSpirit, this repository continues the project with updates and adaptations.


Benefits of using FastCast2

  • Highly customizable
  • Versatile projectile library
  • Parallel scripting support
  • Easy to use and integrate
  • Raycast and Blockcast support
  • BulkMoveTo support
  • Built-in ObjectCache
  • Flexible and extensible design
  • Improves development productivity
  • High Performance
  • Completely free

FastCast2 is an open-source project, and contributions from the community are welcome.
Read more on FastCast2 devforum


Installation guide

  1. Go to Releases and install the .rbxm file from the latest release.
  2. Open Roblox Studio and open any project.
  3. Go to File → Import Roblox Model and import the .rbxm file.
  4. After importing, FastCast2 will appear in your Workspace.
  5. Drag FastCast2 into ReplicatedStorage.
  6. Create a Part and set:
    • Size to 1, 1, 1
    • CanTouch = false
    • CanCollide = false
    • CanQuery = false
  7. Done — you’re ready to use FastCast2.

Code example

Shooting projectiles from your head

-- Services
local Rep = game:GetService("ReplicatedStorage")
local RepFirst = game:GetService("ReplicatedFirst")
local Players = game:GetService("Players")
local UIS = game:GetService("UserInputService")

-- Modules
local FastCast2 = Rep:WaitForChild("FastCast2")

-- Requires
local FastCastTypes = require(FastCast2:WaitForChild("TypeDefinitions"))
local FastCastEnums = require(FastCast2:WaitForChild("FastCastEnums"))
local FastCastM = require(FastCast2)

-- CONSTANTS
local SPEED = 500

-- Variables
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local Head = character:WaitForChild("Head")

local Mouse = player:GetMouse()

local ProjectileContainer = workspace:WaitForChild("Projectiles")
local ProjectileTemplate = Rep:WaitForChild("Projectile")

local debounce = false
local debounce_time = 0.05

-- CastParams
local CastParams = RaycastParams.new()
CastParams.FilterDescendantsInstances = {character}
CastParams.FilterType = Enum.RaycastFilterType.Exclude
CastParams.IgnoreWater = true

-- Behavior
local castBehavior: FastCastTypes = FastCastM.newBehavior()
castBehavior.MaxDistance = 1000
castBehavior.RaycastParams = CastParams
castBehavior.HighFidelityBehavior = FastCastEnums.HighFidelityBehavior.Default
castBehavior.HighFidelitySegmentSize = 1
castBehavior.Acceleration = Vector3.new(0, -workspace.Gravity/2.3, 0)
castBehavior.AutoIgnoreContainer = true
castBehavior.CosmeticBulletContainer = ProjectileContainer
castBehavior.CosmeticBulletTemplate = ProjectileTemplate
castBehavior.UserData = {} -- Initial UserData when ActiveCast created
castBehavior.FastCastEventsConfig = {
UseHit = true,
UseLengthChanged = false, -- Warning: Setting this to true will make your FPS tank when there are 100-200+ projectiles
UseCastTerminating = true,
UseCastFire = true,
UsePierced = false
}

-- Caster
local Caster = FastCastM.new()
Caster:Init(
4, -- Roblox limits at 4 :(
RepFirst,
"CastVMs",
RepFirst,
"CastVMContainer",
"CastVM",
true
)

-- Functions

local function OnCastTerminating(cast: FastCastTypes.ActiveCastCompement)
local obj = cast.RayInfo.CosmeticBulletObject
if obj then
obj:Destroy()
end
end

local function OnHit()
print("Hit!")
end

local function OnCastFire()
print("CastFire!")
end

-- Connections

Caster.CastTerminating:Connect(OnCastTerminating)
Caster.Hit:Connect(OnHit)
Caster.CastFire:Connect(OnCastFire)

UIS.InputBegan:Connect(function(Input: InputObject, gp: boolean)
if gp then return end
if debounce then return end

if Input.UserInputType == Enum.UserInputType.MouseButton1 then
debounce = true

local Origin = Head.Position
local Direction = (Mouse.Hit.Position - Origin).Unit

Caster:RaycastFire(Origin, Direction, SPEED, castBehavior)

task.wait(debounce_time)
debounce = false
end
end)

How to set up FastCastEventsModule

-- Services
local Rep = game:GetService("ReplicatedStorage")

-- Modules

local FastCast2 = Rep:WaitForChild("FastCast2")

-- Requires
local TypeDef = require(FastCast2:WaitForChild("TypeDefinitions"))

-- Module

local module: TypeDef.FastCastEvents = {}

local debounce = false
local debounce_time = 0.2

module.LengthChanged = function(cast : TypeDef.ActiveCast)
if not debounce then
debounce = true
print("OnLengthChanged Test")
task.delay(debounce_time, function()
debounce = false
end)
end
end

module.CastFire = function()
print("CastFire!")
end

module.CastTerminating = function()
print("CastTerminating!")
end

module.RayHit = function()
print("Hit!")
end

module.CanPierce = function(cast, resultOfCast : RaycastResult, segmentVelocity, CosmeticBulletObject)
local CanPierce = false
if resultOfCast.Instance:GetAttribute("CanPierce") == true then
CanPierce = true
end
print(CanPierce)
return CanPierce
end

module.Pierced = function()
print("Pierced!")
end


return module

(FastCastEventsModule can be used to optimize some FastCastEvents, like LengthChanged)

-> Get started with the FastCast2 documentation


People behind FastCast2

  • Mawin CK: Main developer, Maintainer, Graphic designer
  • Naymmmm: Help with proper docs, CI, Rojo supports, wally supports, Github pages(Moonwave)
  • EtiTheSpirit: Original developer

SPECIAL THANKS TO

  • @avibah On Discord: For helping me make VMDispatcher
  • @ace9b472eeec4f53ba9e8d91bo87c636 On Discord: For advice/ideas