How to make an AI that moves away from the player, but still looks at the player

Currently, I’m trying to make an AI that moves away from the player, but still looks at the player.

Since I use the MoveTo() function when I have the AI move away from the player, I think it moves to a different position every time, meaning it wouldn’t look at the player, but instead facing where the new position is.

I’ve tried looking around the internet, but the post solution either doesn’t work with my script, or it is very glitchy. (It isn’t really as smooth as I would like it to be.)

Here’s the code I use to move the AI away from the player:

(By the way, Target is the HumanoidRootPart of the player’s character, RunDistance is just a number (10), and HumanoidRootPart is the AI’s HumanoidRootPart.)

local function RunAway()
	if Target ~= nil then
		local PositionDifference = Target.Position - HumanoidRootPart.Position
		local NormalizedDirection = PositionDifference.Unit
		
		Humanoid:MoveTo(HumanoidRootPart.Position + (Target.Position - HumanoidRootPart.Position) * -1 * RunDistance)
	else
		return nil
	end
end

Thank you for your help! This is my first forum post, so if anything isn’t clear, I can help explain it :slight_smile:

3 Likes

You can use Orientation

workspace.Rig.Head.Orientation = target.Head.Orientation

Also you should learn about Pathfindingservice so that if your NPC gets stuck between a wall or the player is too high, the NPC can still get to the player.

3 Likes

Thanks for your reply! But I’m looking for the ENTIRE AI’s body to face the player, not just the head. Any way I can do that?

3 Likes

Yeah the whole body should look at it too. It’ll move with the head. If it doesn’t work use cframe.lookat()

1 Like

Can you show an example piece of code for the CFrame.lookAt() part? Sorry, I can’t figure it out :frowning:

1 Like

That’s okay!

workspace.Rig.HumanoidRootPart.CFrame = CFrame.LookAt(workspace.Rig.HumanoidRootPart.Position, workspace.Part.Position)
1 Like

It works, but is there a way to make it smoother? It takes a slight second to update and look at the player, plus it messes with the movement code a little bit.

1 Like

I guess you can try using TweenService or you can do this AI stuff on the clients’ side which may be smoother than the server.

1 Like

It tried it out, but it was still glitchy. And to clarify, this is in a LocalScript, which I think means it runs on the clients’ side.

Here’s the code I used if you’re curious:

local direction = (HumanoidRootPart.Position - Target.Position).Unit
local targetPosition = HumanoidRootPart.Position - (direction * RunDistance)

local tweenInfo = TweenInfo.new(
	2,
	Enum.EasingStyle.Linear,
	Enum.EasingDirection.Out,
	0,
	false,
	0
)

local tween = game:GetService("TweenService"):Create(
	HumanoidRootPart,
	tweenInfo,
	{Position = targetPosition}
)

tween:Play()
1 Like

You could use align orientation to orientate it physics wise. Otherwise a runservice heartbeat loop with CFrames could do the trick as well.

Eitherway the key is disabling humanoid autorotate which may interfere with the manual orientation alignment.

I tried using AlignOrientation, (because that seemed like the one that would work best with my code,) but disabling humanoid AutoRotate seems to not let my AI rotate at all for some reason. Is there a reason why for this, or is my code just broken? (I saw the code on a forum post while searching)

local AlignOrientation = Instance.new("AlignOrientation")

AlignOrientation.CFrame = CFrame.new(HumanoidRootPart.Position, Target.Position)
AlignOrientation.Parent = HumanoidRootPart

This is the second time I have seen you not only misinterpreting what the poster wanted, but providing deprecated methods. Please only provide help if you actually can.

As for the original post, the Model or Actor that contains the NPC can be rotated by using the Pivot to function.

Model:PivotTo(CFrame.new(CurrentCFrame, TargetPosition))
The target position will be where it will look at.

You must disable Humanoid.AutoRotate when you are running this code, and re-enable it when you are not.

Thanks for your help! I just have one question, though. What is the value of “CurrentCFrame”? (An example situation to define it is fine)

Disable the Humanoid property AutoRotate. This makes the AI not rotate its body in the direction it moves

I’m currently using that, I’m just trying to figure out nice and smooth code that will actually rotate the AI to face the player.

The smoothest you can have is a physics constraint, but those can fail for seemingly Jo reason. So the next best option is to set the CFrame of the AI’s Root part

You can use cframe.lookalong or cframe.lookat to get the cframe, and lerp for smoothness

That’s interesting! I’ve tried it out (see code below), but I’m not the best at CFrame.lookat or Lerp. It works fine, but my AI waits for a split second, then faces the player and teleports to a location. Is there any way to improve on this piece of code? Thank you for the idea though! It seems really helpful :slight_smile:

local LookAt = CFrame.lookAt(HumanoidRootPart.Position, Target.Position)
local Alpha = 0
local InterpolatedCFrame = LookAt:Lerp(Target.CFrame, Alpha)
				
HumanoidRootPart.CFrame = InterpolatedCFrame

Your alpha is how much you want to interpolate it. If alpha is 0, you get the first cframe. If alpha is 1, you get the second cframe. If alpha is between, you get a cframe between both cframes

You would want to lerp your humanoid root part’s cframe with the LookAt CFrame