How to detect specific Humanoids that are specificly enemies, not other players or genaric NPCs, AND make player face target

I’m trying to make a script detect enemies within a certain range of the player. Currently, everything I’ve found targets other players in the game, but I would like it to not detect other players, only humanoids considered to be enemies. Right now, I have the idea that I need to put some kind of indicator inside of the enemy (like a blank value that I can check for to see if the model is an enemy or not), but I’m not sure how to exactly approach the detection and the turning of the player towards the target.

2 Likes

One thing you can do is have the script check if the model the humanoid is in is a player character.

Something along the lines of

if game.Players:GetPlayerFromCharacter(humanoid.Parent) == nil then

(I have no idea what character(s) one uses to end a code block on the DevForum and can’t find a source of info on how syntax works on here, so I used quotes. If anyone could clarify that for me, I’d appreciate it.) Edit: my apologies. I’m not sure why I thought ending a code block didn’t work for me last night. Thanks!

Alternatively, you could give the enemies’ humanoids a different name, but that would be a bit more painful to work with.

How would I go about getting the humanoids in the area, and finding the closest one to the player if multiple enemies are within range? I tried investigating things like Ray Casting but it didn’t seem very helpful.

1 Like

When it comes to finding enemy characters, many people just search every descendant of the workspace and look at each humanoid found. It’s not the most efficient way, but I haven’t scripted my idea for an alternative yet (basically each enemy would create an object value set to the enemy itself and put it in a certain folder, and delete that object value when the enemy dies. Searching for enemies would involve checking everything in that folder.)

Comparing enemies’ distances from the player is something I’m more familiar with.

Create two variables, one for the closest enemy the script has found, and another for the distance that enemy has from the player character. The first should begin as nil and the second should begin as math.huge.

Whenever the script looks at an enemy, calculate the distance between the player and the enemy. You could compare distance between torsos, heads, HumanoidRootParts, or whatever it is they’re guaranteed to have in common.
To get the distance, use

(a.Position - b.Position).Magnitude

Compare that magnitude to the distance variable. If it’s less than the distance variable, set the enemy variable to the current enemy and set the distance variable to the magnitude that was just found. Have the script repeat this until it checks every enemy, and if the enemy variable isn’t nil at the end, that will be the closest enemy.

2 Likes

@Bergan You can write code blocks using three backticks (`), additionally the formatting guide is here: https://devforum.roblox.com/t/developer-forum-formatting-guide/456083

```
(code here)
```


You’ll need to add something that the code can check to determine who an enemy is or not, as well as if they are an NPC that can be targeted. For simplicity of implementing everything else, it’s best you store them in a specific and unique place so we can reference them when finding the closest enemy. For this example, I’ll be using Workspace.Enemies


If you want to face the player in a specific direction, you can look towards CFrame.lookAt for details about this. You’ll likely just need to assign the HumanoidRootPart CFrame to it’s current position, facing the position the enemy is at.

MyCharacter.HumanoidRootPart.CFrame = CFrame.lookAt(MyCharacter.HumanoidRootPart.Position, Enemy.HumanoidRootPart.Position)

For finding the nearest enemy, it’s a reasonably simple check and there’s probably more efficient ways of doing this but this is what I’m used to. If we stored the enemies in a specific place, this makes the check run much faster.

local function GetNearestEnemy(MyPosition: Vector3)
    local NearestEnemy = nil
    local NearestEnemyDistance = math.huge -- Set to a huge number so that the first enemy will always be closer than this
    
    for _, Enemy in Workspace.Enemies:GetChildren() do
        local Humanoid = Enemy:FindFirstChild("Humanoid")
        local HumanoidRootPart = Enemy:FindFirstChild("HumanoidRootPart")

        -- Verify that we can attack the enemy, and they are a valid enemy
        if (not Humanoid or not HumanoidRootPart or Humanoid.Health <= 0) then
            continue
        end

        -- Grab the distance between the enemy and the player
        local EnemyPosition = HumanoidRootPart.Position
        local Distance = (MyPosition - EnemyPosition).Magnitude

        -- If the distance is less than the current nearest enemy, set it as the new nearest enemy
        if (Distance < NearestEnemyDistance) then
            NearestEnemy = Enemy
            NearestEnemyDistance = Distance
        end
    end

    return NearestEnemy
end

Preferably, you won’t need to call this function too often unless your game depends on it. Once a second is probably a good spot. Additionally, if there are no valid enemies, the function can return nil so have a check in place for that!

2 Likes

Name the enemy in a specific way that you are sure no players would be named, not the most scripty method, but it works (name with 20+ characters, name with special foreign charaters, name with 3- characters, E.T.C)
then just check the name instead of the humanoid

2 Likes

Or just use CollectionService to tag each enemy with the “Enemy” tag and check that instead.

1 Like

You could use CollectionService to tag which humanoid models are players and which aren’t, then compare the tags when handling detection code.

1 Like