How does this work

I have been looking through a module for dynamic smoke, and I understand most of it but have gotten stuck with this:

export type VoxelModel<T> = {
	CreateVoxel: (self: VoxelModel<T>, Position: Vector3, Distance: number, CheckPosition: boolean) -> Voxel?,
	ExpandVoxel: (self: VoxelModel<T>, Voxel: Voxel) -> (),

	ShootVoxels: (self: VoxelModel<T>, StartPoint: Vector3, EndPoint: Vector3, Thickness: number) -> (),

	Clear: (self: VoxelModel<T>) -> (),

	Radius: number,

	LifeTime: Vector2,
	BurstSpeed: Vector2,

	Resolution: number,

	Model: Model,

	Voxels: {}
}

local VoxelModel = {}
VoxelModel.__index = VoxelModel

local function CreateVoxels<T>(Radius: number, Resolution: number, LifeTime: Vector2, BurstSpeed: Vector2):VoxelModel<T>
	local self:VoxelModel<T> = (setmetatable({}, VoxelModel) :: unknown) :: VoxelModel<T>
	self.Radius = Radius
	self.Resolution = Resolution

	self.LifeTime = LifeTime
	self.BurstSpeed = BurstSpeed

	self.Voxels = {}

	local Model = Instance.new("Model", workspace)
	self.Model = Model

	return self
end

local VoxelModel:CreateVoxel()
      --stuff here
end
--other functions also here

I am sort of confused at what exactly is happening, but have a general idea. The local VoxelModel is used to define functions that are somehow used by the VoxelModel type, im just confused about how they got there Any clarification on this would be great.

1 Like

What even is your question? This is just a way of type annotating Luau OOP.

Also, the subtype T for the generic VoxelModel<T> doesn’t appear to be used either, so it is just being passed around for no reason(?)

Sorry, like I said this is not my module, so I don’t really understand it all too well either. I am specifically wondering what

local VoxelModel = {}
VoxelModel.__index = VoxelModel

and the functions stored in it is for

The reason I posted this is because this seemed to complicated, and I think you are agreeing, but correct me if I am wrong

That is just a common way to write OOP-style code in Lua.

The function stored inside VoxelModel are the methods for the objects. Because the VoxelModel table is a metatable for them, the created objects will automatically inherit those methods.

In the example below, the entire class t is also the metatable for any objects of t class. This means those objects will inherit the foo() function and it becomes accessible from the objects themselves, allowing you to call foo by doing object.foo(object) or object:foo()

local t = {}
t.__index = t --t is a metatable and also the class table

t.foo = function(self) --this is a method for the object
    print(self.value)
end

local object = setmetatable({}, t) --create a new object as {}, and then use the class table as the metatable
object.value = 123
object:foo() --> this will print 123

--you can verify that foo() is indeed inherited by printing the function
print(object.foo)
--and then compare the memory address with the one inside the metatable:
print(t.foo)
--they should be the same!

You can learn more specifically about that in many other threads:


And then here’s a guide on the type annotations which the module also has:

Oh, I get how thats a metatable now, thanks

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