ClientCast - A Client-based, Idiosyncratic Hitbox System!

I don’t really understand your issue. Are you saying that the debug rays are being shown even before Start is called? or are you saying you want the debug rays to show without having to call Start? Or something else completely?

1 Like

The debug rays are shown before ClientCast:Start() is called. It shows as soon as,

is being called on the server.

That’s weird - shouldn’t happen. Go into the main module and in the Settings table, set the debug value to false. If that doesn’t work, then try calling :StopDebug() right after creating the caster.

Thank you for answering. Just to elaborate what I was trying to do. I want the rays to be shown when calling ClientCast:Start(). setting debugmode to false removes the rays.

-- DebugMode is set to true in the module

-- Initialize parameters 
local ClientCaster =,

-- Server gets attack input --
AttackRemote.OnServerInvoke = function(player)

   -- connecting "touch/raycast" event of the clientcast
    ClientCaster.HumanoidCollided:Connect(function(RaycastResult, HitHumanoid)


   -- Start damage when marker is reached in the animation
       ClientCaster:Start() -- here i wish the rays would be visible
  -- Stop damage when marker is reached in the animation


Some thoughts afterwards: Can you Initialize ClientCaster inside the attackfunction or will it leak?

I realized my mistake. Turning off debug and setting ClientCast:StartDebug() manually before ClientCast:Start() solved my issue. I believe there are no ClientCast:StopDebug(), but ClientCast:Stop() will remove the debugtrails regardless. Thank you for your help.

1 Like

You know the server hitbox backtracking thing might be more plausible with the upcoming workspace:GetServerTimeNow(): Release Notes for 488

It already is. I backtrack my hitboxes by using a modified version of ClientCast & end up with accuracy within 0.1 studs.


I have an issue with disconnecting the custom ontouch event provided by the module. My debounces are disregarded by the function. Here is an example gif of me trying to create a repro. I am clicking multiple times before rotating my character. As soon as I stop clicking i move my sword onto the target. You can see that (3x) are running even with the debounces present.

My thoughts are as following:

  1. My debounce function is done incorrectly (I dont think it is)
  2. The customised event is not disconnect with ClientCaster:Stop() function
  3. I might have misunderstood the api function.

I am connecting this event whenever the player is attacking (left mouse button down). ClientCaster is only created once outside of the attack remote.

local DamageDebounce = false
	-- Connect damage when hitting a humanoid --
		if DamageDebounce == false then -- avoid damaging again 
			if RaycastResult and RaycastResult.Instance and RaycastResult.Position then
				if not RaycastResult.Instance:IsDescendantOf(char) then -- Avoid hitting yourself
					DamageDebounce = true
					print('should only print once pr attack | Event Number: ',EventNumber)

is called whenever a player is clicking. There is a cooldown to the clicks and it prints out whenever the attack is being performed.

Here is a repro file:

Repro ClientCaster.rbxl (115.6 KB)


Since I need the ontouch event in the attackremote, the best way is to create the clientcaster object on each attack and disconnecting it with clientcaster:Destroy(). This seems to have fixed the issue. I was trying to place the ClientCaster.HumanoidCollided event outside of the attackremote which I think would solve the issue, but there were too many important variables that I wanted locally for the attack function.

Great module, really helps when working with client side melee attacks.

1 Like

The issue here is that you are creating a debounce inside the OnServerInvoke function - if the remote is called 5 times, it would connect 5 different HumanoidCollided events and create 5 different debounces. You can see this by using the following debug code:

Which outputs the following:

The issue here isn’t with ClientCast but rather your code. ClientCast isn’t able to magically ignore your debounce.

1 Like

Yeah thank you for answering. Thats why I was wondering if perhaps the connection was not disconnected after the invoke. I am aware that I connect a new HumanoidCollided event on each invoke, but I thought it would be disconnected with ClientCaster:Stop(). To sum it up the debounce was intended for only that one event which i would disconnect after before remaking a new event. Just so there are no misunderstanding, do ClientCaster:Stop disconnect the HumanoidCollided event or do I need to call ClientCaster:Destroy() to do that. Anyways thank you for the amazing module

The ClientCaster::Stop method does not disconnect it for you - the reason as to why Destroy does it is because it fully cleans up everything in the object - for performance sake though, you should try using only one caster per weapon, and disconnect the events by yourself (or, connect an event outside of the remote and using variables to communicate).

1 Like

Im making a combat system with a L Hand attack and a R Hand attack. What would be the best way to set this up? Right now Im updating the Caster Variable everytime the player Left or Right Clicks.

you say " If you would like to take into account for the player’s ping, you can easily get their ping through ClientCaster:GetPing()" how exactly would you do this?

Is this module intended mainly for singleplayer games or similar designs, where exploiting isn’t a concern? I don’t see how trusting the client with handling hitboxes is a good idea.

It took me about 10 minutes to figure out how to abuse the remote event to damage any player on the map, I’m not sure if I’m using the module wrong (I used the example code provided in the github link, with the exception that i handled the hitbox to the client, obviously) or if I’m supposed to handle verifying the raycasts myself (which would beat the entire purpose of the module and i’d be better off doing hitboxes server side).

Please read the whole thread.

Let’s take a simple case scenario: your game has 10,000 active players. Only about 50 of them are going to be exploiters, and the rest are going to be players that could potentially have high ping, latency issues, and the like. I would much rather be 3-4 studs (smaller than you think!) more lenient with hitboxes (maybe even less depending on how you implement it!) with 0.5% of my playerbase, and let the other 99.5% enjoy a better combat experience.

Depending on your level of expertise, you can implement a complex backtracking system like I do for my game - I rollback animations, and thus am able to verify hits from the client within 0.1 stud accuracy. This thus completely mitigates any chances of exploiters being able to do anything - a best-of-both-worlds scenario.

How does that beat the purpose of the module? The purpose of the module is to take better account for ping & latency, which is simply something you cannot do with a server-based alternative.

1 Like

You’re correct. After a while, I realized that adding a backtracking system would be enough to make it worth it.
Excuse my claims, I didn’t think it through at the time of writing my original response.

1 Like

No problem. If you’ve issues with running it on the client, you can always just not set an owner! The owner is nil, I.e., the server, by default.

How do you get the name of the hitpart? I’ve already tried doing the raycastresult but there’s all kinds of unnecessary information.

RaycastResult{Torso @ 47.3109474, 3.95343065, -112.599541; normal = 0.389086038, 0, -0.921201527; material = Plastic}

You can see the properties of RaycastResult here: RaycastResult | Roblox Creator Documentation
So, to answer your question, you would do HitResult.Instance.Name.

1 Like