Help with BV and spear throwing logic

When the character starts spinning repeatedly and throws the spear, the spear starts spinning as well.

I’ve tried using different forces, but nothing seemed to help.

Here is the SERVER SCRIPT:

spearEvent.OnServerEvent:Connect(function(player, origin, target, tool: Tool)
	if typeof(player) ~= "Instance" then
		return
	end

	local char = player.Character or player.CharacterAdded:Wait()
	if not char then
		return
	end

	setCollisionGroup(char, "Character")
	setCollisionGroup(tool, "Spear")

	-- Prepare the spear parts
	for _, basePart in ipairs(tool:GetDescendants()) do
		if basePart:IsA("BasePart") then
			basePart.CanCollide = true
			basePart.Anchored = false
		end
	end

	-- Release welds
	local weld = tool:FindFirstChildWhichIsA("Weld")
	if weld then
		weldClones[player] = {
			weld = weld:Clone(),
			parent = weld.Parent
		}
		weld:Destroy()
	end
	print(origin)
	-- Add a tag to act as a debounce
	char:AddTag("SPEAR_THROWN")

	local spearRoot = tool.PrimaryPart
	local spearPoint = tool.BaseParts:FindFirstChild("Spike") :: BasePart
	if not spearPoint then
		warn("Did not find a spear point for " .. player.Name)
        end
	-- Explicitly make the char face the mouse hit position
	local direction = (Vector3.new(target.X, origin.Y, target.Z) - origin).Unit
	
	spearPoint.CFrame = CFrame.new(origin, Vector3.new(target.X, origin.Y, target.Z))
        -- WHERE THE BV IS GETTING APPLIED
	local spearBV = Instance.new("BodyVelocity")
	spearBV.MaxForce = Vector3.new(1e6, 1e6, 1e6)
	spearBV.Velocity = direction * 60
	spearBV.Parent = spearRoot

	-- Measure the distance between the char and spear. Once the spear goes a certain distance or stops moving
	local stopTimer = 0

	local connection
	local stopSpear = false
	connection = RunService.Heartbeat:Connect(function(deltaTime)
		if stopSpear then
			returnSpear(player, spearBV, connection, char, tool)
		end
		local dist = (spearRoot.Position - char.PrimaryPart.Position).Magnitude
		if dist >= spearProperties.MAX_THROW_DISTANCE then
			print("Max Distance reached")
			stopSpear = true
			return
		end

		if spearRoot.AssemblyLinearVelocity.Magnitude < spearProperties.MIN_VELOCITY then
			stopTimer += deltaTime
			if stopTimer >= spearProperties.STOP_THRESHOLD then
				print("Spear has stopped moving!")
				stopSpear = true
				return
			end
		else
			stopTimer = 0
		end
	end)
end)

And here is the local script where ORIGIN and TARGET is getting specified

local function onSpearThrow(input: InputObject, _gameProcessedEvent)
	if _gameProcessedEvent then
		return
	end
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		if not canThrow then -- make sure the player can throw the spear
			return
		end
		if throwCooldown then
			return
		end

		if char:HasTag("SPEAR_THROWN") then
			return
		end
		-- Find the spear. Should be in the equipped slot; players Left Arm
		local spear = utilityModule.getBodyPart(char, "Left Arm"):FindFirstChild(properties.SPEAR_NAME)
		if not spear then
			warn("Did not find spear!")
			return
		end
		throwCooldown = true
		local throwTrack = fxManager.CreateTrack(properties.throwAnimId, animator) :: AnimationTrack
		fxManager.playOrStopTrack(throwTrack, true)

		throwTrack.KeyframeReached:Connect(function(keyframeName)
			if keyframeName ~= "Throw" then
				return
			end
			-- WHERE TARGET AND ORIGIN IS GETTING SPECIFIED
			local origin, target = utilityModule.getBodyPart(char, "Left Arm").Position, mouse.Hit.Position
			spearEvent:FireServer(origin, target, spear)
			print("Fired to the server!")
		end)

		-- Wait the throwtrack length
		throwTrack.Ended:Connect(function()
			task.delay(1, function()
				throwCooldown = false
			end)
			throwTrack:Destroy()
		end)
	end
end

Clip of what is happening:

Any help would be appreciated.

This is a really simple fix, simply add a BodyGyro to the SpearRoot, set the MaxTorque to something that’s enough to let it set the rotation of the Spear, then just set the CFrame property of the BodyGyro to the Spear’s Throw CFrame, which in this case is (from your code)

CFrame.new(origin, Vector3.new(target.X, origin.Y, target.Z))

Thanks, added a body gyro to the SpearRoot like you said and it completely fixed the issue!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.