Instead of using raycasting, use blockcasting. It works similar to raycasting, but essentially, it’s casting a hitbox. It would allow you to only cast it once rather than casting multiple raycasts in different directions, like in your script, which would boost your game’s performance.
Alright! I will give it a try and get back to you.
I tried this code out but it keeps returning nothing was hit, am I doing something wrong?
local SS = game:GetService("SoundService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local CombatEvent = ReplicatedStorage.Remotes.CombatEvent
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
local CombatStatus = Instance.new("StringValue", character)
CombatStatus.Name = "SwordStatus"
CombatStatus.Value = ""
local Hitbox = Instance.new("Part")
Hitbox.Name = "Hitbox"
Hitbox.Anchored = false
Hitbox.Massless = true
Hitbox.CanCollide = false
Hitbox.CanTouch = false
Hitbox.Transparency = 1
Hitbox.Size = Vector3.new(7, 6, 7)
Hitbox.Color = Color3.new(1, 0, 0)
Hitbox.CFrame = character.HumanoidRootPart.CFrame
Hitbox.Parent = character.HumanoidRootPart
local WeldConstraint = Instance.new("WeldConstraint")
WeldConstraint.Part0 = Hitbox
WeldConstraint.Part1 = character.HumanoidRootPart
WeldConstraint.Parent = Hitbox
Hitbox.CFrame = character.HumanoidRootPart.CFrame * CFrame.new(0, 0, 0)
end)
end)
CombatEvent.OnServerEvent:Connect(function(plr, eventType, Arg1)
local Character = plr.Character
local Humanoid = Character:FindFirstChild("Humanoid")
local CombatStatus = Character:FindFirstChild("SwordStatus")
if eventType == "SM1" and CombatStatus.Value == "" then
CombatStatus.Value = "Attacking"
local AT = Humanoid.Animator:LoadAnimation(script[Arg1])
AT:Play()
local Hitbox = Character.HumanoidRootPart:FindFirstChild("Hitbox")
local blockSize = Vector3.new(7, 6, 7)
local blockDirection = Character.HumanoidRootPart.CFrame.LookVector * 10
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = { Character }
local blockcastResult = workspace:Blockcast(Hitbox.CFrame, blockSize, blockDirection, raycastParams)
if blockcastResult and blockcastResult.Instance then
local hitPart = blockcastResult.Instance
local enemyCharacter = hitPart.Parent
print("Blockcast hit: ", hitPart:GetFullName())
if enemyCharacter and enemyCharacter:FindFirstChild("Humanoid") then
print("Enemy detected:", enemyCharacter.Name)
if enemyCharacter.SwordStatus.Value == "Blocking" then
enemyCharacter.SwordStatus.Value = ""
SS.SwordParry:Play()
AT:Stop()
Character.SwordStatus.Value = "Parried"
task.delay(0.75, function()
Character.SwordStatus.Value = ""
end)
else
local enemyHumanoidRootPart = enemyCharacter:FindFirstChild("HumanoidRootPart")
SS.SwordHit:Play()
if Arg1 == "Stab4" then
enemyCharacter.Humanoid.Health -= 30
else
enemyCharacter.Humanoid.Health -= 10
end
print("Dealing damage to:", enemyCharacter.Name)
if enemyHumanoidRootPart then
local knockbackForce = Instance.new("BodyVelocity")
knockbackForce.MaxForce = Vector3.new(100000, 0, 100000)
knockbackForce.P = 1000
if Arg1 == "Stab4" then
knockbackForce.Velocity = blockDirection * 50
else
knockbackForce.Velocity = blockDirection * 30
end
knockbackForce.Parent = enemyHumanoidRootPart
game:GetService("Debris"):AddItem(knockbackForce, 0.2)
end
end
else
print("No enemy detected or SwordStatus is not found.")
end
else
print("Nothing was hit")
SS.SwordSlash:Play()
end
task.delay(0.75, function()
if CombatStatus.Value == "Attacking" then
CombatStatus.Value = ""
print("Forced stop")
end
end)
elseif eventType == "Block" and (Character.SwordStatus.Value == "" or Character.SwordStatus.Value == "Blocking") then
if Character.SwordStatus.Value == "" then
Character.SwordStatus.Value = "Blocking"
local BlockAnimation = Humanoid.Animator:LoadAnimation(script.Block)
BlockAnimation:Play()
local UpdateFunction
UpdateFunction = Character.SwordStatus.Changed:Connect(function(newStatus)
if newStatus ~= "Blocking" then
BlockAnimation:Stop()
UpdateFunction:Disconnect()
end
end)
task.delay(1, function()
if Character.SwordStatus.Value == "Blocking" then
Character.SwordStatus.Value = ""
print("Blocking ended automatically")
end
end)
end
elseif Character.SwordStatus.Value == "Blocking" then
Character.SwordStatus.Value = ""
end
end)
Where is the hitbox relative to the HumanoidRootPart?
Ok I was just swinging around and I did get a hit, but the detection is not good:
12:45:41.029 Blockcast hit: Workspace.Rig.LeftUpperArm - Server - CombatScript:203
Try changing the direction magnitude to about 2 instead of 10, and let me know what happens.
The detection is much better. The issue is that if the dummy is inside the hitbox, it cant be hit. I can only hit the dummy at a certain position.
Another growing issue is this:
I am trying to hit the dummy, but it keeps getting the other parts. Giving some code to fix this would be nice
Thanks.
Actually don’t worry about the second issue I mentioned above. I fixed that.
In that case, just remove the multiplier part and just have:
local blockDirection = Character.HumanoidRootPart.CFrame.LookVector
Why not use workspace:GetPartsInParts()
?
Yep better.
But still if the player were any closer than this:
it still doesn’t detect. Only if the player is at that exact distance it works. If you go closer it doesn’t detect for some reason.
I will try that if this system doesn’t work.
Just saying Blockcast don’t detect parts that are already in the box when it was created Direct quote from Blockcast Documentation: “Unlike WorldRoot:GetPartsInPart(), this method does not detect BaseParts that initially intersect the shape.” Unless I’m reading that wrong
Huh. Looks like you are right. I will try something out and see if it works.
Oh yeah, I forgot about that. So then, :GetPartsInPart()
would be a better option.
Try to turn off respect to can collide in the raycast perams.
Raycasts with CanCollide checking - Resources / Community Resources - Developer Forum | Roblox
Thanks! Worked like a charm.
Char limit
Sorry for pushing back up; there is a new bug.
For some reason, the hit is only happening every other time. Does anyone know a fix for this?
Server Code:
local Debris = game:GetService("Debris")
local SS = game:GetService("SoundService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local Tool = script.Parent
local animationIds = {
["Stab1"] = "rbxassetid://18894699991",
["Stab2"] = "rbxassetid://18894701886",
["Stab3"] = "rbxassetid://18894703743",
["Stab4"] = "rbxassetid://18894705958",
}
local currentAnimation = "Stab1"
local function GetNextAnimation(current)
local animations = {"Stab1", "Stab2", "Stab3", "Stab4"}
local nextIndex = 1
for i, anim in ipairs(animations) do
if anim == current then
nextIndex = i + 1
break
end
end
if nextIndex > #animations then
nextIndex = 1
end
return animations[nextIndex]
end
function TagHumanoid(humanoid, player)
local Creator_Tag = Instance.new("ObjectValue")
Creator_Tag.Name = "creator"
Creator_Tag.Value = player
Debris:AddItem(Creator_Tag, 2)
Creator_Tag.Parent = humanoid
end
function UntagHumanoid(humanoid)
for i, v in pairs(humanoid:GetChildren()) do
if v:IsA("ObjectValue") and v.Name == "creator" then
v:Destroy()
end
end
end
local function OnToolActivated(tool)
local swordStatus = Character:FindFirstChild("SwordStatus")
if not Humanoid or not swordStatus then
return
end
if swordStatus.Value == "" then
swordStatus.Value = "Attacking"
local animation = Instance.new("Animation")
animation.AnimationId = animationIds[currentAnimation]
local animationTrack = Humanoid.Animator:LoadAnimation(animation)
animationTrack:Play()
currentAnimation = GetNextAnimation(currentAnimation)
animationTrack.Stopped:Connect(function()
if swordStatus.Value == "Attacking" then
swordStatus.Value = ""
print("Animation ended, forced stop")
end
end)
local hitbox = Character:FindFirstChild("HumanoidRootPart"):FindFirstChild("Hitbox")
local overlapParams = OverlapParams.new()
overlapParams.FilterType = Enum.RaycastFilterType.Exclude
overlapParams.FilterDescendantsInstances = { Character }
overlapParams.MaxParts = 10
local partsInHitbox = Workspace:GetPartsInPart(hitbox, overlapParams)
local hitDetected = false
for _, part in ipairs(partsInHitbox) do
if part:IsA("BasePart") and part.Parent ~= Character then
local enemyCharacter = part.Parent
print("Hitbox detected: ", part:GetFullName())
if enemyCharacter and enemyCharacter:FindFirstChild("Humanoid") then
print("Enemy detected:", enemyCharacter.Name)
if enemyCharacter:FindFirstChildOfClass("ForceField") then
print("Enemy has a ForceField, skipping damage and knockback")
continue
end
local enemyHumanoidRootPart = enemyCharacter:FindFirstChild("HumanoidRootPart")
SS.SwordHit:Play()
local damage = (currentAnimation == "Stab4") and 30 or 10
enemyCharacter.Humanoid:TakeDamage(damage)
print("Dealing damage to:", enemyCharacter.Name)
UntagHumanoid(enemyCharacter.Humanoid)
TagHumanoid(enemyCharacter.Humanoid, Player)
if enemyHumanoidRootPart then
local knockbackForce = Instance.new("BodyVelocity")
knockbackForce.MaxForce = Vector3.new(100000, 0, 100000)
knockbackForce.P = 1000
knockbackForce.Velocity = hitbox.CFrame.LookVector * ((currentAnimation == "Stab4") and 50 or 30)
knockbackForce.Parent = enemyHumanoidRootPart
game:GetService("Debris"):AddItem(knockbackForce, 0.2)
end
hitDetected = true
break
end
end
end
if not hitDetected then
print("Nothing was hit")
SS.SwordSlash:Play()
end
end
end
local function onBlockEvent(player)
local character = player.Character
if not character then return end
local humanoid = character:FindFirstChildOfClass("Humanoid")
local combatStatus = character:FindFirstChild("SwordStatus")
if humanoid and combatStatus then
if combatStatus.Value == "" or combatStatus.Value == "Blocking" then
if combatStatus.Value == "" then
combatStatus.Value = "Blocking"
local blockAnimation = humanoid.Animator:LoadAnimation(script.Block)
blockAnimation:Play()
wait(0.5)
if combatStatus.Value == "Blocking" then
combatStatus.Value = ""
blockAnimation:Stop()
print("Blocking ended automatically after 0.5 seconds")
end
local updateConnection
updateConnection = combatStatus.Changed:Connect(function(newStatus)
if newStatus ~= "Blocking" then
blockAnimation:Stop()
updateConnection:Disconnect()
end
end)
blockAnimation.Stopped:Connect(function()
if combatStatus.Value == "Blocking" then
combatStatus.Value = ""
print("Blocking ended automatically")
end
end)
end
else
combatStatus.Value = ""
end
end
end
script.Parent.BlockEvent.OnServerEvent:Connect(onBlockEvent)
local function OnToolEquipped()
Character = Tool.Parent
Player = Players:GetPlayerFromCharacter(Character)
Humanoid = Character:FindFirstChildOfClass("Humanoid")
end
Tool.Activated:Connect(OnToolActivated)
Tool.Equipped:Connect(OnToolEquipped)
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
end)
end)
Thanks for helping!
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.