Setmetatable to an Instance in Roblox

So I tried to do this by using setmetatable():

local zombieModel = script.Parent

local Zombie = {}
Zombie.__index = Zombie

function Zombie.new()
    local newZombie = zombieModel:Clone()

    setmetatable(newZombie, Zombie)

    return newZombie
end

return Zombie

But I got this error:
ServerStorage.Zombie.ZombieModule:8: invalid argument #1 to ‘setmetatable’ (table expected, got Instance)
Is there any way to fix this?

1 Like

the newZombie variable is an instance (i.e a model in your case), but setmetatable requires tables. You can fix this by doing something simple like so:

setmetatable({model = newZombie}, Zombie})
1 Like

I think it’s not quite right, cuz if I do this, I cannot use other functions of this class. Here is the whole script:
GameManager

local Zombie = require(game.ServerStorage.Zombie.ZombieModule)
local RunService = game:GetService("RunService")

local currentTime = 0
RunService.Heartbeat:Connect(function(deltaTime)
    currentTime = currentTime + deltaTime
    print(currentTime)
    local newZombie
    if currentTime > 10 then
        newZombie = Zombie.new()
        newZombie.Parent = workspace
    end

    if workspace:FindFirstChild("Zombie") then
        newZombie:Print("Brain Brain Brain")
    end
end)

ZombieModule

local zombieModel = script.Parent

local Zombie = {} 
Zombie.__index = Zombie

function Zombie.new()
    local newZombie = zombieModel:Clone()

    setmetatable({newZombie}, Zombie)

    return newZombie
end

function Zombie:Print(string)
    print(string)
end

return Zombie

I got this error after calling the Zombie:Print() function:
Print is not a valid member of Model “Workspace.Zombie”

2 Likes

I am not really clear about what you are really trying to do by passing an instance as the first argument to the setmetatable method.

local Zombie = {} 
Zombie.__index = Zombie 

function Zombie.new() 
    local self = setmetatable({} , Zombie)  
    self.template = zombieModel:Clone()

    return self ; 
    
end 

function Zombie:Print(s)
    print("Zombie says "..s) 
end 

--script
local module = -- path to module 
local zombie = module.new() 

zombie:Print("Hello") --> Zombie says Hello
1 Like

I just want to add some new functions to the zombie model. Is it possible to do that?

1 Like

You can add methods to the Zombie class itself then which may manipulate the model of the zombie,which in this case was referred to as the template of the zombie.

For example -
Imagine I want my zombie to have a method which destroys the zombie , in which case I can just do this-

function Zombie.new() 
    local self = setmetatable({} , Zombie)  
    self.template = zombieModel:Clone() 
    
    self.template.Parent = workspace 

    return self ; 
    
end 

function Zombie:Print(s)
    print("Zombie says "..s) 
end 

function Zombie:Die()
    self.template:Destroy() 
end
2 Likes

Alright! This one works well! By the way, I have a question: Is it possible to add more methods to a built-in Instance in Roblox?

As far as I know that is not possible as the Instances are programmed in another language other than Lua , most probably C++.
But that by no means does cause restrictions in our code in any way as you saw we can manipulate objects in other ways.

1 Like

in the Zombie.new() function, how come self works? I thought this was only allowed when a colon is used.

1 Like

You can use self as a variable name.

3 Likes

also to clarify, what exactly is happening here

self.template = zombieModel:Clone() 
    
    self.template.Parent = workspace 

by my understanding, self.template would create a table/list? or rather a dictionary where template is equal to the clone? im just a little confused by it all