I’m working on an entity script and I’m trying to use the module functions (Specifically, Wander). The issue is that it’s printing out “Attempt to index nil with 'PrimaryPart'” during the ComputeAsync part.
--[[SERVICES]]--
local ServerStorage = game:GetService("ServerStorage")
local PathfindingService = game:GetService("PathfindingService")
--[[FOLDERS]]--
local EntityFolder = ServerStorage:WaitForChild("Entities")
local RegularFolder = EntityFolder.Regular
local SpecialFolder = EntityFolder.Special
--[[MODULE]]--
local BaseEntity = {}
BaseEntity.__index = BaseEntity
--//Creating the entity
function BaseEntity:CreateEntity(EntityName)
--//Finding entity
local RequestedEntity = RegularFolder:FindFirstChild(EntityName) if not EntityName then
RequestedEntity = SpecialFolder:FindFirstChild(EntityName) if not EntityName then
warn("CANNOT FIND ENTITY: "..EntityName)
return
end
end
--//Creating entity
local self = setmetatable({}, BaseEntity)
self.Entity = RequestedEntity:Clone()
self.Humanoid = RequestedEntity:FindFirstChildWhichIsA("Humanoid")
self.Entity.Parent = game.Workspace
--//List of entity behaviors & assinging them to their respective entity.
self.EntityBehaviors = {
["Starvlud"] = {
["Behavior"] = function(self)
BaseEntity:Wander()
end,
}
}
self.EntityBehaviors.Starvlud:Behavior()
return self
end
--//Default functions
function BaseEntity:Wander()
local Walkpoints = workspace:WaitForChild("Walkpoints"):GetChildren()
local RandomWalkPoint = Walkpoints[math.random(1,#Walkpoints)]
while task.wait() do
local NewPath = game:GetService("PathfindingService"):CreatePath()
NewPath:ComputeAsync(self.Entity.PrimaryPart.Position, RandomWalkPoint.Position)
if NewPath.Status == Enum.PathStatus.Success then
local Waypoints = NewPath:GetWaypoints()
for _, Waypoint in pairs(Waypoints) do
self.Humanoid:MoveTo(Waypoint.Position)
self.Humanoid.MoveToFinished:Wait()
end
end
end
end
function BaseEntity:InvestigateNoise()
--//TBA
end
function BaseEntity:ChaseTarget()
--//TBA
end
function BaseEntity:TryJumpscare()
--//TBA
end
return BaseEntity
“Attempt to index nil” means the object you’re trying to index in doesn’t exist, e.g self.Entity.
This error message has tripped me up multiple times and still continues to do so. I honestly don’t know why, maybe it’s the quotations around what you try to index it with
I think it’s because of this
this gets compiled as BaseEntity.Wander(BaseEntity) which i dont think you are trying to do, BaseEntity doesn’t have a Entity member so it’d error
if thats not the problem then i have no other idea
I also noticed the code will attempt to clone the requested entity even if it doesn’t exist. This is because the return condition only checks if a parameter isn’t passed to CreateEntity:
If nothing is passed you should honestly just return it. Also return if there is no Requestedentity. Also, use string interpolation, it’ll make your life easier:
function BaseEntity:CreateEntity(EntityName)
if not EntityName then return warn("NO ENTITYNAME GIVEN") end
--//Finding entity
local RequestedEntity = RegularFolder:FindFirstChild(EntityName)
if not RequestedEntity then return warn(`CANNOT FIND ENTITY: {EntityName}`) end
This is a second error (i think?) I noticed. I may be wrong on this though.
You defined self in a function, overwriting self from earlier, meaning self:Wander() won’t work.
If you find a way to, I’d recommend having a data ModuleScript of all the entity behaviors and just indexing that whenever one is created. This’ll make it much easier to add new ones and organize.
One last thing, I’d recommend defining all your services at the top of the script, if this gets annoying you can try using SimpleComplete, but having a bunch of game:GetService calls in the middle of your script might get very annoying to read and hurt maintainability of your code in the future.
Actually, you already did, this variable is just repeating it lol:
Removing the self seems to let me use module functions now. The wandering script isn’t working but that’s another issue that I think I can fix all by myself. Anyway, what should a data ModuleScript look like since I’m most likely gonna just be using that.
Just a modulescript that returns information about something:
-- Module named EntityBehaviors?
return {
["Starvlud"] = {
["Behavior"] = function()
-- impossible to get entity?
end,
},
["OtherEntity"] = {
["Behavior"] = function()
-- impossible to get entity?
end,
}
}
You can then require it as so:
local EntityBehaviors = require(EntityBehaviors)
local currentEntityBehavior = EntityBehaviors[currentEntity] -- self.Entity.Name?
if not currentEntityBehavior then return end
currentEntityBehavior.Behavior()
With the way your system is set up, I don’t exactly think it’s possible to get the entity to use the wander function, so this is just a general idea.
Just saying, if you add a bunch of entities to self.EntityBehaviors it’ll create that whole table for every entity object in the game AND get pretty messy for the code.
Alrighty then. I’ll look into data ModuleScripts. Though, I noticed that it might be impossible to use the functions in there, but wouldn’t moving the general functions into the EntityBehavior module work or good practice?
Although now that I think of it, creating a function for every entity in the table might also be unnecessary when you can just reference back to a preexisting module function.
Maybe you can add an entity parameter to the Wander function and then check:
local self = self or entity
Then you can just reference to Wander in the module behavior, and call Behavior(entityObject)
Edit: iirc you can just call BaseEntity.Wander(entity) and throw the entity object as the parameter, this should pass to self anyway. So your data module would look more like this:
local EntityBehaviors = require(EntityBehaviors)
local currentEntityBehavior = EntityBehaviors[currentEntity] -- self.Entity.Name?
if not currentEntityBehavior then return end
currentEntityBehavior.Behavior(entity)
Unsure if this is the best option, but it seems like it’ll work.