Cat isn't following the player

Script in my cat model. Primary Part is already been set and there are no errors in the output nor any prints/warns. I have made sure the Owner Attribute in the value is set to the players username.

local cat = script.Parent
task.wait(4)
-- Ensure the cat model has a PrimaryPart set
if not cat.PrimaryPart then
	warn("PrimaryPart not set for cat model")
	return
end

-- Add BodyGyro to the PrimaryPart for orientation
local bodyGyro = Instance.new("BodyGyro")
bodyGyro.MaxTorque = Vector3.new(4000, 4000, 4000)  -- Adjust the torque as needed
bodyGyro.P = 3000  -- Adjust the power of the gyro
bodyGyro.Parent = cat.PrimaryPart

-- Add BodyPosition to the PrimaryPart
local bodyPosition = Instance.new("BodyPosition")
bodyPosition.MaxForce = Vector3.new(50000, 50000, 50000)  -- Increase the force as needed
bodyPosition.Parent = cat.PrimaryPart

-- Get the Value object with the Owner attribute
local ownerValueObject = cat:FindFirstChild("Value")
if not ownerValueObject then
	warn("Value object not found in cat model")
	return
end

local rotationOffset = CFrame.Angles(0, math.rad(-80), 0) -- Adjust this angle incrementally (90 degrees initially)
local previousPosition = cat.PrimaryPart.Position
local offset = Vector3.new(2, 2, -2)  -- Adjust the offset as needed (2 studs right, 2 studs up, 2 studs behind)

-- Update the cat's orientation to face the direction it is moving
game:GetService("RunService").Stepped:Connect(function()
	local ownerName = ownerValueObject:GetAttribute("Owner")
	if not ownerName then
		return
	end
	local player = game.Players:FindFirstChild(ownerName)
	if not player then
		warn("Player not found: " .. ownerName)
		return
	end

	local character = player.Character
	if not character then
		warn("Character not found for player: " .. ownerName)
		return
	end

	local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
	if not humanoidRootPart then
		warn("HumanoidRootPart not found for player: " .. ownerName)
		return
	end

	local currentPosition = cat.PrimaryPart.Position
	local direction = (currentPosition - previousPosition).Unit

	if direction.Magnitude > 0 then
		direction = Vector3.new(direction.X, 0, direction.Z).Unit
		bodyGyro.CFrame = CFrame.lookAt(cat.PrimaryPart.Position, cat.PrimaryPart.Position + direction) * rotationOffset
	end

	local targetPosition = humanoidRootPart.Position + offset
	bodyPosition.Position = targetPosition

	previousPosition = currentPosition
end)

5 Likes

I have narrow down the issue to this bit:

if direction.Magnitude > 0 then
		direction = Vector3.new(direction.X, 0, direction.Z).Unit
		bodyGyro.CFrame = CFrame.lookAt(cat.PrimaryPart.Position, cat.PrimaryPart.Position + direction) * rotationOffset
		print("o")
	end

It seems something is wrong with if statement as o is not printed

2 Likes

Here, the magnitude of the unit vector is always going to be 1, but regardless your mistake is that you’re getting the unit vector of two identical vectors. At the beginning of your loop, you the past position and current position are identical so the unit vector is undefined, and the magnitude is also undefined so it never reaches that if statement

1 Like

Ok, how would I fix it then?

This was my attempt still didn’t work.

task.wait(7)
local cat = script.Parent

-- Ensure the cat model has a PrimaryPart set
if not cat.PrimaryPart then
	warn("PrimaryPart not set for cat model")
	return
end

-- Add BodyGyro to the PrimaryPart for orientation
local bodyGyro = Instance.new("BodyGyro")
bodyGyro.MaxTorque = Vector3.new(4000, 4000, 4000)  -- Adjust the torque as needed
bodyGyro.P = 3000  -- Adjust the power of the gyro
bodyGyro.Parent = cat.PrimaryPart

-- Add BodyPosition to the PrimaryPart
local bodyPosition = Instance.new("BodyPosition")
bodyPosition.MaxForce = Vector3.new(50000, 50000, 50000)  -- Increase the force as needed
bodyPosition.Parent = cat.PrimaryPart

-- Get the Value object with the Owner attribute
local ownerValueObject = cat:FindFirstChild("Value")
if not ownerValueObject then
	warn("Value object not found in cat model")
	return
