How do I make region3 last longer?

Hi, I’m making a punch script using region3 but when you click to punch, region3 only appears for a split second and then disappears. How can I make the region3 be there when the punch hits?

local Enabled = true
local Combo = 1

wait(.001)
script.Parent.OnServerEvent:connect(function(Player, Action)
	local c = Player.Character
	if Enabled == false then return end
	if Action == "Combat" then
		Enabled = false
		if Combo == 1 then
			Combo = 2
			local Anim1 = c.Humanoid:LoadAnimation(script.Punch1)
			Anim1:Play()
			script.Event:Fire()
		elseif Combo == 2 then
			Combo = 1
			local Anim2 = c.Humanoid:LoadAnimation(script.Punch2)
			Anim2:Play()
			script.Event:Fire()
		end
		wait(.2)
		local Region = Region3.new(c.HumanoidRootPart.CFrame*CFrame.new(0,0,-2).p - Vector3.new(2,2,2),c.HumanoidRootPart.CFrame*CFrame.new(0,0,-2).p + Vector3.new(2,2,2)) -- region3
		local RTable = workspace:FindPartsInRegion3(Region, nil, 20)
		for i,v in pairs(RTable) do
			if v.Parent:findFirstChild("Humanoid") and v.Parent:findFirstChild("Deb") == nil and v.Parent ~= c then
				v.Parent.Humanoid:TakeDamage(4)
				
				local Deb = Instance.new("BoolValue", v.Parent)
				Deb.Name = "Deb"
				game.Debris:AddItem(Deb,0.2)
				
				local S = Instance.new("Sound", v)
				S.SoundId = "rbxassetid://131237241"
				S.PlaybackSpeed = math.random(80,120)/100
				S:Play()
				
				local FX = Instance.new("Part", workspace.FX)
				FX.Name = "CombatHit"
				FX.Transparency = 0
				FX.CanCollide = false
				FX.Anchored = true
				FX.Material = "ForceField"
				FX.Color = Color3.new(1,0,0)
				FX.Size = Vector3.new(1,1,1)
				
				local SM = Instance.new("SpecialMesh", FX)SM.MeshType = "Sphere"
				SM.Scale = Vector3.new(0,0,0)
				FX.CFrame = v.Parent.HumanoidRootPart.CFrame*CFrame.new(math.random(-20,20)/10,math.random(-20,20)/10,math.random(-20,20)/10)
				
				local BV = Instance.new("BodyVelocity", v)
				BV.maxForce = Vector3.new(25000,25000,25000)
				BV.Velocity = c.HumanoidRootPart.CFrame.lookVector*5
				game.Debris:AddItem(BV,0.2)
			end
		end
		wait(0.15)
		Enabled = true
		if script.Parent.Parent.Parent.Humanoid.Health < 1 then
			script.Parent.Parent:Destroy()
		end
	end
end)
2 Likes

You could run a separate thread for the duration of the animation that is being played. You may have to change your logic a bit for hit detection or whatever result you’re trying to achieve. But the thread will fire the Region3 check for the duration of the animation at approximately 1/60th of a second. (How fast RunService.Stepped is fired)

It also won’t yield your code.

local RunService = game:GetService("RunService")

script.Parent.OnServerEvent:connect(function(Player, Action)    
local c = Player.Character
    	if Enabled == false then return end
    	if Action == "Combat" then
            local Anim = nil -- Define the animation variable here
    		Enabled = false
    		if Combo == 1 then
    			Combo = 2
    			Anim = c.Humanoid:LoadAnimation(script.Punch1)
    			Anim:Play()
    			script.Event:Fire()
    		elseif Combo == 2 then
    			Combo = 1
    			Anim = c.Humanoid:LoadAnimation(script.Punch2)
    			Anim:Play()
    			script.Event:Fire()
    		end
    		wait(.2)
            coroutine.resume(coroutine.create(function()
                while Anim.IsPlaying() and RunService.Stepped:wait() do -- While the animation is playing and we wait for the next frame (Approx. 1/60th a second)
            		local Region = Region3.new(c.HumanoidRootPart.CFrame*CFrame.new(0,0,-2).p - Vector3.new(2,2,2),c.HumanoidRootPart.CFrame*CFrame.new(0,0,-2).p + Vector3.new(2,2,2)) -- region3
    		        local RTable = workspace:FindPartsInRegion3(Region, nil, 20)
            end))
end)

