I think you got the parameters mixed up. The first parameter should be the table you are setting the metatable of, and the second parameter is what to set the metatable to.
local self = setmetatable({}, classHere)
I think you got the parameters mixed up. The first parameter should be the table you are setting the metatable of, and the second parameter is what to set the metatable to.
local self = setmetatable({}, classHere)
Pretty sure I tried this before and it worked but I couldn’t use methods.
Well, it’s definitely the right way to use setmetatable()
. Did your class inherit methods or not? Can you send an example of code you used?
you’re setting the metatable the wrong way round, it should be table you want to give a metatable to, and then the metatable you are going to give to that table
I am not sure what you mean.
Also this is my full Module Script:
local BaseModule = script
local Module = {}
local Classes = {
Boid = {};
}
-- Services
local WorkService = game:GetService("Workspace")
local RunService = game:GetService("RunService")
-- Local
local Templates = BaseModule.Templates
-- Boid Class
function Module:NewBoid(Origin, Environment)
local NewBoid = setmetatable(Classes.Boid, {})
NewBoid.Environment = Environment
NewBoid.Body = Templates.Body:Clone();
NewBoid.Speed = 1;
NewBoid.Range = 15;
NewBoid.Fov = 0.5;
NewBoid.Enabled = true;
-- Body
NewBoid.Body.Parent = NewBoid.Environment
NewBoid.Body.Position = Origin
return NewBoid
end
function Classes.Boid:Update()
local LookDirection = self.Body.CFrame.LookVector
local BoidsInRange = {}
for BoidI, Boid in pairs(self.Environment:GetChildren()) do
if Boid:IsA("BasePart") then
local Sub = Boid.Position - self.Body.Position
local Distance = Sub.Magnitude
local LookDot = LookDirection:Dot(Boid.CFrame.LookVector)
if Distance <= self.Range and LookDot > self.Fov then
table.insert(BoidsInRange, Boid)
end
end
end
for BoidI, Boid in pairs(BoidsInRange) do
local Sub = Boid.Position - self.Body.Position
local Distance = Sub.Magnitude
local Ratio = math.clamp(Distance / 4, 0, 1)
LookDirection -= Ratio * Sub
end
self.Body.Position += (LookDirection / 4) * self.Speed
self.Body.CFrame = CFrame.lookAt(self.Body.Position, self.Body.Position + LookDirection)
end
function Classes.Boid:Destroy()
self.Body:Destroy();
self.Range = nil;
self.Enabled = nil;
self = nil
end
return Module
Do you mean something like:
setmetatable(Class, Class)
I tried that and it didn’t work.
I don’t see you using any metamethods, so what do you mean by “methods don’t work”? You might need to define subprograms within the class:
local class = {
["Function1"] = function()
end
}
but you also only have one class, so I don’t understand your Classes
table at the top. Seperate classes should use seperate modules.
local boid = {}
boid.__index = boid
boid.__newindex = function(tbl, key, value)
if rawlen(tbl) < 15 then
rawset(tbl, key, value)
else
warn("New indexes are not allowed.")
end
end
function Boid:MethodOne()
--do stuff
end
Also, the correct syntax of setmetatable
is as follows:
local something = {}
function something.hi()
end
local self = setmetatable({}, something)
print(self) --> {["hi"] = "function"}
Sorry, I really don’t understand metatables very well, I am not sure what meta methods are.
But I am pretty sure that I am using meta methods in this, like for example I have a method called “Update” that updates the boid’s position, isn’t that a method?
I know I am only using one class but the classes table just makes things more organized, also I don’t understand why every class has to be in a different module, can you explain please?
I tried searching up about metatables and what they do but all I saw was that meta tables are just fancy tables which was very confusing.
Boid
) should be in different modules - the whole point in an Object-Oriented approach (which we are doing) is to simplify and declutter code. Multiple classes per script means the code becomes more cluttered.Metamethods are methods that can change the way tables behave. Here is a post in Community Tutorials explaining more about it:
Metatables and Metamethods - Community Tutorials
Try just using one class per module, like this:
local module = {}
function module.MethodOne()
end
function module.MethodTwo()
function module.new()
local self = setmetatable({}, module)
end
I updated my code to this:
local BaseModule = script
local Module = {}
-- Services
local WorkService = game:GetService("Workspace")
local RunService = game:GetService("RunService")
-- Local
local Templates = BaseModule.Templates
-- Boid Module
function Module:New(Origin, Environment)
local NewBoid = setmetatable({}, Module)
NewBoid.__index = NewBoid
NewBoid.Environment = Environment
NewBoid.Body = Templates.Body:Clone();
NewBoid.Speed = 1;
NewBoid.Range = 15;
NewBoid.Fov = 0.5;
NewBoid.Enabled = true;
-- Body
NewBoid.Body.Parent = NewBoid.Environment
NewBoid.Body.Position = Origin
return NewBoid
end
function Module.Update(self)
local LookDirection = self.Body.CFrame.LookVector
local BoidsInRange = {}
for BoidI, Boid in pairs(self.Environment:GetChildren()) do
if Boid:IsA("BasePart") then
local Sub = Boid.Position - self.Body.Position
local Distance = Sub.Magnitude
local LookDot = LookDirection:Dot(Boid.CFrame.LookVector)
if Distance <= self.Range and LookDot > self.Fov then
table.insert(BoidsInRange, Boid)
end
end
end
for BoidI, Boid in pairs(BoidsInRange) do
local Sub = Boid.Position - self.Body.Position
local Distance = Sub.Magnitude
local Ratio = math.clamp(Distance / 4, 0, 1)
LookDirection -= Ratio * Sub
end
self.Body.Position += (LookDirection / 4) * self.Speed
self.Body.CFrame = CFrame.lookAt(self.Body.Position, self.Body.Position + LookDirection)
end
function Module.Destroy(self)
self.Body:Destroy();
self.Range = nil;
self.Enabled = nil;
self = nil
end
return Module
But it gives me an error saying:
attempt to call missing method 'Update' of table
I think it’s to do with your notation. Colon notation implicitely defines self
. You do not need it for the New
function.
You should also set NewBoid.__index
to Module
, but by simply doing
Module.__index = Module
at the top of your script it will inherit the __index metamethod.
__index is a table Lua will search for a missing method when a missing method is called. Here’s more information about self
and notation:
My code is working now, Thanks for helping me.
I don’t understand a lot of things but it’s working which is the important part lol.
It’s also very important to understand them. You should try to learn about them.
I am aware this post is solved but, what is the difference between using self
and local
?
From what I know, self is a variable that returns the table of a function.
For example:
local TestTable = {}
TestTable.Value = 5
function TestTable:Print() -- The self variable in this function is TestTable.
print(self.Value) -- Should print 5.
end
That is true but what stops us from just doing this
local value = TestTable.Value
function TestTable:Print()
print(value)
end
Because the value variable is a property of the TestTable, It just makes things more readable I guess, Here is a better example:
local Car = {}
Car.Name = "Lamborghini"
Car.Speed = 50
Car.Passenger = game.Players.zeyan200_gotdeleted
function Car:Activate()
-- Code that activates the car.
end
function Car:ToggleLights()
-- Code that toggles the lights of the car on and off.
end
function Car:Boost()
-- Code that gives the car a speed boost.
end
If we just did:
local Name = "Lamborghini"
local Speed = 50
local Passenger = game.Players.zeyan200_gotdeleted
It wouldn’t really make much sense because the speed variable is for this specific car,
Sorry I am not the best at explaining, I am still new to classes too.
self
is a variable used in OOP and OOP related programming to refer to the object you are currently using, since in OOP everything related to the object is in the object. You can refer to the post I made linking someone else’s explanation of it.
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.