end

local rotationOffset = CFrame.Angles(0, math.rad(-80), 0) -- Adjust this angle incrementally (90 degrees initially)
local previousPosition = cat.PrimaryPart.Position
local offset = Vector3.new(2, 2, -2)  -- Adjust the offset as needed (2 studs right, 2 studs up, 2 studs behind)

-- Update the cat's orientation to face the direction it is moving
game:GetService("RunService").Stepped:Connect(function()
	local ownerName = ownerValueObject:GetAttribute("Owner")
	if not ownerName then
		return
	end

	local player = game.Players:FindFirstChild(ownerName)
	if not player then
		warn("Player not found: " .. ownerName)
		return
	end

	local character = workspace:FindFirstChild(player.Name)
	if not character then
		warn("Character not found for player: " .. ownerName)
		return
	end

	local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
	if not humanoidRootPart then
		warn("HumanoidRootPart not found for player: " .. ownerName)
		return
	end

	local currentPosition = cat.PrimaryPart.Position
	print("0")
	if (currentPosition - previousPosition).Magnitude > 0.01 then
		print("1")
		local direction = (currentPosition - previousPosition).Unit
		direction = Vector3.new(direction.X, 0, direction.Z).Unit
		bodyGyro.CFrame = CFrame.lookAt(cat.PrimaryPart.Position, cat.PrimaryPart.Position + direction) * rotationOffset
	end

	local targetPosition = humanoidRootPart.Position + offset
	bodyPosition.Position = targetPosition

	previousPosition = currentPosition
end)

1 Like

Try this as this should fix the issue.

task.wait(7)
local cat = script.Parent

-- Ensure the cat model has a PrimaryPart set
if not cat.PrimaryPart then
	warn("PrimaryPart not set for cat model")
	return
end

-- Add BodyGyro to the PrimaryPart for orientation
local bodyGyro = Instance.new("BodyGyro")
bodyGyro.MaxTorque = Vector3.new(4000, 4000, 4000)  -- Adjust the torque as needed
bodyGyro.P = 3000  -- Adjust the power of the gyro
bodyGyro.Parent = cat.PrimaryPart

-- Add BodyPosition to the PrimaryPart
local bodyPosition = Instance.new("BodyPosition")
bodyPosition.MaxForce = Vector3.new(50000, 50000, 50000)  -- Increase the force as needed
bodyPosition.Parent = cat.PrimaryPart

-- Get the Value object with the Owner attribute
local ownerValueObject = cat:FindFirstChild("Value")
if not ownerValueObject then
	warn("Value object not found in cat model")
	return
end

local rotationOffset = CFrame.Angles(0, math.rad(-80), 0) -- Adjust this angle incrementally (90 degrees initially)
local previousPosition = cat.PrimaryPart.Position
local offset = Vector3.new(2, 2, -2)  -- Adjust the offset as needed (2 studs right, 2 studs up, 2 studs behind)

-- Update the cat's orientation to face the direction it is moving
game:GetService("RunService").Stepped:Connect(function()
	local ownerName = ownerValueObject:GetAttribute("Owner")
	if not ownerName then
		return
	end

	local player = game.Players:FindFirstChild(ownerName)
	if not player then
		warn("Player not found: " .. ownerName)
		return
	end

	local character = workspace:FindFirstChild(player.Name)
	if not character then
		warn("Character not found for player: " .. ownerName)
		return
	end

	local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
	if not humanoidRootPart then
		warn("HumanoidRootPart not found for player: " .. ownerName)
		return
	end

	local currentPosition = cat.PrimaryPart.Position
	if (currentPosition - previousPosition).Magnitude > 0.01 then
		local direction = (currentPosition - previousPosition).Unit
		direction = Vector3.new(direction.X, 0, direction.Z).Unit
		bodyGyro.CFrame = CFrame.lookAt(cat.PrimaryPart.Position, cat.PrimaryPart.Position + direction) * rotationOffset
		previousPosition = currentPosition  -- Move this line inside the check
	end

	local targetPosition = humanoidRootPart.Position + offset
	bodyPosition.Position = targetPosition
end)

did not work

char 30 limit!!!

1 Like

Have you tried having the cat unanchored or anchored? Also make sure primarypart is setup right.

