Any way to prevent fliping with look at CFrame?

So right when the Goal object crosses over the Eye object does a flip. Anyway to prevent that, so it just rolls further keeping look at Goal?

Code:

local Eye = workspace.Eye;

local Goal = workspace.Goal;

local runService = game:GetService("RunService")

runService.Heartbeat:Connect(function()

Eye.CFrame = CFrame.new(Eye.CFrame.Position, Goal.CFrame.Position)

end)

You can ignore certain axis of rotation by changing the lookvector of the CFrame. For example, you could multiply that last vector by Vector3.new(1,0,1) and that would cause the part to ignore changes on the Y axis as it moves. Though since you are using position rather than look direction here, you may also need to add back the vector as a constant + Vector3.new(0,Eye.Position.Y,0)

Hmmm… but i do not want to restrict to some particular axis

You have to make sure one particular axis is exactly the same(in this case, the blue axis, which I think is the z axis). Make sure both values are the same, this should theoretically not make it flip.


Another option is to use math.clamp to clap the axis.

1 Like

So the reason this happens is because that CFrame constructor has to make some assumptions in order to properly function.

The biggest of those assumptions is that the unit direction vector between your eye and goal is not Vector3.new(0, 1, 0). If it is, then it snaps to a default rotation and I can assure you that looks worse/more abrupt than what you’re showing in your video. You can see if you are able to get the goal postion EXACTLY above the eye position.

If you want to have it work as described you’re going to need to do some math.

The trick is to adjust by the rotational delta of the current look vector and the desired look vector. I have discussed how to do this before as found in this post. I have purposefully not included the function in the code snippet below because I want you to actually read the post I just linked.

local UNIT_X = Vector3.new(1, 0, 0)
local UNIT_Z = Vector3.new(0, 0, 1)

local eyePart = workspace.EyePart
local goalPart = workspace.GoalPart

eyePart.CFrame = CFrame.new(eyePart.Position, goalPart.Position)

game:GetService("RunService").Heartbeat:Connect(function(dt)
	local eyeCF = eyePart.CFrame
	local delta = getRotationBetween(-UNIT_Z, eyeCF:PointToObjectSpace(goalPart.Position).Unit, UNIT_X)
	
	eyePart.CFrame = eyeCF * delta
end)

Good luck!

7 Likes

Off topic, but had to inform you that this had me giggling

2 Likes

Big thanks. Im currently reading ur POST. Btw is there a way to prevent the eye from rotating in Z (blue) at all? It eye perfectly rotates to the goal, but that angle is screwed up after some moving.