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.
https://gyazo.com/7a6aa662a0ecf10c1108165acb47eb19
My thoughts are as following:
- My debounce function is done incorrectly (I dont think it is)
- The customised event is not disconnect with ClientCaster:Stop() function
- 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 --
ClientCaster.HumanoidCollided:Connect(function(RaycastResult,HitHumanoid)
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)
end
end
end
end)
--------------------------------------------
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)
Edit:
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.
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.
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).
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.
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.
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
.
When I enable Debug in settings it works the first time but it doesnât seem to after that. I think this has to do with setting self._Debug
to false in DisableDebug()
(which is called automatically in Stop()
) which prevents StartDebug()
from being called again, which also prevents it from telling the client to start debugging as well. All I did was remove the self._Debug = true
and self._Debug = false
in StartDebug()
and DisableDebug()
, but kept the ReplicationConnection
updates in and it stayed debugging as expected.
Good catch! Iâve pushed an update to both the github & the Roblox module - could you update and confirm that this has been fixed on your end?
Seems to work, one other thing I wanted to mention is that Recursive doesnât seem to replicate when you do SetRecursive
. I was looking into the code and saw that a caster is only made on the client when Start
is fired which means that youâll need to start the hitbox at least once in order to apply updates to it (like setting recursive). I think itâd be beneficial to add caster creation to Update
as well so that this works:
Hitbox = ClientCast.new(Tool, params, Player)
Hitbox:SetRecursive(true)
as right now this doesnât because Caster
is nil
on the client until you start it once.
You already have the functionality to create a caster on the client if it doesnât exist so it should just be able to be copy pasted into the update function as well.
Update 1.0.5.0
- Casters on the client can now have their methods be updated without having to use the Start method prior
cc. @steven4547466
Update 1.0.6.0 [IMPORTANT UPDATE]
- A bug has been fixed in regards to raycasts actually raycasting in the opposite direction - I frankly have no idea how this went by unnoticed for so long, but I have noticed this on accident and thus fixed it. Please update to make sure this bug is fixed for you all also.
Update 1.0.7.0
-
Switched to " (double quotation marks) instead of â (single quotation marks) to stay consistent with Roblox code.
-
Switched out coroutine.resume for task.spawn, which does not break continuations.
-
GetPing is no longer divided by two, as ping is a two-way trip rather than one-way.
General tip:
if youâre calculating your hitbox on the client, please also validate on whether the hit-position is accurate, as exploiters could spoof this value whenever itâs being sent over to the server. There is no one reliable way to verify this, and as such you should program your own solutions depending on the context.