Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Pet always looks at one direction?

So I've been looking at this pet (follow) system and I can't figure out what's wrong with it, the pet was always looking at one direction then I've fixed that so it moves with the characters direction but it still looks the wrong way, I want it facing the character's direction.

Thank you in advanced.

The script that makes the magic happen.

game.ReplicatedStorage.Events.GivePet.OnClientEvent:Connect(function(Pet)
	
	local Character = Player.Character
	Pet:SetPrimaryPartCFrame(Character.PrimaryPart.CFrame)
	local BodyGyro = Instance.new("BodyGyro")
	BodyGyro.Parent = Pet.PrimaryPart
	BodyGyro.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)
	local BodyPosition = Instance.new("BodyPosition")
	BodyPosition.Parent = Pet.PrimaryPart
	
end)

game:GetService("RunService").RenderStepped:Connect(function()
	local Pet = workspace.Pets:FindFirstChild(Player.Name)
	if not Pet then return end;
	local BodyPosition = Pet.PrimaryPart.BodyPosition
	local BodyGyro = Pet.PrimaryPart.BodyGyro
	game:GetService("RunService").Heartbeat:Connect(function()
		--BodyPosition.Position = Character.HumanoidRootPart.Position + Vector3.new(2, 2, 3)
		--BodyGyro.CFrame = Character.HumanoidRootPart.CFrame + Vector3.new(0,10,10)
		BodyPosition.Position = Character.HumanoidRootPart.Position + Vector3.new(3, 3, 4)
		BodyGyro.CFrame = Character.HumanoidRootPart.CFrame
	end)
end)

It's a model, with parts / unions in it.

2 answers

I don't think it's necessary to set the primary part CFrame since you're changing the gyro's CFrame to the humanoidRootPart's CFrame.

Also, I don't think it's good practice to use runservice inside another runservice.

Make sure you weld every part to the primary part.

Here's what I did to test it.

I created a pet and gave it a primary part. I welded the pet to the primary part. Everything inside the pet model is welded to the "PrimaryPart". Next I gave the following script to the primary part and the pet would continuously face the direction of the char.

I'm not sure what you are doing wrong. But try replicating my script and let me know how it does for you. If it doesn't work out, then something is wrong with your pet model.

local primaryPart = script.Parent
primaryPart.Anchored = false
local prrimaryPartPos = Instance.new("BodyPosition",primaryPart)
local prrimaryPartGyro = Instance.new("BodyGyro",primaryPart)
prrimaryPartGyro.MaxTorque = Vector3.new(900000,900000,900000)
local offsetPosition = Vector3.new(2,2,0)
local char = workspace:WaitForChild("DevMaster333")

while wait(0.1) do
	local ownerPos = char.HumanoidRootPart.Position
	-- Changing the power of the body position depending on how far the pet is from the character. The further away it is, the stronger the power.
	local stopAt = ((ownerPos-primaryPart.Position).magnitude - 1) * 1000
	prrimaryPartPos.P = stopAt
	prrimaryPartPos.Position = ownerPos + offsetPosition
	prrimaryPartGyro.CFrame = char.HumanoidRootPart.CFrame
end

1 comment

0

Have you tried it? How did it go?

As DevMaster333 said, you should not nest RunService connections. With every RenderStepped you are making a new Heartbeat connection. That means at 60fps, you have 60 new connections every second! Eventually your game will slow down until an inevitable crash.

For that matter you should not use RenderStepped for anything else than manipulating camera, as the engine has to execute this code before actual frame render! Heartbeat (used outside RenderStepped) connection is better, however as I will demonstrate, even that is not needed. Remember that both of this connections are extremely resource heavy, and should be only used as a last resort.

The other problem is that you are using BodyGyro and BodyPosition. Unless you are updating an old game, or you really know that you need old body movers functionality, there is absolutely no reason to use those in this case.

While pet system on client could work, but wouldn't it be better for all players to see pets? I will therefore provide a server script.

You are making a pet following system. This just screams to use shiny new AlignPosition and AlignOrientation. Those were basically made for situations like this. They however have a rather steep learning curve, as you need to use Attachments. I will do my best to provide a step - by - step in script comments below.

--put your pet in server storage
local pet = game.ServerStorage.Pet

local function GivePet(player)
	
	--first lets find player character
	local character = player.Character or player.CharacterAdded:Wait()
	
	--next we will make a character attachment
	local petGoal = Instance.new("Attachment")
	--you can change the offset of the attachment, this is where the pet will try to go
	--this is called Position, but it is actually distance from parent.
	petGoal.Position = Vector3.new(3,3,4)
	--you can also change the goal orientation, but it should work with default one
	--petGoal.Orientation = Vector3.new(0,0,0)
	petGoal.Parent = character:FindFirstChild("HumanoidRootPart")
	
	--next we will need to clone the pet and weld all its parts to the primary part
	--Use new WeldConstraints to avoid setting C0, this is also the way to go for new games.
	--"BasePart" means part, meshparts and unions!
	local newPet = pet:Clone()
	newPet.Parent = workspace
	for _, part in pairs(newPet:GetDescendants()) do
		if part:IsA("BasePart") and part.Name ~= "PrimaryPart" then
			local weld = Instance.new("WeldConstraint")
			weld.Part0 = part
			weld.Part1 = newPet.PrimaryPart 
			weld.Parent = part
			part.Anchored = false
		end
	end
	
	--now we will make a pet attachment
	--do not change position or orientation here, unless you don't want 
	--pet to be "pulled" by the middle of primary part
	local petLeash = Instance.new("Attachment")
	petLeash.Parent = newPet.PrimaryPart
	
	--lets add AlignPosition, this will move our pet to the goal position.
	local mover = Instance.new("AlignPosition")
	mover.Attachment0 = petLeash
	mover.Attachment1 = petGoal
	mover.MaxForce =  100000
	--from max experience is better to control maxspeed than max force
	--but feel free to experiment
	mover.MaxVelocity = 5
	mover.Parent = newPet.PrimaryPart

	--now lets add AlignOrientation, this will rotate our pet into desired direction
	local rotater = Instance.new("AlignOrientation")
	rotater.Attachment0 = petLeash
	rotater.Attachment1 = petGoal
	rotater.MaxTorque = 100000
	--as before, set torque to high number and control velocity
	rotater.MaxAngularVelocity = 0.5
	rotater.Parent = newPet.PrimaryPart

	--finally unachor your pet and the job is done
	newPet.PrimaryPart.Anchored = false
	
end

--this is just a raw function, and since you used local script and remote event before,
--i do not know how you are supposed to integrate it with your code.

--here is an example

local me = game.Players:WaitForChild("Sleazel")
GivePet(me)

I hope this helps. EDIT: Make sure your primary part is called "PrimaryPart", as this script will break otherwise.

This discussion is preserved as it was. New answers, comments, and votes are closed.