How to use OOP/metatables with entities?

How would I use metatables to create entities and simulate their AIs? To my knowledge, other OOP languages usually have a .__process function to something similar which gets called each frame, and which I think would be the best way to program AI, unless there is a better way.

In a module script I have:

local EntityClass= {}
EntityClass.__index = EntityClass

function EntityClass.new()
	local instance = setmetatable({},EntityClass)
	
	return instance
end

-- creates a body for the entity
function EntityClass:CreateBody(entityId,pos)
	local entity = game.ServerStorage.Entities[entityId]:Clone()
	entity.Position = pos
	entity.Parent = workspace

	self.body = entity

	return entity
end

-- How would I simulate entity Ai?

return EntityClass

Some additional question about OOP I have:

  • I plan to have dozens of different types of entities. Do I make a class and a module for each type of entity that inherits from the entity class? Or is there a more efficient way to do it?
  • If I want to, for example, hit an enemy and apply damage to an entity, how would I call a function that is inside the EntityClass that handles damage?

Thanks all!

1 Like

I’d probably say just make a function in the module to handle damage, etc. and call it with the appropriate entity, because the entity itself will inherit these functions so they can be called with the entity itself.

For the AI, you could even use a seperate script. Or, just use a procedure in your current module.

function EntityClass.TakeDamage(entity, damage)
    --stuff goes here
end

function EntityClass.MoveEntity(entity)
    --movement code could go here
end

function EntityClass.new()
    local self = setmetatable({}, EntityClass)
    task.spawn(self.MoveEntity, entity)
end

Also yes, you should probably make a new class for each entity. It’d help to simplify the overall system.

I hope this helps :smiley: .

2 Likes

So I would have a script that handles where the entities are created, and give them a unique identifier so you know which entity is which.

--@@ Creating Entities
local Entities: { [string]: table } = {}

--> Creation:
local UniqueID = --> Can use a custom method or just HttpService:GenerateGUID()
local Entity = EntityClass.new()
Entity:CreateBody()

Entities[UniqueID] = Entity 

Now whenever you want to access this specific entity you could just use the unique id to do so.

As for taking damage that is pretty straightforward, in the script that handles the creation of the entity you would add a damage function and also add a damage function to the entity class itself.

local function attackEntity(uniqueID: string, damage: number)
   local Entity = Entities[uniqueID]
   if not Entity then
      return
   end

   Entity:Damage(damage)
end

How the class would look:

function EntityClass.new()
	local self = setmetatable({}, EntityClass)
	
    self.Health = 100
    
	return self
end

--@@ Deals damage to entity
function EntityClass:Damage(damage: number)
   self.Health -= damage
end

Finally the actual movement, there is so many ways to do this. One way is you could handle it all in the class itself, using pathfinding or any custom path you have and just have them move in a function, or you could use runservice to loop through all entities and move them accordingly. I haven’t really used entities in this way so I wouldn’t know the most optimised approach but you can always try them and see which one performs better.

1 Like

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