Allowing NPC to rotate only at Y axis (Or connecting many NPCs to one Heartbeat connection)

I made NPC that looks at player, using AlignOrientation. The problem is that NPC can rotate along X and Z axes, and this is not what I want.

Is there a way to make this WITHOUT using a single loop or RunService connections? If it’s not, there’s another question: How can I make PERFORMANT usage of RunService.Heartbeat with many NPCs, so there’s only one connection, instead of creating new connection for every single NPC?

(A bit more info)
I’m making a comprehensive NPC AI system for my game. Every single NPC is realised through the main module script.

function module.new(npc: Model)
	local self = setmetatable(module, {})
	
	self.align = npc.PrimaryPart:FindFirstChildOfClass("AlignOrientation") -- Deleted everything in this constructor, expect this
	
	return self
end

There’s an AlignOrientation object, defined as self.align.

GetTarget() function got this:

self.align.Attachment1 = self.target.PrimaryPart.RootAttachment

It defines RootAttachment of the target for AlignOrientation.

It should rotate NPC so it can face player, but it also can rotate at X and Z axis, doing some weird flips.
SO, how i can make it rotate ONLY at Y axis?

1 Like

Hello! Can you condense what exactly your asking a little bit more? Are you asking for both the optimization and solution to your axis issue or one or the other? Please let me know then I’ll be glad to help!

1 Like

Hello, if it’s possible to do, then both of the issues.

You can probably use actors + a loop + BulkMoveTo for maximum efficiency. Unfortunately, I don’t think you can do this without loops or events.

1 Like

I’m guessing you could store all the npcs in a table and loop for them in one HeartBeat to make them look at you

Also quick correction:

I think you meant this:

local self = setmetatable({},module)--creates a new table with its metatable set to the module

I think about that too, but there are going to be many NPC’s in the game, using that amount of loops at the same time is very bad for performance

Isn’t for loop every heartbeat bad for performance? Also, i think setmetatable({}, module) gives an error:

Workspace.Rig.Script:4: attempt to call missing method 'Start' of table

Yeah probably if there is a lot of npcs yeah but then again there are people who make npcs with a lot of raycasting stuff in them that run in heartbeats or while wait() dos several times. I’m not saying that it’s good tho.

Perhaps you could skip a few Heartbeats, at least to a point where the extra latency isn’t noticeable
Like maybe uptdating the rotations like 3 times a second, instead of every heartbeat.

You could also make the npcs rotate towards you when they’re close to the player.

you probably didn’t set the module’s __index to be itself, without that, objects with their metatables set to your module won’t be able to inherit functions or other things from your module

Yeah, that would definetely work. I don’t think ~15 NPCs that updates 3 times per second and player can just kill them very fast (Their .new() sets to nil after death) will affect that much performance. Thanks!

You can just use collection service to get all the npc’s without hard searching through your game for them

Wait, how i can update NPCs? There’s a :Start() Function in module and there’s an AlignOrientation with Mode set to OneAttachment(Basically, instead of attachment0 look at attachment1 instance, attachment0 is looking to Vector3)

function module:Start()
    --this function needs to update NPC

	self:GetTarget() -- Temporarily
	local oldHealth = self.humanoid.Health
	self.humanoid.HealthChanged:Connect(function(newHealth: number)
		if newHealth >= oldHealth then return end
		self.states.lastDamage = tick()
		self:Retreat(self.target.PrimaryPart.CFrame.LookVector)
		
		if newHealth <= 0 then
			self.align:Destroy()
		end
	end)
end