Alternatively, you could run the same loop at the bottom of the OnServerEvent without a thread. When Region3 returns a part, you can fire a BindeableEvent which can take arguments and handle code whenever a condition is triggered.

it gives me unkown global ‘RTable’
and
29: [invalid argument #1 to ‘pairs’ (table expected, got nil)

You’re going to have to reposition a few variables and rework a bit of the logic. I also did not test the code. But the logic should be straight forward.

Hi so the it works but it does damage right after the punch animation ends. How can I make it so it does damage when the punch hits?

clip:
https://imgur.com/a/dpxB2Kb

Here’s the updated script:

local Enabled = true
local Combo = 1
local RunService = game:GetService("RunService")
local Region
local RTable

script.Parent.OnServerEvent:connect(function(Player, Action)    
local c = Player.Character
	if Enabled == false then return end
	if Action == "Combat" then
	    local Anim1 = c.Humanoid:LoadAnimation(script.Punch1)
		local Anim2 = c.Humanoid:LoadAnimation(script.Punch2)
		Enabled = false
		if Combo == 1 then
			Combo = 2
			Anim1:Play()
			script.Event:Fire()
		elseif Combo == 2 then
			Combo = 1
			Anim2:Play()
			script.Event:Fire()
		end
		wait(.25)
		coroutine.resume(coroutine.create(function()
	        while Anim1.IsPlaying or Anim2.IsPlaying and RunService.Stepped:wait() do -- While the animation is playing and we wait for the next frame (Approx. 1/60th a second)
				wait(.01)
				Region = Region3.new(c.HumanoidRootPart.CFrame*CFrame.new(0,0,-2).p - Vector3.new(2,2,2),c.HumanoidRootPart.CFrame*CFrame.new(0,0,-2).p + Vector3.new(2,2,2)) -- region3 -- region3
				RTable = workspace:FindPartsInRegion3(Region, nil, 20)
			end
			for i,v in pairs(RTable) do
				RTable = false
				Region = false
				if v.Parent:findFirstChild("Humanoid") and v.Parent:findFirstChild("Deb") == nil and v.Parent ~= c then
					v.Parent.Humanoid:TakeDamage(4)
					local Deb = Instance.new("BoolValue", v.Parent)
					Deb.Name = "Deb"
					game.Debris:AddItem(Deb,0.2)
					
					local S = Instance.new("Sound", v)
					S.SoundId = "rbxassetid://131237241"
					S.PlaybackSpeed = math.random(80,120)/100
					S:Play()
					
					local FX = Instance.new("Part", workspace.FX)
					FX.Name = "CombatHit"
					FX.Transparency = 0
					FX.CanCollide = false
					FX.Anchored = true
					FX.Material = "ForceField"
					FX.Color = Color3.new(1,0,0)
					FX.Size = Vector3.new(1,1,1)
					
					local SM = Instance.new("SpecialMesh", FX)SM.MeshType = "Sphere"
					SM.Scale = Vector3.new(0,0,0)
					FX.CFrame = v.Parent.HumanoidRootPart.CFrame*CFrame.new(math.random(-20,20)/10,math.random(-20,20)/10,math.random(-20,20)/10)
					
					local BV = Instance.new("BodyVelocity", v)
					BV.maxForce = Vector3.new(25000,25000,25000)
					BV.Velocity = c.HumanoidRootPart.CFrame.lookVector*5
					game.Debris:AddItem(BV,0.2)
				end
			end
		end))
		wait(0.25)
		Enabled = true
		if script.Parent.Parent.Parent.Humanoid.Health < 1 then
			script.Parent.Parent:Destroy()
		end
	end
end)
1 Like

Well your while loop lasts as long as the animation. But what if I hit an enemy on the first frame of the animation and miss them on the last? You’ll overwrite RTable with the empty one.

If you want to achieve a one hit only effect, check if the RTable contains a part with a Humanoid under its parent. If it does, break the loop. (Make sure that if there is a Humanoid under the same parent, it’s not the player’s own)

3 Likes

After like six hours of trying to fix this it finally works thank you so much

1 Like

Hi I was reading this thread and I got the same issue as you when doing what Exeplex said to, I read his solution but I don’t understand how it worked for you. Do you mind helping me?