How bad is it to use Humanoids for non-humanoid damage?

The damage handler I wrote works specifically for Humanoids.
I want to have environmental damage as well.
Ex: Cutting a tree down

How bad of an idea is it to just drop humanoids into every tree in the game?
Do Humanoids still use up processing power when they don’t have any parts named “Head” inside the model?

1 Like

I’m not sure why you would want to add a Humanoid to an object such as a tree unless your Tool is coded to specifically damage only Humanoids and you don’t want to change it.

What I would suggest as an alternative, is to add an IntValue to the object that you wish to damage and code the Tool to detect the collision with the Tree for example and decrement the IntValue.

1 Like

Yea, that’s probably what I’ll end up doing.
I’m just curious about the actual effects in terms of performance.

1 Like

Very bad. Humanoids on their own participate in a lot of baked-in process, from rendering to what-have-you. It’s bad enough using Humanoids as they are for player characters and stacking that up for any NPCs: your game will not do well if you use Humanoids for non-characters.

Since you’re not using anything from the Humanoid other than the health, adding a Humanoid to every tree is a very lazy workaround. What you should instead be doing is changing your damage handler to account for this. Add some kind of health tracker to trees (e.g. ValueObjects, ModuleScript, whatever you’d like) and make the damage handler determine what it hit. Depending on what it hit, then it should handle damage a different way: take points off the tree or damage a Humanoid.

The damage handler needs to change for this circumstance, not the way you allow trees to be damaged, if you’re looking to keep performance in good hands.

2 Likes

yes

I’m mainly curious as to when a humanoid starts taking up processing power.
Does it happen regardless of if the humanoid’s character model has a part named “Head”?

The only reason I even considered this was because I would have to rewrite multiple things if I started using NumberValues to measure damage as well.

This is easy to benchmark.

local statsService = game:GetService'Stats';
local function Benchmark(n, f)
	local s = tick();
	local startMem = statsService:GetTotalMemoryUsageMb();
	xpcall(f, function()
		warn('[-] Benchmark', n, 'failed! time taken:', tick() - s, '\nMemory delta:', statsService:GetTotalMemoryUsageMb() - startMem);
	end);
	print('[+] Benchmark', n, 'ran! time taken: ', tick() - s, '\nMemory delta:', statsService:GetTotalMemoryUsageMb() - startMem);
end;

Benchmark('Initiation', function()
	local sampleRig = workspace.testCharacter.Model;
	--[[
		* testCharacter is an R6 block rig built with the Rig Builder plugin
		* Model is an empty model with a Part named 'Head', as this is all a humanoid needs to show it's name
	]]--
	for i = 1, 1000 do
		Instance.new'Humanoid'.Parent = sampleRig;
	end;
end);
Benchmark('Damage', function()
	local myHumn = Instance.new'Humanoid';
	for i = 1, 10000 do
		myHumn:TakeDamage(.01)
	end;
end);

Output (note, Memory delta is in megabytes):
image
Either way I’d recommend using tables in the first place as they are even less expensive than any instances (such as NumberValues), as the time it takes to run is different from the memory it uses up.
There is no excuse to lazy coding; it’s very bad practice for you and your game. I’m gonna sound harsh here but if you want your game to succeed, you have to be far off from lazy.

1 Like

I would tend to disagree.
I believe that being lazy is important when it comes to indie game development.
A lot of games on the front page are pretty lazy.


I always struggle with feature creep.

Cool Benchmark function. I didn’t know Stats service was a thing. That’s awesome!
I don’t think those tests were exactly what I was looking for though.
The function labeled “Initiation” creates 1000 humanoids while the one labeled “Damage” simply damages a single humanoid 10000 times. I don’t get much insight by comparing these two numbers.

I wrote a little edited version of your code that basically confirms some stuff

local statsService = game:GetService'Stats';
local CharsWithHead = Instance.new('Model',workspace)
local CharsWithoutHead = Instance.new('Model',workspace)

for i=0,1000 do
	Instance.new('Part',Instance.new('Model',CharsWithHead)).Name='Head'
	Instance.new('Model',CharsWithoutHead)
end

local function Benchmark(n, f)
	local s = tick();
	local startMem = statsService:GetTotalMemoryUsageMb();
	xpcall(f, function()
		warn('[-] Benchmark', n, 'failed! time taken:', tick() - s, '\nMemory delta:', statsService:GetTotalMemoryUsageMb() - startMem);
	end);
	print('[+] Benchmark', n, 'ran! time taken: ', tick() - s, '\nMemory delta:', statsService:GetTotalMemoryUsageMb() - startMem);
end;

Benchmark('With Head', function()
	for i,v in pairs(CharsWithHead:GetChildren()) do
		Instance.new('Humanoid',v)
	end
end);

Benchmark('Without Head', function()
	for i,v in pairs(CharsWithoutHead:GetChildren()) do
		Instance.new('Humanoid',v)
	end
end);

[+] Benchmark With Head ran! time taken: 0.010543823242188 Memory delta: 4.20703125 [+] Benchmark Without Head ran! time taken: 0.0097887516021729 Memory delta: 4.6015625

4 Likes