3 Likes

When I unanchored it it worked, but I had to turn collisions back on as it won’t work when its off. Is there away to get it to work without having to turn off collisions?

1 Like

I edited the script: try it.

local cat = script.Parent

-- Ensure the cat model has a PrimaryPart set
if not cat.PrimaryPart then
	warn("PrimaryPart not set for cat model")
	return
end

-- Add AlignPosition to the PrimaryPart
local alignPosition = Instance.new("AlignPosition")
alignPosition.MaxForce = 50000
alignPosition.Responsiveness = 200
alignPosition.Parent = cat.PrimaryPart

-- Add AlignOrientation to the PrimaryPart
local alignOrientation = Instance.new("AlignOrientation")
alignOrientation.MaxTorque = 4000
alignOrientation.Responsiveness = 200
alignOrientation.Parent = cat.PrimaryPart

-- Define target position and orientation
local targetPosition = Vector3.new(2, 2, -2)  -- Adjust the offset as needed
local targetOrientation = CFrame.Angles(0, math.rad(-80), 0)

game:GetService("RunService").Stepped:Connect(function()
	-- Update position and orientation targets
	alignPosition.Position = targetPosition
	alignOrientation.CFrame = targetOrientation
end)

2 Likes

Since the body movers use physics, it needs physics to move.
Anchored makes a part stand still in its position, physics will then have no effect on the part.

Are you trying to make the cat not collide with the player character?
Then you should, rather than disabling collisions, create a collision group for the player and the cat and make these collisiongroups not interact, so they, the cat and the player, do not interact.

To do this easily (without need for much additional scripting), consider using the collision group editor studio plugin.

Add a group for the cat and for the player, make both interact with Default, make them not interact with eachother.
Add the collisiongroup for the cat to the cat and make a script to add the player collision group to the player.

3 Likes

The only issue with this solution is that I am going to have multiple cats in the game and would need to make alot of collision groups. Also I am going to have the same ones repeatedly I don’t know if this would cause any problems?

1 Like

This did not work sadly

limited char

You can make each cat in the same collision group.

You can make it so the cats don’t touch eachother either if you want to.
Then you just disable collision with the own collision group.

Let’s say you have collision group Cat and Player:

Cat has collision with Default
Cat has no collision with Cat
Cat has no collision with Player

Player has collision with Default
Player has no collision with Cat
Player has collision with Player

Oh yeah, if you’ve played some Roblox games and realise they don’t let characters touch eachother, then the characters are in a collision group that doens’t interact with itself, similar to how the cats in the example I just gave works.

2 Likes

Alright, Do I make separate groups for each cat as they are named something else? Or just make one and call it cat? And what script you meaning to add collision group to player? If there any good tutorial videos on this so i can see a demostration that would be helpful.

First time using collision groups thanks for any help in advanced

1 Like

You make one group and call it “Cat”, you make another group and call it “Player”.


An example is available in the documentation for Collisions.
I’ll take a little code snippet from there to show you how it would work with your collision groups:

local Players = game:GetService("Players")
local function onDescendantAdded(descendant)
	-- Set collision group for any part descendant
	if descendant:IsA("BasePart") then
		descendant.CollisionGroup = "Player"
	end
end
local function onCharacterAdded(character)
	-- Process existing and new descendants for physics setup
	for _, descendant in character:GetDescendants() do
		onDescendantAdded(descendant)
	end
	character.DescendantAdded:Connect(onDescendantAdded)
end
Players.PlayerAdded:Connect(function(player)
	-- Detect when the player's character is added
	player.CharacterAdded:Connect(onCharacterAdded)
end)
1 Like

I got it working! Thanks for your help so far, but when I walk through the cat model the camera acts like it is still a part with collisions. How could I fix this?

1 Like

The camera uses raycasts using the default collision group as far as I know, I don’t think you can fix this unless you make another collision group for all of the parts in the map, then make this collisiongroup interact with the cat and the default collision group, rather than having the cat interact with the default collision group.
This is far more work though and won’t work along with Terrain.

A better solution would be forking the camera script and make it use a separate collision group that doesn’t interact with the cat collision group, but does interact with the default collision group, but still, that’s a lot of work for a beginner.

1 Like

Thank you for all your help!!!

1 Like

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