CFrame based NPC walking going crazy

Okay. Basically I've been working on a CFrame based walking system for NPCS. Now, You may be asking why CFrame based? well here's 3 reasons why.

Reason 1.
The risk of an NPC glitching out or getting stuck is literally null since, You don't aren't relying on physics to move your NPC
Reason 2.
You don't have to worry about NetworkOwnership and exploiters being able to mess up the NPC. Unless there's a backdoor in your game, I think you should check your game for backdoors. I recommend searching for scripts named "Fix", "Weld" or "Anticheat"
Reason 3.
You can make your NPC go as fast as you want. No overshooting, Jittering, etc.

The issue:

I'm trying to make it so that the NPC faces in the direction it is walking. When I put 0 as the Y value of the direction Vector3 it teleports into interstellar space (literally). If I don't do that, It looks at the ground.

The code that's being annoying:

 local function restockerGoTo(pos)
	local path = pathfindingService:CreatePath({
		AgentRadius = 5;
		Costs = {
			DoorMass = math.huge
		}
	})
	path:ComputeAsync(restockerNPCHum.RootPart.Position, pos)

	for i, v in ipairs(path:GetWaypoints()) do
		local direction = (restockerNPCHum.RootPart.Position - v.Position)
		direction = Vector3.new(direction.X, 0, direction.Z)
		local calculatedTime = (direction.Magnitude/restockerNPCHum.WalkSpeed)
		local goalPosition = v.Position + Vector3.new(0, restockerNPCHum.HipHeight, 0)
		local calculatedCFrame = CFrame.new(goalPosition, restockerNPCHum.RootPart.Position - direction)
		local tween = tweenService:Create(restockerNPCHum.RootPart, TweenInfo.new(calculatedTime, Enum.EasingStyle.Linear), {CFrame = calculatedCFrame})
		tween:Play()
		tween.Completed:Wait()
	end
end

> Yes, I went through the trouble of making the post look nice with HTML.

2 Likes

Use CFrame.LookAt() constructor using the current position of the NPC and the lookat being the next position then squash the Y value of the next position.

local charPos = char:GetPivot().Position
local lookAt = goal.Position * Vector3.new(1,0,1)
char:PivotTo(CFrame.LookAt(charPos, lookAt)) --This will turn the char to face the goal position
2 Likes

Ooh, I never knew :GetPivot() existed.
Anyways I’ll try this thank you so much!

np. Yeah the new pivot stuff is nice. It sort of replaces the “GetPrimaryPartCFrame()” and it uses the new pivot point property of the model/part.

Is it a beta function? I never saw a post about it.

Nope not that I know of. I’ve been using it alot lately. PVInstance | Roblox Creator Documentation

Whoops! There’s a small error here…

1 Like

I forgot the wrap the position values in the the CFrame.LookAt. I’ve updated the script I posted. Sorry about that.

Oh, My bad I typed it wrong. (i dont like the chars limit)

It’s actually working!
Well, Kinda. It’s just looking towards the goal but the tweening is messing it up… I gotta go to bed, I’ll figure this out tomorrow. GN.

Again, Thanks for the help.

1 Like

Put the CFrame update into the renderStep at a priority after the character is updated. That should solve the tween issue.

1 Like

No, The issue is that the CFrame rotations are different.

If i add even the SLIGHTEST angle to the calculatedCFrame variable, And then equip a tool, This happens.
image

Do the CFrame orientation change AFTER the tween not inside it. In the tween just update the position.

1 Like

But the question is, Why does it go to the third universe when it equips a tool?

I have no idea why the tool is affecting it. It really shouldn’t. Honestly now that I think about it, there really no good reason why you can’t tween the position and rotation at the same time. It will just turn as it moves

1 Like

It just went to the 4th universe after I did what you said… Should I report this bug to roblox?

1 Like

image

1 Like

Post your updated code. Maybe something isn’t quite right.

1 Like
local function restockerGoTo(pos)
	local path = pathfindingService:CreatePath({
		AgentRadius = 5;
		Costs = {
			DoorMass = math.huge
		}
	})
	path:ComputeAsync(restockerNPCHum.RootPart.Position, pos)

	for i, v in ipairs(path:GetWaypoints()) do
		local direction = (restockerNPCHum.RootPart.Position - v.Position)
		direction = Vector3.new(direction.X, 0, direction.Z)
		local calculatedTime = (direction.Magnitude/restockerNPCHum.WalkSpeed)
		local goalPosition = v.Position + Vector3.new(0, restockerNPCSize.Y/2, 0)
		local calculatedCFrame = CFrame.new(goalPosition)
		local tween = tweenService:Create(restockerNPCHum.RootPart, TweenInfo.new(calculatedTime, Enum.EasingStyle.Linear), {CFrame = calculatedCFrame})
		tween:Play()
		tween.Completed:Wait()
		local charPos = restockerNPC:GetPivot().Position
		local lookAt = goalPosition * Vector3.new(1,1,1)
		local lookTowards = CFrame.lookAt(charPos, lookAt)
		restockerNPC:PivotTo(lookTowards)
	end
end

Edit: The code was cut off, Sry about that

2 Likes