An improved version of FastCast
with Parallel Luau scripting, static typing, more extensions, built-in object pooling
FastCast2 It's a projectiles library powered by VMsDispatcher meant to simulate projectiles without any physic replication
What the benefits of using FastCast2 :
- More customizable
- Able to communicate between the main thread and different threads, with more control over the thread (costs performance)
- Parallel scripting
- Easy to use
- Raycast, Blockcast support
- BulkMoveTo support
- Built-in ObjectCache
- Flexible
Follow on FastCast2 devforum
Â
Note
- I still have not finished making the API Usage, README.md 100% yet
- Go to the toolbox
- Inside the toolbox, model tab. Search for "FastCast2"
- You should see FastCast2 and then click it
- Make sure it's owned by "Mawin_CK"
- Insert into the studio
- If you're seeing this. Click "OK"
- Now you will see "FastCast2" inside the workspace. Drag it into ReplicatedStorage
- Make sure inside the FastCast2. The "ClientVM" and "ServerVM" path is correct
- Insert a part into the workspace and then rename it to "Projectile" and set its size to 1,1,1, and make sure "CanCollide", "CanQuery", "CanTouch" are all unmarked. And drag it into ReplicatedStorage
(If you dont found FastCast2 in the toolbox, click this link: https://create.roblox.com/store/asset/87459814880446/FastCast2)
- To test if FastCast2 actually works. Insert a "LocalScript" Inside "StarterCharacterScripts" and paste this code :
--[[
- Author : Mawin_CK
- Date : 2025
]]
-- Services
local Rep = game:GetService("ReplicatedStorage")
local RepFirst = game:GetService("ReplicatedFirst")
local UIS = game:GetService("UserInputService")
local Players = game:GetService("Players")
-- Modules
local FastCast2ModuleScript = Rep:WaitForChild("FastCast2")
-- Requires
local FastCast2 = require(FastCast2ModuleScript)
local FastCastEnums = require(FastCast2ModuleScript:WaitForChild("FastCastEnums"))
local FastCastTypes = require(FastCast2ModuleScript:WaitForChild("TypeDefinitions"))
-- Variables
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local Head = character:WaitForChild("Head")
local Mouse = player:GetMouse()
local ProjectileTemplate = Rep:WaitForChild("Projectile")
local ProjectileContainer = workspace:FindFirstChild("Projectiles")
if not ProjectileContainer then
ProjectileContainer = Instance.new("Folder")
ProjectileContainer.Name = "Projectiles"
ProjectileContainer.Parent = workspace
end
local debounce = false
-- CONSTANTS
local DEBOUNCE_TIME = 0.1
local SPEED = 75
-- CastParams
local CastParams = RaycastParams.new()
CastParams.FilterDescendantsInstances = {character}
CastParams.IgnoreWater = true
CastParams.FilterType = Enum.RaycastFilterType.Exclude
-- Behavior
local Behavior = FastCast2.newBehavior()
Behavior.RaycastParams = CastParams
Behavior.MaxDistance = 1000 -- Explicitly set the max distance
Behavior.HighFidelityBehavior = FastCastEnums.HighFidelityBehavior.Default
Behavior.Acceleration = Vector3.new(0, -workspace.Gravity, 0)
Behavior.CosmeticBulletTemplate = ProjectileTemplate
Behavior.CosmeticBulletContainer = ProjectileContainer
Behavior.AutoIgnoreContainer = true
Behavior.UseLengthChanged = false
-- Caster
local Caster = FastCast2.new()
Caster:Init(
4, -- Due to roblox limits :P
RepFirst, -- Where cloned FastCastVMs will be parented to
"CastVMs", -- New name of cloned FastCastVMs
RepFirst, -- VMs Container
"CastVMsContainer", -- Name of VMs Container
"CastVM", -- Name of VMs
true -- useBulkMoveTo
)
-- Event functions
local function OnRayHit(cast : FastCastTypes.ActiveCast)
print("Hit")
FastCast2:SafeCall(cast.Terminate)
end
local function OnCastTerminating(cast : FastCastTypes.ActiveCast)
local obj = cast.RayInfo.CosmeticBulletObject
if obj then
obj:Destroy()
end
end
-- Listeners
Caster.RayHit:Connect(OnRayHit)
Caster.CastTerminating:Connect(OnCastTerminating)
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
local Origin = Head.Position
local Direction = (Mouse.Hit.Position - Origin).Unit
Caster:RaycastFire(Origin, Direction, SPEED, Behavior)
debounce = true
task.wait(DEBOUNCE_TIME)
debounce = false
end
end)- Or you can get FastCast2 testing ground from : https://github.com/weenachuangkud/FastCast2/releases
FastCast.new()Construct a new Caster instance
FastCast:Init(
numWorkers : number,
newParent : Folder,
newName : string,
ContainerParent : Folder,
VMContainerName : string,
VMname : string,
useBulkMoveTo : boolean,
useObjectCache : boolean,
Template : BasePart | Model,
CacheSize : number,
CacheHolder : Instance
)Initialize Caster. Allocate the worker amount of numWorkers, rename it to VMname, clone FastCastVMs to newParent, rename it to newName , and then create a VMsContainer which is a container of workers, set its parent to ContainerParent, and rename it to VMContainerName
- useBulkMoveTo: if true, will enable BulkMoveTo to handle CFrame changes for every
ActiveCast.RayInfo.CosmeticBulletObject. Can be disabled and enabled byCaster:BindBulkMoveTo(boolean) - useObjectCache: if true, will permanently use ObjectCache for Caster
FastCast:SafeCall(f : (...any) -> (...any), ...)Call the passed-in function if it exists
FastCast:BindBulkMoveTo(bool : boolean)Enable or disable BulkMoveTo for Caster
FastCast:ReturnObject(obj : Instance)Return passed-in obj to ObjectCache
FastCast:Destroy()Destroy Caster
FastCast:RaycastFire(origin: Vector3, direction: Vector3, velocity: Vector3 | number, BehaviorData: TypeDef.FastCastBehavior?)Create a new ActiveCast; it will not work if the Caster has not initialized
FastCast:BlockcastFire(origin : Vector3, Size : Vector3, direction : Vector3, velocity : Vector3 | number, BehaviorData: TypeDef.FastCastBehavior?)Create a new ActiveBlockCast; it will not work if the Caster has not initialized
Caster.RayHit(ActiveCast, RaycastResult, segmentVelocity : Vector3, cosmeticBulletObject : Instance?)Fires every RayHit
Caster.RayPierceFunction(ActiveCast, RaycastResult, segmentVelocity : Vector3, cosmeticBulletObject : Instance?)Fires every RayPierceFunction
Caster.LengthChanged(ActiveCast,lastPoint : Vector3, rayDir : Vector3, rayDisplacement : number, segmentVelocity : Vector3, cosmeticBulletObject : Instance?)Fires every LengthChanged
Caster.CastTerminating(ActiveCast)Fires every CastTerminating
Caster.CastFire(ActiveCast, Origin : Vector3, Direction : Vector3, Velocity : Vector3, behavior : FastCastBehavior)Fires if ActiveCast is created successfully before the RunService
- @avibah On Discord: For helping me make VMDispatcher
- @ace9b472eeec4f53ba9e8d91bo87c636 On Discord: For advice/ideas
