Overview
As a game developer, it is important to have feature parity between Player Characters and Non-Player Characters (NPCs). There is currently a gap in functionality related to character direction alignment. Player characters use Humanoid:Move(vec3, true) to orient the character independently of the move direction. The player, using shiftlock or being in first-person, will orient their character in the direction of their camera, regardless of their movement. This API is not usable on NPC’s as it specifically relies on the orientation of the camera (which NPCs do not have).
The Humanoid does have the setting Humanoid.AutoRotate which is seemingly used to disable the built-in humanoid rotation forces, allowing devs to implement their own rotation forces. This is not ideal because devs won’t be able to rotate NPC characters with the same exact forces, or with similarly easy to use API’s as Player Characters.
Usecases
In my swordfighting game, players use shiftlock to face their characters in the direction of their cameras, allowing for facing their targets while moving, and giving fine-control over the direction of their sword swings. I am not able to make NPC’s that have the same exact functionality as player characters. This is is upsetting. Regardless of my parity and strafing usecases, the biggest usecase is to orient a non-moving character, such as to face the direction they are speaking.
Suggested API Request
Humanoid.FaceToPoint: Vector3?Humanoid.FaceToPart: BasePart?Humanoid:FaceTo(point: Vector3, part: BasePart?)
These APIs match the paradigm currently set by Humanoid.WalkToPoint, Humanoid.WalkToPart, and Humanoid:MoveTo(). It is expected that the two properties will automatically be set by the Humanoid:MoveTo() function unless Humanoid.AutoRotate is set to false. The rotational forces should only be applied in humanoid states that allow players to rotate their characters.
Ugly Workaround
To understand my struggles more, I am sharing some of the code that I use to try to emulate this functionality in my sword fighting game. It is not ideal since the rotational forces in player characters and NPCs do not match. My code also does not take into account the current humanoid state, so there is more code that needs to be developed to make progress towards PC and NPC parity.
function Bot:FaceTo(faceToPos)
if not (self.Humanoid and self.Character and self.Character.Parent and self.Character.PrimaryPart) then
return
end
self.Humanoid.AutoRotate = false
--self.Character:PivotTo(CFrame.lookAt(selfPos, selfPos + flatAttackVec)) -- Always face the target -- has stuttering problems
local bodyGyro = self.Character.PrimaryPart:FindFirstChild('BotFaceToBodyGyro')
if not bodyGyro then
bodyGyro = Instance.new('BodyGyro')
bodyGyro.Name = 'BotFaceToBodyGyro'
-- These values are guesses, after many manual observations and changes
bodyGyro.MaxTorque = Vector3.new(0,1,0) * 4000000
bodyGyro.D = 5--500
bodyGyro.P = 300000--3000
bodyGyro.Parent = self.Character.PrimaryPart
end
bodyGyro.CFrame = CFrame.lookAt(self.Character.PrimaryPart.CFrame.Position, faceToPos)
end
function Bot:MoveTo(goalPos, faceToPos: Vector3?)
if not (self.Humanoid and self.Character and self.Character.Parent and self.Character.PrimaryPart) then
return
end
if faceToPos then
self:FaceTo(faceToPos)
else
local bodyGyro = self.Character.PrimaryPart:FindFirstChild('BotFaceToBodyGyro')
if bodyGyro then
bodyGyro:Destroy()
end
self.Humanoid.AutoRotate = true
end
self.Humanoid:MoveTo(goalPos)
end

