Having an issue with my combat system

So I made a combat system for my game with custom characters that works by having an invisible part in the model called “AttackZone”. When the attack animation is played the AttackZone shoots out (part of the animation) and hits whatever is in front of the player and a script inside the part deals damage to it if it’s a player. This system works fine if I just click play and test it on dummies, but when I go to test it on other players in a server for some reason the AttackZone only damages them if either player is moving. If both players are stationary the attacks do no damage. I’ve tried running the animations on the server instead of the client but it made no difference. Any clue to what the issue might be?

Have you tried using ray casting, and casting a ray forward instead of using physical objects?

I’ve never really messed with ray casting before, no

I know the roblox wiki has a great article on ray casting, and it’s much more accurate. The .Touched event only fires with movement.

Alright I’ll look into it :wink: .

This is due to the fact that the attack part has no velocity. If you want this to work you can apply a tiny forward velocity on the attack part and this will cause touched updates.

Example:

game:GetService("RunService").Heartbeat:Connect(function()
    attackPart.Velocity = Vector3.new(0, 0, -0.01)
end)

But as @REALTimothy0812 suggested RayCasting would be a faster and less hacky way of doing this.

If you have the character, you can make a ray with:
Ray.new(char.HumanoidRootPart.Position,char.HumanoidRootPart.CFrame.lookVector*5)

The humanoidRootPart position is the start, the lookVector times 5 is the direction.5 is the distance.

Use workspace:FindPartOnRay(ray) to find colliding parts. You might want to also add the character to the ignore list so you do not hit yourself.

You should use renderstepped, as Heartbeat is usually for game logic, while renderstepped is for real-world 3-D reorientation.

game:GetService("RunService").Renderstepped:Connect(function()
    attackPart.Velocity = Vector3.new(0, 0, -0.01)
end)

They can be used for either, HeartBeat provides the amount of time that passed since the last heart beat. They both run with framerate.

I just figured it is ideally bad practice to use Heartbeat for these types of scenarios. I generally use Renderstepped for real world reorientation. But it’s not wrong to use Heartbeat, just a suggestion.

RenderStepped is not available on the server for one thing and secondly Heartbeat fires after physics which is important in this case. I always keep server-side physics inside of Heartbeat because if I didn’t I would expect to see strange results.

If you’re animating something, of course you should use RenderStepped, but in this case we are looking at setting velocity which is physics related. If we use RenderStepped and the player’s FPS is less than Heartbeat’s tps than velocity will be inconsistently set, or set too quickly resulting in fluctuations in the final Velocity’s Magnitude.

3 Likes

Do you know of the reason why velocity is required for Touched updates? I’ve been having massive troubles with my hitboxes for another game, though I notice one of my archived projects have hitboxes that work completely fine by adding a body force to the hitbox with a negligible amount of force.

I apologize for not getting back to you quickly… If a part with collisions off has no velocity, no collision/physics updates will happen which I’d guess is for performance reasons. If you want an object to have collision updates, setting velocity causes the part to want to move in a direction meaning physics will take place.

Adding a BodyForce to a part will actually apply velocity. That is a non-programmatic way to apply velocity and does basically the same thing (but some extra math may be done)… I’d guess a BodyVelocity would be slightly more efficient since it doesn’t need to take into account mass but it probably doesn’t matter unless you have many thousands of hitboxes all at once.

2 Likes