Just running the humanoid collided event with no internal checks, a humanoid is not always detected on the hit, even when they are clearly hit by the weapon/rays. If anyone else has experienced this, and/or has a possible solution, please let me know.
local Caster = ClientCast.new(tool.Blade, raycastParams)
local hitTable = {}
-- Connect callback to 'Collided' event
Caster.HumanoidCollided:Connect(function(RaycastResult, HitHumanoid)
print(HitHumanoid.Parent.Name)
--Calcuate and deal damage based on weapon and active buffs/debuffs
--DamageModule.DealDamageBasic(tool.Name, player, HitHumanoid, character, hitTable, toolInfo.Damage)
end)
-- Set owner of ClientCaster, who will be the one to calculate collisions.
-- You can skip this if you want the server to be the owner.
Caster:SetOwner(player)
-- Start detecting collisions
Caster:Start()
task.wait(toolInfo.Cooldown - 0.2)
-- Stop the caster object / collisions detections
Caster:Stop()
I can’t really help without having a way to reproduce the issue. I recommend you try isolating the problem, and finding as consistent a repro as possible. This would help a lot in fixing the bug!
Well the issue I’m having is with me running the module bare bones, with nothing else in the back ground. I am however, accessing the module from the server, which honestly isn’t really a great idea for combat, and may be the cause of the discrepancies. I’ll try testing the system locally instead.
That’s the intended use of the module! It handles client <–> server communication for you, so you can just set up hitboxes on server, have them calculated on client, and sent back to server. Depending on how big the hitbox inaccuracy may be, perhaps it could be attributed to network lag?
Well the issue persists even in local play test servers against stationary player characters with fairly optimal performance. I’ll run some extensive tests when I have time.
Not to be rude, it could simply be an issue with how I setup the system, but after moving over to the raycast hitbox, all hits were detected. If anyone else ends up having similar issues to what I was having I could maybe dig deeper and try to be a bit more helpful. One thing I will note is that I setup the hitboxes on the client using the rh4 module, over on the server as I did with yours.
Also i’ve seen others mention this; however, the detections seemed worse when I had attacking animations that caused the dmgpoints to intersect the player wielding the weapon. Hence, it may have been an issue with the module registering the attacker’s character and then jumping out of the hitdetection system, without continuing checks. (Just speculations though)
Well, as mentioned in the thread this module is meant to be very barebones in order to allow for maximum customization for the end user - this comes with a downside of being complex for those not as familiar, or to those who don’t need overly dynamic behavior.
Unsure if you’re referring to this module or rh4, but ClientCast has no built-in debounces, nor does it differentiate the weapon wielder from other targets. It shouldn’t stop raycasting when it hits a target, only when you explicitly call either:Stop or :Destroy.
game.Players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Connect(function(char)
while true do
local lastHRP = char.HumanoidRootPart.Position
task.wait(2)
if (char.HumanoidRootPart.Position - lastHRP).Magnitude > 20 then
char:PivotTo(CFrame.new(lastHRP))
end
end
end)
end)
anyway, I wanted smooth weapons and this is what i will use in the future, thanks
If a connected client were to have several connected casters at once, a raycast event from the client would fire all active casters on the server which are owned by that client. Oops…
How would i activate raycasts for separate parts? For example, have the left fist activate it’s raycasts only, then on the second time the player clicks the right fist activates.
So I’ve been using your module to make a sword system. Works pretty nice, however I noticed one thing.
Whenever I try to set the owner of the sword and do Caster:GetOwner(), it prints out nil? And using Caster:GetPing() prints out 0.
Did I mess something up?
Screenshots:
Client:
local RS = game:GetService("ReplicatedStorage")
local PS = game:GetService("Players")
local player = PS.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
player.CharacterAppearanceLoaded:Wait()
local hum = char:FindFirstChildWhichIsA("Humanoid")
local animator = hum:FindFirstChildWhichIsA("Animator")
local tool = script.Parent
local blade = tool:WaitForChild("Blade")
local equip = blade:WaitForChild("Equip")
local request = RS.Sword.Events.Request
local validate = RS.Sword.Events.Validate
local idleAnim = nil
local animation = {
attack = {
9503532906,
9503922539,
9504030319
},
idle = 9504150874,
}
local function LoadAnimation(id, priority)
local anim = Instance.new("Animation") do
anim.AnimationId = "rbxassetid://" .. id
end
local load = animator:LoadAnimation(anim) do
load.Priority = priority
load:Play()
end
return load
end
tool.Equipped:Connect(function()
equip:Play()
idleAnim = LoadAnimation(animation.idle, Enum.AnimationPriority.Idle)
end)
tool.Unequipped:Connect(function()
if idleAnim then
idleAnim:Stop()
idleAnim = nil
end
end)
tool.Activated:Connect(function()
request:FireServer(tool)
end)
request.OnClientEvent:Connect(function()
LoadAnimation(animation.attack[math.random(1, #animation.attack)], Enum.AnimationPriority.Action)
end)
Server:
local RS = game:GetService("ReplicatedStorage")
local caster = require(RS.Sword.ClientCast)
local request = RS.Sword.Events.Request
local validate = RS.Sword.Events.Validate
local stat = {
Sword1 = {Damage = 10}
}
local debounce = {}
local function IsHitboxValid(hitPos: Vector3, swordPos: Vector3): boolean
local mag = (hitPos - swordPos).Magnitude
if mag > 8 then
return false
else
return true
end
end
local function CalculateHitbox(player, blade)
if not player or not blade then
return
end
local sword = caster.new(blade, RaycastParams.new())
local char = player.Character or player.CharacterAdded:Wait()
local debounce = {}
sword.HumanoidCollided:Connect(function(ray, hum)
local instance = ray.Instance
if instance:IsDescendantOf(char) or instance:IsDescendantOf(blade.Parent) or IsHitboxValid(ray.Position, sword.Object.Position) == false then
return
end
local info = stat[blade.Parent.Name]
local hit = blade:FindFirstChild("Hit")
if debounce[hum] then
return
end
debounce[hum] = true
hit:Play()
hum:TakeDamage(info.Damage)
end)
task.spawn(function()
warn("old: ", sword:GetOwner())
sword:SetOwner(player)
warn("new: ", sword:GetOwner())
warn("ping: ", sword:GetPing())
sword:Start()
task.wait(1)
sword:Destroy()
end)
end
request.OnServerEvent:Connect(function(player: Player, tool: Tool)
if debounce[player] or not tool:FindFirstChild("Blade") then
return
end
local blade = tool:FindFirstChild("Blade")
debounce[player] = true
request:FireClient(player)
CalculateHitbox(player, blade)
task.wait(2)
debounce[player] = false
end)
I’ve been trying to use this for a few hours, and got a bug.
Whenever I first join the game, hitboxes are fine, but when I respawn and try to hit someone, the first hit registers, but then it just breaks and there are no errors, or it just registers a few hits.
Hey, sorry for the late response. What’s happening is that to make sure the :SetOwner command is replicated to the client, :SetOwner is actually wrapped in task.spawn, which then yields for a maximum of 0.1 seconds. This is to make sure that by the time the SetOwner command is sent to the client, the client already has a Caster object created.
If you want the caster’s object to be set to player the moment it’s created, use the third argument of ClientCast.new directly:
EDIT: Due to how I structured the code, it should actually be fine to remove the yields in theory. I will update the module to remove the yields, which should fix your issue without having to do anything besides updating the module.
Please verify that this is indeed an issue with the ClientCast module, and not your code. ClientCast never indexes the Character property in any of it’s code, meaning it’s extremely unlikely for the bug to be tied to ClientCast itself.