Is There A Better Way To Get A Player Character From Only A Basepart

Hello, I am making a combat system and I need to get the character from only a basePart without using hit.Parent or something like that. Are there better ways to get their character?

No. There aren’t. You could have a parent folder for all characters and then do

if hitPart:IsDescendantOf(characterFolder) then
 -- Do stuff
end

but performance-wise, I would just do this:

if hitPart.Parent.Parent = workspace.Characters then -- assume workspace.Characters is created by
                                                     -- you and every Player Character is parented to it
    local char = hitPart.Parent
end
1 Like

If you really cared about performance then you would also alias the Parent instance to avoid redundant hierarchy path evaluation :stuck_out_tongue:

--init
local charFolder = workspace.Characters

--tight loop
local parent = hitPart.Parent
if parent.Parent == charFolder then
    local char = parent
    ...
end

But to suggest a solution to the OP’s question, you could also hash every basepart belonging to a character into a hashmap and use that as a reference. But please be careful of memory leaks with this approach. Pseudocode below

local hash: {[BasePart]: Character} = {}

onCharacterAdded:Connect(function(ch)
	for _, bp in ch:GetChildren() do
		if bp.CanQuery then
			hash[bp] = ch
		end
	end
end)

local function garbageCollectHash()
	for bp, ch in hash do
		if not bp:IsDescendantOf(workspace) then
			hash[bp] = nil
			continue
		end
		if not ch:IsDescendantOf(workspace) then
			hash[bp] = nil
		end
	end
end

--hitreg
local character: Character? = hash[RaycastResult.Instance]

If we’re going down that route, wouldn’t it also be easy to check the network owner of the part (assuming the player is not taking network ownership of anything else)?

local function getPlayerFromPart(part)
    return part:GetNetworkOwner()
end

That’s also a possibility. The OP was asking for alternatives so may as well deliver all of them lol