ObjectValue 'attempt to index nil with position'

Hello!

Currently still working on a boss fight, had some trouble conveying a player’s position to a separate melee script, so I used an object value. The object value’s value is the player’s HumanoidRootPart. In my code, which is being assigned by the main code to make the enemy move. For God knows what reason, it’s able to get the position of the HRP just fine in the move code but apparently it can’t do that for the ObjectValue despite it being the same information.

I’ve looked at a couple different posts and none have really seemed to clarify my issue or find a solution.

Here’s the logic for the attack:

local model = script.Parent
local root = model:WaitForChild('HumanoidRootPart')
local currentTarget = model._currentTarget
local attacks = require(model.Main.Attacks)

local maxRange = 12

local attacking = false

while task.wait() do
	if currentTarget == nil then return end
	print(currentTarget, typeof(currentTarget))
	local distance = (currentTarget.Value.Position - model.HumanoidRootPart.Position).Magnitude
	
	if distance > 12 then return end -- code below should only run if distance is less than or equal to 12
	
	local humanoid = target:FindFirstChildOfClass('Humanoid')
	if game.Players:GetPlayerFromCharacter(target) and humanoid and humanoid.Health > 0 and not attacking then
		attacking = true
		attacks.melee()
	end
end

I’ve printed out the _currentTarget value and it’s type, and it’s giving me HumanoidRootPart Instance, so somethings up with the properties of that object but I’m not sure how to fix that.

This is definitely roundabout. Not once have I ever encountered a situation where a position needed to be communicated over an ObjectValue. If you can provide more information, I’m sure we can divulge a better solution

Hello! I tried to use the same module I’m using for my movement function but no matter what I input, even the same values for the movement, the returned player would always be nil, so getting desperate, I swapped over to an ObectValue.

Edit: I’d be happy to supply you with the code for the Target module if you’d like.

You should investigate why that is. I surmise it’s an issue with the replication boundary. Let’s see some code

Sure thing. Here’s the code that the Target module is using:

local targets = {}
local npc = script.Parent.Parent

function targets.findNearestTarget()
	local range = math.huge
	local nearestTarget = nil

	for _, player in game.Players:GetPlayers() do
		local target = workspace:FindFirstChild(player.Name)

		if target and target:FindFirstChildOfClass('Humanoid').Health > 0 then
			local distance = (target.PrimaryPart.Position - npc.PrimaryPart.Position).Magnitude

			if distance <= range then
				range = distance
				nearestTarget = target
			end
		end
	end

	return nearestTarget, range
end

return targets

Here’s how the main script is interpreting it:

local function move()
	local target, distance = targets.findNearestTarget()
	if target == nil then return end
	currenttarget.Value = target.HumanoidRootPart

	local humanoid = target:FindFirstChildOfClass('Humanoid')
	if game.Players:GetPlayerFromCharacter(target) and humanoid and humanoid.Health > 0 then
		entityHumanoid:MoveTo(target.PrimaryPart.Position)
	end

	if distance <= ranges.sight then
        -- do abilities
	end
end

Can you share what line the error occurs on?

if currentTarget == nil then return end
This is checking the value instance itself, but not its value property. Change to
if currentTarget.Value == nil then return end

Took Ziffix’ advice and stopped using the ObjectValue and instead resorted back to the module. The error would’ve occurred when defining the Distance variable. The module currently still has an issue where it returns nil for the target.

Oh, I didn’t catch that. Nonetheless, the issue still occurs when trying to index the value’s position.

Ah alright, so you are using the module now?
Can you use print statements to see where it excludes the target from being returned?

Should be currentTarget.Value.Value.Position I think.

Assuming the ObjectValue is named as ‘Value’, but you need to grab the value of it then the position.

Oh, actually I’m not sure! Taking your advice, the module does print me as the nearestTarget and returns that value, but when being indexed by the script, the target returns nil.

Edit: It looks like the melee function detected it was nil when I first spawned in and the game didn’t detect I was in the game quite yet, but stopped running after the target script identified me as the nearest target.

image

Is it because attacking is never set to false again?

Could be, let me see if that’ll fix the issue.

Yeah, no. The script just refuses to run again after erroring:

local model = script.Parent
local root = model:WaitForChild('HumanoidRootPart')
local targets = require(model.Main.Targets)
local attacks = require(model.Main.Attacks)

local maxRange = 12

local attacking = false

while task.wait() do
	local target, distance = targets.findNearestTarget()
	print(target, typeof(target))
	if target == nil then return end
	print('got target')
	
	local humanoid = target:FindFirstChildOfClass('Humanoid')
	if game.Players:GetPlayerFromCharacter(target) and humanoid and humanoid.Health > 0 and not attacking then
		print('is attacking!')
		attacking = true
		attacks.melee()
		task.wait(3)
		attacking = false
	end
end

image

Calling ‘‘return’’ on a loop will also break it (it stops repeating)

1 Like

image
Wouldn’t necessarily change much if I changed ‘return’ to ‘break’ or nothing at all since it’ll still break the repeat loop or stop when it tried to find a Humanoid in nil. I could try creating a separate loop just to index the humanoid.

image
Apparently when still constantly checking for a target, it’ll continue to return nil.

Actually, nevermind. I was able to fix this by changing the ‘return’ to a ‘continue’. Thanks for making me aware of this oversight!

1 Like

Awesome! I was gonna send you this code snippet, but while trying to boot up studio so the code was correctly formatted, I had some trouble

while task.wait() do
	local target, distance = targets.findNearestTarget()
	
	if target then
		local humanoid = target:FindFirstChildOfClass('Humanoid')
		if game.Players:GetPlayerFromCharacter(target) and humanoid and humanoid.Health > 0 and not attacking then
			print('is attacking!')
			attacking = true
			attacks.melee()
			task.wait(3)
			attacking = false
		end
	end
end
1 Like