NPC OOP Struggles

So I started a new Project with the intentions of making the structure on OOP, I started with a constructor and I’m having issues with the methods not taking the personal object’s table and instead the constructor’s. Would anyone have a solution to this?




image

3 Likes

why do you have functions for things that are a single line

2 Likes

I have them as getter methods to be more organized

1 Like

Few questions:

  1. Why are writing getter and setter methods… this feels like you’re trying to turn LuaU into Java; there are no existing “protections” in place against modifying the module remotely… so might aswell just do it.
  2. You aren’t returning the new as an actual instance to when it’s called, so when you are running start it is running the generic rather than a self. You aren’t assigning the self either which is strange, so it only will behave within the constructor.

Like if you want to do OOP, it should be formatted like this:

function CharacterMovement.new(player: Player, characterInstances: {humanoidRootPart: BasePart, torso: BasePart, humanoid: Humanoid, leftShoulder: Motor6D, rightShoulder: Motor6D, neck: Motor6D, hold: Motor6D})
	local self = setmetatable({}, CharacterMovement)

	self.player = player
	self.humanoidRootPart = characterInstances.humanoidRootPart
	self.torso = characterInstances.torso
	self.humanoid = characterInstances.humanoid

	self.leftShoulder = characterInstances.leftShoulder
	self.rightShoulder = characterInstances.rightShoulder
	self.neck = characterInstances.neck
	self.hold = characterInstances.hold

	self._setTiltDebounceTime = TILT_DEBOUNCE_TIME
	self._lastSetAngle = 0
	self._currentAngle = 0

	return self
end

Where you actually are declaring the self and blah blah blah. Probably is why you have the whole not applying to the object thing. This is entirely just for sake of readability and comprehendability at-least for the defining it as self, but the return part definitely is a source of questioning.

5 Likes

You’re prolly not setting the metatable on the returned object correctly. Make sure your constructor does setmetatable(self, NPC) where NPC has __index = NPC, not just returning the raw table. If your methods are defined on the module table but __index isnt pointing there, the instance wont find them and itll fall back to the base table. Hard to tell exactly without seeing the full constructor but thats the most common cause. Lua isn’t OOP the way you think of Java or C++ as OOP. It’s prototype based inheritence rather than class based. So all new objects by default inherit the prototypes memory space.

1 Like

Well…you could use enclosures if you really want to keep the guts of a module private. But then you can’t use metatables. If you are using a factory pattern and backing it up with a lookup table…technically possible. Why a person would do this is another question. But I’ve used it once in awhile in both Lua and Javascript. Personally hate prototype inheritence, but it is what it is.

1 Like

I don’t believe it’s an issue like that. I understand that lua isn’t suppose to be treated exactly like Java, I had this commission where this guy had a similar coding style to that of Java and it inspired me to do the same. Is there anyway you can see with this new information of a way where I could make the functions in NPC take the maniac table as self?

If you’re looking to inherit NPC’s properties and methods you could do something like this

  • NPC would stay the same
  • Maniac would be like this
local NPC =  require(script.Parent)

local PoliceOfficer = {}

PoliceOfficer.__index = setmetatable(PoliceOfficer, NPC) -- Different to what you have

function PoliceOfficer.new()
	local self = setmetatable(NPC.new(), PoliceOfficer) -- Different to what you have

	return self
end

return PoliceOfficer

Now you could do Maniac.new():setTarget(workspace.Model)

2 Likes

whatever you do, do not use @ABC2gameYT solution / idea, that is literally horrible, you shouldn’t do Subclasses in Luau, switch to DOD in that case

1 Like

Everyone on here thinks they know what’s best. Just do what works for you and makes it easy for you to build off, that’s what really matters.

I’m not sure if this is the issue, since I see other issues that others here have already pointed out, but I see you using both periods “.” and colons “:” to define methods (functions in Lua but logically methods since bound to an object instead), I had an embarrassing couple weeks where I defined them using periods or colons and then calling them after defining an object using the opposite and that resulted I think in a call to the class that had no concept of “self” and so had none of my member methods defined.

Again, I’m a little fuzzy on the details but just thought I’d let you know there are some risks in how its called even if defined correctly. Maybe someone else would have more recent experience with similar issues.

1 Like

How example say I have the Queue Class

Queue.__index = Queue

function Queue:new()
	local obj = { data = {}, front = 1, back = 0, size = 0 }
	setmetatable(obj, self)
	return obj
end

function Queue:enqueue(value)
	self.back = self.back + 1
	self.data[self.back] = value
	self.size = self.size + 1
end

function Queue:dequeue()
	if self.size == 0 then return nil end
	local value = self.data[self.front]
	self.data[self.front] = nil -- Optional: Clear memory
	self.front = self.front + 1
	self.size = self.size - 1
	return value
end

function Queue:peek()
	return self.size > 0 and self.data[self.front] or nil
end

function Queue:isEmpty()
	return self.size == 0
end

function Queue:getSize()
	return self.size
end

-- Get a copy of the Queue (note preserves order but not start and end indices)
function Queue:copy()
	local newQueue = Queue:new()
	for i, val in pairs(self.data) do
		newQueue:enqueue(val)
	end
	return newQueue
end

return Queue

Then I can do


local q = Queue:new()

q:enqueue("A")
q:enqueue("B")
q:enqueue("C")

and it will throw no errors but if I do


local q = Queue:new()

q.enqueue("A")
q.enqueue("B")
q.enqueue("C")

the “ship” has hit the fan and we get

  13:02:38.843  Stack Begin  -  Studio
  13:02:38.843  Script 'ServerScriptService.Queue', Line 11 - function enqueue  -  Studio - Queue:11
  13:02:38.843  Script 'ServerScriptService.Script', Line 5  -  Studio - Script:5
  13:02:38.844  Stack End  -  Studio```

You’re right on that, I do use them later on from this ss. Thank you for the feedback

NP, I hope you project proceeds smoothly

Abandon OOP entirely. Eat ze bug

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.