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.
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.
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.
@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!
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
You could use CollectionService to tag which humanoid models are players and which aren’t, then compare the tags when handling detection code.