Yea the hit detection is done client side, here’s a little snippet on the order I call the events in:
(renamed the module “Kenjutsu_HitDetection”)
local Hitbox = Kenjutsu_HitDetection:Initialize(ServerHold, {plr.Character})
Hitbox:HitStart()
Hitbox.OnHit:Connect(function(hit, humanoid)
if game.Players:GetPlayerFromCharacter(humanoid.Parent) then
SentInfo["enemyPlr"] = game.Players:GetPlayerFromCharacter(humanoid.Parent)
Kenjutsu_Events:WaitForChild("Damage_Request"):FireServer(SentInfo, workspace.Universal_Tick.Value)
end
end)
local Used_Slash_Set = Slash_Moveset["Slash"..CurrentSlash]
local SlashAnim = MASTER_Anim_Module.Fire("Combat", Used_Slash_Set.."_Slash"..CurrentSlash)
SlashAnim.Stopped:wait()
Hitbox:HitStop()
Kenjutsu_HitDetection:Deinitialize(ServerHold)
Can you double-check if this portion of the code is being reliably fired? From my tests, Stopped sometimes does not work or does not call correctly (I’ve notified an engineer about this beforehand but I’m unsure of the outcome, I think they are still looking into it). Initialize will return the preexisting hitbox if it wasn’t deinitialized and if it does, it will see HitStop was never called which can explain why some of your hits don’t actually register.
Hello! I’m using this script as-shown in the API notes; however, I’m getting this error:
I have this script placed in the client (in the weapon that fires it), with the module as a child of said script. The debugger says the error occurs here:
Here is my relevant code:
local RaycastHitbox = require(script.RaycastHitboxV3)
local hitRays = RaycastHitbox.Initialize(weapon, {player.Character})
...
local attacking = false
local function attack(actionName, inputState, inputObj)
if not attacking then
if inputState == Enum.UserInputState.Begin then
attacking = true
playAnimationForDuration(swing_1, calcStats.spd)
--hitRays:DebugMode(true)
hitRays.OnHit:Connect(function(hit, humanoid, results)
humanoid:TakeDamage(calcStats.atk) -- will connect to the server later
end)
--
-- testing!
hitRays:HitStart()
wait(swing_1.Length)
hitRays:HitStop()
attacking = false
end
end
end
Some notes:
The attachments are on a meshpart of the weapon and are called “DmgPoint” (which is what I still have it configured as)
Every part of the rest of the script works, and functions correctly when I use it with my less desirable hitbox system
There are objects other than parts in the weapon model, such as the script (I don’t think this would matter as the script searches for attachments)
I’m not really sure what’s going on, so if you could take a look and point me in the right direction, that’d be great! Let me know if you need anymore info.
Hmm, if possible, can you try initializing once and never deinitializing? Is there a reason that you need to deinitialize? Seems like you are reusing the sword hitbox so you probably don’t need to do this. It will help with performance as well and it will guarantee the hitbox will be available and resetted without delay (deinitialize does not remove the hitbox immediately, it only removes it on the next heartbeat frame).
You also mentioned that putting more attachments didn’t work. Have you tried making the hitbox slightly wider? If none of these suggestions worked, I’ll diagnose it a bit further by reusing your script you’ve given me in my own tests to see if its a script or a module issue.
EDIT: I found the solution, just needed to add a wait() when ChildAdded is fired. Hitbox not firing occasionally still happens though, so this code may still be relevant to help you figure out what I’m doing wrong.
I actually tried a completely different approach with only having to initialize once every time the sword is actually created, and the hitbox doesn’t want to work at all now. I actually had to do some workarounds to get the first test going, and I thought this would fix that. It’s not throwing any errors and all the prints are printing as intended.
local Player_Swords_Folder = Runtime_Swords:WaitForChild(plr.Name)
Player_Swords_Folder.ChildAdded:connect(function(child)
if child.Name == "ServerHold" then
local ServerHold = child
local Kenjutsu_Hitbox = Kenjutsu_HitDetection:Initialize(ServerHold, {plr.Character})
local KenjutsuHitboxActivate_Connect
KenjutsuHitboxActivate_Connect = Activate_KenjutsuHitbox:GetPropertyChangedSignal("Value"):connect(function()
if Activate_KenjutsuHitbox.Value == true then
print("start")
Kenjutsu_Hitbox:HitStart()
Kenjutsu_Hitbox.OnHit:Connect(function(hit, humanoid)
if game.Players:GetPlayerFromCharacter(humanoid.Parent) then
if SlashType == "Normal" then
NormalSlashInfo["enemyPlr"] = game.Players:GetPlayerFromCharacter(humanoid.Parent)
Kenjutsu_Events:WaitForChild("Damage_Request"):FireServer(NormalSlashInfo, workspace.Universal_Tick.Value)
elseif SlashType == "Heavy" then
HeavySlashInfo["enemyPlr"] = game.Players:GetPlayerFromCharacter(humanoid.Parent)
Kenjutsu_Events:WaitForChild("Damage_Request"):FireServer(HeavySlashInfo, workspace.Universal_Tick.Value)
end
end
end)
elseif Activate_KenjutsuHitbox.Value == false then
print("end")
Kenjutsu_Hitbox:HitStop()
end
end)
local DestroyedConnect
DestroyedConnect = ServerHold.AncestryChanged:connect(function()
if ServerHold.Parent == nil then
print("de initialized")
Kenjutsu_HitDetection:Deinitialize(ServerHold)
Kenjutsu_Hitbox = nil
if DestroyedConnect then
DestroyedConnect:Disconnect()
DestroyedConnect = nil
end
if KenjutsuHitboxActivate_Connect then
KenjutsuHitboxActivate_Connect:Disconnect()
KenjutsuHitboxActivate_Connect = nil
end
end
end)
end
end)
As you can see in the output, all the prints fire like the system is working as intended. Does anything I’ve done stick out to you as incorrect at all?
I have a feature request, or maybe its there but I couldn’t find how to do it in the API docs.
When I do hitBox:HitStart() it would be really nice to allow it to accept arguments that will be passed into the OnHit event. For example, I might want to name this particular :HitStart() like so:
hitBox:HitStart({Name = "Foo"})
now when I receive the OnHit event like so:
hitBox:OnHit:Connect(function(hit, humanoid, rayCastResults, groupName, myTable)
if myTable.Name == "Foo" then
-- do stuff
end
end)
I will give you an example use-case to go along with this. I am starting and stopping the hit to reset the de-bounce in a for loop. It would be amazing to be able to pass the for loops control variables into the hit. In this example I am looping the hit 3 times and on the third hit, I do double damage. Currently I think I have to construct a new hitbox and connect it fresh for each loop, or maybe just the third one. Being able to pass some parameter into HitStart and the resulting OnHit connection would greatly simplify this sort of thing.
This would make my life easier and also interesting! Thank you
Basically I’m making a brand new hitbox for projectiles and it works perfectly, though it damages the caster and I have no idea how to make it ignore the caster and not damage him, since this module is mainly used for swords.
Hey, is it viable to use these hitboxes on the server, and have no hitbox detection on the client? (Would remove the need for me to add sanity checks etc)
Is there a way to control “How long can a ray last ?” cause if the character is moving so fast it still makes rays behind it that if someone hits the ray he still get damaged even though the caster is far away from him.
Hey all, sorry for the long replies! Long story short I had some health complications which ended up with multiple hospital visits. Though everything should be okay now so I should be back to having support here
Anyone with the same questions above who ended up becoming unanswered should repost/reply underneath me so I can take a look at any problems that people are still having.
@ShokuTakahashi The rays only draw in one frame, and the positions are based on velocity. I don’t think there is a reliable way to tell time with the way the module works. I think a better solution is to have a range limit so even if you are trailing at light speed, you won’t have a lingering ray in your previous position. Perhaps you can try looking into the MainHandler in the heartbeat loop to see if you can implement this.
@Neotrinax The hitbox only creates once yes. Initialize will always return a pre-existing hitbox that has been created previously.
Good that you are okay. I failed trying to make it so maybe i can wait till you can add it in an update for the module. Thats too much advanced for me atm.
New Feature: Did you ever want the hitbox to turn off after a few seconds automatically? Don’t like wait()? Hate using more threads just so your script doesn’t yield? Featuring the new Hitbox Time Scheduler!
Additional information can be found here, though here is a summary from that page for those who don’t want to click onto Github:
Instead of using wait(), spawn(), or delay() which are prone to throttling, consider using RaycastHitbox’s internal custom time scheduler to automatically switch the hitbox off for you. Using this will allow you to continue the script without it yielding. It is extremely simple to use, all you need to do is give HitStart a number. The module will use its preexisting loop to calculate the time automatically with no added performance cost. No hassles and no additional threads created.
local turnOffAfterThisAmountOfSeconds = 5
Hitbox:HitStart(turnOffAfterThisAmountOfSeconds) --- Turns off after 5 seconds automatically
--- Does not yield the thread, the script will automatically continue
print("Hey! I still print!")
Calling HitStop prematurely will automatically cancel the timer as well.
Before anyone asks, once PostSimulation is released, I will update this module accordingly to supersede the now deprecated Heartbeat.