The humanoid would do an action when being close enough to the player.
The humanoid would walk backwards if the player gets closer.
What did I try doing?
I tried getting random position around the player and moving the humanoid to them, but it makes the humanoid walk randomly in front of the player’s face, back and forward, so that’s a big no-no.
I tried doing some weird magic tricks with Humanoid.Parent.LowerTorso.CFrame * CFrame.new(0, 0, -4.5)) - but that didn’t seem to work very well.
El’ Conclusion
What can I use (or do) to hit these objectives?
I am really bad with explaining maths, but hopefully you are able to understand. If you’re confused I suggest try reading up on the Unit Circle, I probably will not be able to help much more due to my inability to explain things coherently.
Get the direction between the Dummy and the NPC, then multiply a custom distance.
You can derive the direction using some basic trig. If you think about it, any two points in space can be represented using a triangle.
Sorry I am not the best artist, but here is a visualization. The side lengths are the absolute value of the corresponding components of our position subtracted.
Trust me when I say that the direction in the form of a vector to B from A is just (cos(theta), sin(theta)). I don’t know the terminology for what the product of (cos(theta) * d, sin(theta) * d), but essentially we are representing the points on a unit circle. Where A is the origin and B is a point on the circle.
Using this, we can say that the position the NPC needs to walk to is something along the lines of:
local A = Dummy.Position
local B = NPC.Position
local radius = 5
--// imagine we rotated the plane sideways, this makes Z the Y coordinate
--// IDK How to explain this but just trust me
local sideX = math.abs(A.X - B.X)
local sideZ = math.abs(A.Z - B.Z)
local direction = math.atan(sideY / sideX)
local directionX = math.cos(direction) * radius
local directionZ = math.sin(direction) * radius
--// assuming `A.Y` and`B.Y` are the same because they're on the same plane
local directionVector = Vector3.new(directionX, A.Y, directionZ)
local NCPPosition = CFrame.new(A, directionVector).Position