How do I rotate an NPC?

I am trying to make a script that turns an NPC using tweenservice. I want it to face south every time the tween is played. Unfortunately, whenever I use orientation, it only rotates the humanoidrootpart, and not the entire NPC. I have also tried using CFrame, but it did not work as well. Here is my script:

local tweenservice = game:GetService("TweenService")
local root = script.Parent.HumanoidRootPart

local tweeninfo = TweenInfo.new(
	1, --Length
	Enum.EasingStyle.Sine, --Easing Style
	Enum.EasingDirection.Out, --Easing Direction
	0, --# of times Repeated
	false,--Tween Repeat
	0 --Delay between each tween

)

local tweenaction = {
	Orientation = Vector3.new(0,180,0)
}

local tween = tweenservice:Create(root,tweeninfo,tweenaction)

tween:Play()
2 Likes

Try rotating all the parts in the model I guess? I am not too familiar with this, but I am assuming that rotating an npc humanoid root part will not work because it does not function as a normal player character, instead it might act like just a normal model. If it does act like a normal character then I have no idea sorry.

If I am right about the npc acting like a normal part model then do something like this:

local tweenservice = game:GetService("TweenService")
npc = game.workspace.npcModel 

-- all ur tween setup code

for i, v in ipairs(npc:GetChildren()) do
    local tween = tweenservice:Create(v,tweeninfo,tweenaction)

    tween:Play

end

Sorry if there are any mistakes, I am on mobile rn and autocorrect makes this a pain.

I hope this works, but I am not sure if it does. Good luck and sorry if I am just completely wrong here!

1 Like

The only way to make an entire model (in this case, an NPC) face a certain direction is to use :SetPrimaryPartCFrame(), which doesn’t lend itself nicely to tweens. However, you can do a fun little thing where you create a dummy CFrameValue that updates the model’s CFrame as the value changes, and tween the dummy CFrame.

local TweenService = game:GetService("TweenService")
local dummy = workspace.Dummy

local cframe = Instance.new("CFrameValue") -- create dummy cframe
cframe.Value = dummy:GetPrimaryPartCFrame() -- set value to current cframe for smooth tween
cframe.Changed:Connect(function(value) -- connect dummy to a Changed function
	dummy:SetPrimaryPartCFrame(value)
end)

local info = TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.Out)
local action = {
	Value = CFrame.new(dummy.PrimaryPart.Position) * CFrame.Angles(0,math.rad(-90),0)
	-- play around with the CFrame.Angles part to get to the correct orientation you want
	-- currently it faces to the negative X direction
}
local tween = TweenService:Create(cframe, info, action)
tween:Play()
tween.Completed:Wait() -- wait for the tween to finish

cframe:Destroy() -- destroy the dummy CFrameValue to prevent memory leaks
2 Likes

I have not done much with CFrames, so I am wondering why you used Instance.new instead of CFrame.new? Is there a difference between the two ways?

Sorry that this is off topic, I am just trying to learn cframes

1 Like

Yes, so this is a matter of an Instance versus a variable. A variable can only be referenced in the code it was created in, but an Instance is a physical object that can be referenced anywhere (as long as you know its location). Creating a CFrameValue is the exact same thing as creating a new part with Instance.new("Part") You can even insert a CFrameValue while in studio with the explorer:

image

The reason why I chose a CFrameValue over a variable is because TweenService:Create() needs an Instance, not a variable (so you wouldn’t be able to tween otherwise)


(From the TweenService wiki)

Additionally, all Instances have the function GetPropertyChangedSignal() (or for Value instances .Changed which is used above) that can be used to call a function every time the Instance’s value changes.

With those two things combined, a CFrameValue is perfect for tweening a model because you can tween a single CFrame and use the Changed connection to smoothly moved the model. A variable with CFrame.new() simply couldn’t do either of those things and therefore won’t work for this case.

oh ok that makes sense thank you so much!