Correctly make 2D SurfaceGui face look at another entity?

I’m trying to achieve making a face look towards an entity. The behaviour of the facial movements is identical to some 2D games where they look at the mouse’s cursor or at another entity (I can’t think of an example as I have forgotten many games.) I also want the behaviour of it to work well with the entity’s current rotation.

I’ve successfully achieved the first half of the process:

But failed on the rotation part:

Sorry if the movement of the faces were subtle, but you can see on the second video that the eyes are looking somewhere else when rotated.

I’ve used CFrames to get the LookAt Vector3 value of the two via their positions, and used only the X and Y (because again, 2D). To be honest, I’m weak at CFrame math, usually not using them, and often relying on tutorials. The only thing I’ve tried right now is using the entity’s Orientation, add to the LookAt value, and get the .Unit value, but that did the opposite as now I just have a face that gets centered once I rotate it.

Here’s my far-from-finished-and-overly-inefficient code:

local AmountOfMovement -- Unused yet. For max radius.
local Smoothness = 5 -- Unused yet. To smoothen movement.

local LookingAt = {} -- Unused yet. For multiple entities.

function FocusAtNeighbouringBlock()
	local Origin = script.Parent.Parent.Position
	local Target = script.Parent.Parent.Parent.Target.Position
	local Rotation = script.Parent.Parent.Orientation
	
	local CFrameLookAt = CFrame.new(Origin, Target).LookVector.Unit
	
	script.Parent.FaceG.LeftEye.Position = UDim2.new(0.5, -75 + (15 * CFrameLookAt.X), 0.5, -15 * CFrameLookAt.Y)
	script.Parent.FaceG.Mouth.Position = UDim2.new(0.5, 7 * CFrameLookAt.X, 0.5, -7 * CFrameLookAt.Y)
	script.Parent.FaceG.RightEye.Position = UDim2.new(0.5, 75 + (15 * CFrameLookAt.X), 0.5, -15 * CFrameLookAt.Y)
end

while true do
	wait(0.1)
	FocusAtNeighbouringBlock()
end

What should I do to get this working correctly? Am I missing something?

Thanks in advance.

2 Likes

Simply rotate the SurfaceGui opposite of original Rotation, like make it static.

1 Like

Btw it looks so cool ngl, love that style.

2 Likes

By Rotation you mean the Rotation property of the face?

Because if so then I’m not trying to rotate the face so it looks like it is straight. I want the faces to, let’s say “move closer” to another entity to give an impression of the face looking towards it. I can’t explain real good so here’s a gif that I crudely animated using Pivot Animator, which took me a few minutes + a year of struggling Windows to let me install it:

Test

On the gif above, the face doesn’t change rotation, the part does, yet the face will try to look at the blue ball by moving its face closer. I don’t want it to oppose its parent’s Orientation.

Sorry if I took too long.

if the image is on the top surface why not just rotate the part using CFrame.new(currentPos, enemyPos)? or did i misunderstand what you needed.

No he want do thing like cube facing at point no Matter what rotation like real life head.

I’m not trying to make a friendly vs. enemy type of game. It’s an aesthetic feature for an interactive physics puzzle game that I’m developing. They all are affected by physics, so what I need is to make the faces look at another entity (or move closer to others.)

I’ve found the solution:

  1. Get LookAt/Difference Vector of Origin and Target.

  2. Convert X and Y to angle in degrees, and add Z-axis of parent entity’s Orientation property.

  3. Convert back to vector values, and get normalized values.

local Ascendant = script.Parent.Parent
local FaceG = script.Parent.FaceG

local Rotation = Ascendant.Orientation

local Origin = Ascendant.Position
local Target = Ascendant.Parent.Target.Position

local LookDiff = Origin - Target -- Get Difference/LookAt

local Deg = math.deg(math.atan2(LookDiff.X, LookDiff.Y)) + Rotation.Z -- Turn to angle + Z Rotation of parent entity

local Look = -Vector3.new(math.sin(math.rad(Deg)),math.cos(math.rad(Deg)), 0 ) -- Transform back to X, Y, 0

With this code, I can finally produce the behaviour I wanted: