What do you want to achieve?
I want to make the humanoidrootpart rotate only in the Y axis.
and how do I make hrp rotate using frames, when looking at the nearest player?
(I want to make hrp npc facing to the nearest player)
What is the issue?
The script does not detect the JointBone of hrp, which will be used to rotate the npc Y axis.
What solutions have you tried so far?
ive tried looking on the other model’s script and most of them are using R15 and neck bone, since im using R6 using Hrp Bone/cframe if that possible
local NPC = script.Parent
local neck = NPC.HumanoidRootPart.RootJoint
function getClosestPlayer()
local closest_player, closest_distance = nil, 30
for i, player in pairs(workspace:GetChildren()) do
if player:FindFirstChild("Humanoid") and player ~= NPC then
local distance = (NPC.PrimaryPart.Position - player.PrimaryPart.Position).Magnitude
if distance < closest_distance then
closest_player = player
closest_distance = distance
end
end
end
return closest_player
end
local cframe0 = neck.C0
while true do
local player = getClosestPlayer()
if player then
local is_in_front = NPC.PrimaryPart.CFrame:ToObjectSpace(player.PrimaryPart.CFrame).Z < 0
if is_in_front then
local unit = -(NPC.PrimaryPart.CFrame.p - player.PrimaryPart.Position).unit
neck.C0 = cframe0 * CFrame.new(Vector3.new(0, 0, 0), unit) * CFrame.Angles(0, -math.rad(NPC.PrimaryPart.Orientation.Y), 0)
end
end
wait()
end
we could use unit vector and calculate the angle to rotate only on the y axis and applying the rotation using cframe angles also using task.wait is much better than wait
local NPC = script.Parent
local hrp = NPC:WaitForChild("HumanoidRootPart")
local neck = hrp:WaitForChild("RootJoint")
local function getClosestPlayer()
local closest_player, closest_distance = nil, 30
for _, player in pairs(workspace:GetChildren()) do
if player:FindFirstChild("Humanoid") and player ~= NPC then
local distance = (hrp.Position - player.PrimaryPart.Position).Magnitude
if distance < closest_distance then
closest_player = player
closest_distance = distance
end
end
end
return closest_player
end
local cframe0 = neck.C0
while true do
local player = getClosestPlayer()
if player then
local is_in_front = hrp.CFrame:ToObjectSpace(player.PrimaryPart.CFrame).Z < 0
if is_in_front then
local targetPosition = player.PrimaryPart.Position
local direction = (targetPosition - hrp.Position) * Vector3.new(1, 0, 1)
local unit = direction.Unit
local angle = math.atan2(unit.X, unit.Z)
neck.C0 = cframe0 * CFrame.Angles(0, angle, 0)
else
neck.C0 = cframe0
end
end
task.wait(0.1)
end
thx for the help, but i think i might get the wrong axis, how do i change it to other axis, ive tried replacing the Z with Y not working
btw how do i make it that it doesnt check the player should be infront of the npc to rotate
i made a config for you , you can adjust these as much you want i made it support all axes if you set the rotationaxis values to 0 there would be no rotation on that axis for 1 would be full rotation values between 0 and 1 would be partial rotation i currently set it to roatate only on the y axis for example all axes would be x = 1 , y = 1 ,z = 1
local NPC = script.Parent
local hrp = NPC:WaitForChild("HumanoidRootPart")
local neck = hrp:WaitForChild("RootJoint")
local config = {
rotationAxis = {X = 0, Y = 1, Z = 0},
maxDistance = 30,
updateInterval = 0.1,
checkInFront = false
}
local function getClosestPlayer()
local closest_player, closest_distance = nil, config.maxDistance
for _, player in pairs(workspace:GetChildren()) do
if player:FindFirstChild("Humanoid") and player ~= NPC then
local distance = (hrp.Position - player.PrimaryPart.Position).Magnitude
if distance < closest_distance then
closest_player = player
closest_distance = distance
end
end
end
return closest_player
end
local cframe0 = neck.C0
local function getRotationCFrame(direction)
local rotX = config.rotationAxis.X ~= 0 and CFrame.fromAxisAngle(Vector3.new(1, 0, 0), math.atan2(direction.Y, direction.Z) * config.rotationAxis.X) or CFrame.new()
local rotY = config.rotationAxis.Y ~= 0 and CFrame.fromAxisAngle(Vector3.new(0, 1, 0), math.atan2(direction.X, direction.Z) * config.rotationAxis.Y) or CFrame.new()
local rotZ = config.rotationAxis.Z ~= 0 and CFrame.fromAxisAngle(Vector3.new(0, 0, 1), math.atan2(direction.X, direction.Y) * config.rotationAxis.Z) or CFrame.new()
return rotX * rotY * rotZ
end
while true do
local player = getClosestPlayer()
if player then
local shouldRotate = true
if config.checkInFront then
local is_in_front = hrp.CFrame:ToObjectSpace(player.PrimaryPart.CFrame).Z < 0
shouldRotate = is_in_front
end
if shouldRotate then
local targetPosition = player.PrimaryPart.Position
local direction = (targetPosition - hrp.Position).Unit
local rotationCFrame = getRotationCFrame(direction)
neck.C0 = cframe0 * rotationCFrame
else
neck.C0 = cframe0
end
end
task.wait(config.updateInterval)
end