- Home /
Unity Auto detecting...
I have this code I made for detecting enemies based on the distance from the enemy to the player and then updating the detection level in an over all game script which then changes the a GUI texture to show the player that they are getting closer or farther away from an enemy... so it works perfect except one major thing: Every enemy is detecting the distance from them to the player and apparently if you do not kill the enemy that is closest to you it will not detect any other enemy... Im not telling the script to do this at all... granted it would be nice to know which one is closest and go off that one for the detection level but how can I get this to update to the next enemy if you do not kill the one before it? It seems as though Unity is determining which one is closest since Im not doing that anywhere in code...
thanks! Code below:
Detection system on Enemy Ai
detectDistance = Vector3.Distance (player2.transform.position, transform.position);
if (Game_script.playerStealthed == false)
{
if (detectDistance <= 20)
{
detectionLevel = 2;
Game_script.enemyDetectionLevel = 2;
}
else if (detectDistance > 20)
{
detectionLevel = 1;
Game_script.enemyDetectionLevel = 1;
}
if(detectDistance <= 15)
{
detectionLevel = 3;
Game_script.enemyDetectionLevel = 3;
}
if(detectDistance<= 10)
{
detectionLevel = 4;
Game_script.enemyDetectionLevel = 4;
}
if(detectDistance <= 5)
{
detectionLevel = 5;
Game_script.enemyDetectionLevel = 5;
enemychase();
}
if (enemyState == "attackmode")
{
if(detectDistance >= 15)
{
detectionLevel = 3;
Game_script.enemyDetectionLevel = 3;
enemyState = "looking";
}
}
}
Game_script GUI change based on detection lvl of Ai
if(controlerChosen) { if(stealthedToggler <= 0) { gStealth.guiTexture.texture = stealthed; } else if (stealthedToggler > 0) { gStealth.guiTexture.texture = notStealthed; }
if(!playerStealthed)
{
if (enemyDetectionLevel >= 1)
{
gGauge.guiTexture.texture = detctLvl1;
}
if (enemyDetectionLevel >= 2)
{
gGauge.guiTexture.texture = detctLvl2;
}
if (enemyDetectionLevel >= 3)
{
gGauge.guiTexture.texture = detctLvl3;
}
if (enemyDetectionLevel >= 4)
{
gGauge.guiTexture.texture = detctLvl4;
}
if (enemyDetectionLevel >= 5)
{
gGauge.guiTexture.texture = detctLvl5;
}
}
else if (playerStealthed)
{
if (!iSeeYou)
{
enemyDetectionLevel = 1;
gGauge.guiTexture.texture = detctLvl1;
}
else
{
enemyDetectionLevel = 5;
gGauge.guiTexture.texture = detctLvl5;
}
}
}
That's a lot of script to look through for one relevant segment. Do you think you could cut it down to just the parts you're having trouble with?
This is on each enemy, right? I'm not seeing the part where it sets the GUItext, so can't tell why it might be wrong. Also, the last function, NextWP, takes 15 lines to say currentWayPoint=currentWayPoint+1
, which is a sign you may be starting from messed-up code.
there really isnt any part in the code im having issue with its just the fact that unity defaults the closest enemy to you and wont recognise any other's until you kill it. This is on every enemy their detection level goes up in their script but doesn't change in our game script. I only posted the entire script bc its fully working and so would need it all to understand what's goin on
As for the WP system, check my notes, i didnt script that part this is someone else's AI on my $$anonymous$$m which I added the detection system to I have a better WP system but have not implimented it yet we have other issues that need to be fixed right now.
also the GUi isnt in this script for obvious reasons.. we have a seperate GA$$anonymous$$ESCRIPT that holds all static var's and gui elements since its always loaded in every scene.. makes things alot easier. The detection lvl goes up just fine, i've tested it. Its not an issue with the GUI. It's an issue with Uniy or needing a hard code to make Unity not default to the 1st enemy. Since each enemy calculates the distance to the player then based on those distances raises the threat lvl it "should" be working independantly from every game object with this attached
Answer by Bunny83 · Mar 04, 2011 at 01:19 PM
Well, it's really hard to read that code. You mixed different programmingstyles and your indention seems a bit "random". Like owenpat already mentioned there are some really strange "constructs" that doesn't make much sense.
You used a lot of static variables from your Game_script
and i think that's the main problem. Every enemy that have a greater distance than 20 will set your static var enemyDetectionLevel
. All do that in the same frame.
What is the detectionLevel
var even good for, because it gets written but never read? And why is it a float?
function enemyAttack is a coroutine and if your state is "attacking" it gets called every frame but you have two yield in there so there are 3 functions running at the same time... I don't know if that was intended but it looks strange to me.
edit
Well, since you added that you want to display the closest enemy's detection level, we can go on from there.
The easiest way to find the closest enemy would be to use Physics.OverlapSphere in your playerscript to get all colliders that are in range (eg. 20). Just sort them out and test for enemies only. If you have tagged your enemies you can use the tag or even simpler and faster to place them on a seperate layer and restrict OverlapSphere to check this layer only.
You will end up with some thing like that:
// Enemy are tagged with "Enemy" the AI script is called "EnemyAI" var allNearbyColliders = Physics.OverlapSphere(transform.position, 20); var closestEnemy : EnemyAI = null; for(var current : Collider in allNearbyColliders) { if (current.tag == "Enemy"){ if (closestEnemy == null) closestEnemy = current.GetComponent.<EnemyAI>(); else { var currentEnemy : EnemyAI = current.GetComponent.>EnemyAI>(); if (currentEnemy.detectDistance < closestEnemy.detectDistance) closestEnemy = currentEnemy; } } }
//
// Or with all enemies on a special layer: // Enemy are on layer 10 and the AI script is called "EnemyAI" var allNearbyEnemies = Physics.OverlapSphere(transform.position, 20, 1<<10); var closestEnemy : EnemyAI = null; for(var current : Collider in allNearbyEnemies) { if (closestEnemy == null) closestEnemy = current.GetComponent.<EnemyAI>(); else { var currentEnemy : EnemyAI = current.GetComponent.<EnemyAI>(); if (currentEnemy.detectDistance < closestEnemy.detectDistance) closestEnemy = currentEnemy; } }
After that loop you will have the closest enemy AI-script reference in the closestEnemy
variable. If no enemy is in range, closestEnemy
will be null, so keep that in mind! Now you can just use the detectionLevel variable of that enemy.
if (closestEnemy != null)
enemyDetectionLevel = closestEnemy.detectionLevel;
Note: This requires the variables detectDistance
and detectionLevel
to be public (in JS simply not private ;) ) and your AI script is named EnemyAI. If your script have a different name, you have to adjust it accordingly (either rename the script or change it in my sample code to match your name).
If you want to know how to setup you layer just look at the documentation on layers.
All this is untested but it should work. Maybe if i have some time i could try it myself.
Good luck! again ;)
Good catch on enemyAttack
. What I usually do for coroutines is start with a line like enemyState=busy
. Then have as many yields as I want. The AI code sees "busy" and knows to do nothing (there are no ifs for it.) Then I set enemyState=chase
(or whatever) at the end to signal the AI code to run again.
This would certainly not be the way I would do Ai, I know it's messy but it's not my assignment to rewrite the code for it, just impliment a working detection system which works independantly from all the Ai. Basically im setting each enemy to track its local distance between it and the player - as the player gets closer the detection level raises in the Game_script which then changes the GUI textures to indicate which level it is. The secondary detection lvl you see is for testing only, i wanted to make sure each enemy was working properly, its for inspector use only
i was using float's before because for somereason unity was complaining about using int with this code - for the refference detection lvl it can be an int, but it's not an important detail since its just for testing to make sure each enemy has its own detection level working constantly - it will be taken out completely soon. I'll cap the code to just what I wrote and what it refferences in the game script below
I just edited the original post ins$$anonymous$$d of reposting the code *
the only thing I can think of to fix this so the Game_script Detection lvl always increases is to take it off the enemy, put it on the player and have the player detect the distance to each enemy in an array then hard code it so which ever enemy is closest that is the absolute detection level. the issue with this is how do I get it do to that with out it conflicting on the detection lvl if there are multiple enemies with in 20 - 0 range? because it will want to set the detection lvl to all the levels that are being hit if multiple enemies are in the area. I need it to always take the highest
Answer by Soby · Mar 05, 2011 at 07:58 AM
After hours of altering Bunny83's code i finally got it working perfectly - but thank you Bunny! That gave me a greate base to work from :D below is the final code:
var allNearByColliders = Physics.OverlapSphere(transform.position, 20); var currentEnemy : enemymove; for (var current : Collider in allNearByColliders) { if (current.tag == "Enemy") { if (currentEnemy == null) { currentEnemy = current.GetComponent.<enemymove>(); }
if (currentEnemy)
{
var closestEnemy : enemymove = current.GetComponent.<enemymove>();
if (closestEnemy.detectDistance <= currentEnemy.detectDistance)
{
distanceToEnemy = Vector3.Distance (closestEnemy.transform.position, transform.position);
Debug.DrawLine (transform.position, closestEnemy.transform.position, Color.red);//shows how many enemies are in range and where they are and how close to player
if (Game_script.playerStealthed == false)
{
if (distanceToEnemy <= 20)
{
Game_script.enemyDetectionLevel = 2;
}
else if (distanceToEnemy >= 20)
{
Game_script.enemyDetectionLevel = 1;
closestEnemy = null;
}
if(distanceToEnemy <= 15)
{
Game_script.enemyDetectionLevel = 3;
}
if(distanceToEnemy <= 10)
{
Game_script.enemyDetectionLevel = 4;
}
if(distanceToEnemy <= 5)
{
Game_script.enemyDetectionLevel = 5;
}
}
}
}
}
}
Your answer
Follow this Question
Related Questions
Collision detection not working properly with 2D sprites 1 Answer
the most efficient way to detect colision between objects in a large scene (Strategy Game) 1 Answer
Death fall 1 Answer
WALL collision detection problem... help!!!! 0 Answers
Idle gameobjects within spawned trigger wont set trigger off 1 Answer