3 Ways to Find Targets in Unity! (Collider, Physics, Distance)
Вставка
- Опубліковано 4 жов 2024
- Let's check out 3 unique Methods of Finding Targets in Unity!
🌍 Get my Complete Courses! ✅ unitycodemonke...
👍 Learn to make awesome games step-by-step from start to finish.
Simple Tower Defense AI in Unity!
• Simple Tower Defense A...
Collisions and Triggers (OnTriggerEnter not working!)
• Collisions and Trigger...
🌍 Get Code Monkey on Steam!
👍 Interactive Tutorials, Complete Games and More!
✅ store.steampow...
If you have any questions post them in the comments and I'll do my best to answer them.
🔔 Subscribe for more Unity Tutorials / @codemonkeyunity
See you next time!
📍 Support on Patreon / unitycodemonkey
🤖 Join the Community Discord / discord
📦 Grab the Game Bundle at unitycodemonke...
📝 Get the Code Monkey Utilities at unitycodemonke...
#unitytutorial #unity3d #unity2d
--------------------------------------------------------------------
Hello and welcome, I am your Code Monkey and here you will learn everything about Game Development in Unity 2D using C#.
I've been developing games for several years with 7 published games on Steam and now I'm sharing my knowledge to help you on your own game development journey.
You can see my games at www.endlessloopstudios.com
--------------------------------------------------------------------
Website: unitycodemonke...
Twitter: / unitycodemonkey
Facebook: / unitycodemonkey
🌐 Have you found the videos Helpful and Valuable?
❤️ Get my Courses unitycodemonkey.com/courses or Support on Patreon www.patreon.com/unitycodemonkey
Somewhat, but not quite.
I came here to find out if OnTriggerStay2D can switch which collider it's detecting, if that collider doesn't meet a certain criteria.
I'm trying to switch target once a variable has changed in the current target. (two targets in total)
It's for a treasure chest, and the targets are units that the player controls.
It should detect whichever target is currently "active". (only one unit is active at a time)
The problem is that it doesn't update, if both units are already inside the trigger when the variable changes.
Example;
First unit enters trigger. Chest can open, as it detects the active unit.
Second unit is activated and enters trigger. Chest can open, as it detects the new active unit.
*First* unit is activated again. Chest *cannot* open, as it still checks the *second* unit. The first unit being active again is not detected.
Guess i'll never know :,(
Brackeys : *Leaves*
Code monkey : Fine ill do it myself
Not the same kind of content, CodeMonkey's is more advanced.
@@SpawnCampGames yea
@@SpawnCampGames And more in depth I would say
And using clean code principles
I agree with the guy above that its not exactly the same content.
But you hit a weak spot with brackeys right there man.... :(
This video format is the best of the best!
1) Show different ways to solve the problem.
2) List the pros and cons of each method.
3) Demonstrate practical application.
+ The community actively discusses and offers other solutions to the problem.
💬 Here's 3 different interesting methods each with their Pros and Cons.
How do YOU usually find targets? Use any of these or something different?
I use the 3 methods according to my needs. Super video.
I'm working on a variant of the collider trigger method that uses a dynamic collision mesh to target groups of enemies within a simple, but morphing 3D shape. Works great for now, but I might need to switch to a different method if performance becomes an issue.
Instead of using a custom editor, just add "OnDrawGizmoSelected" method, drawing a sphere of radius tower range. Takes 1 line and adds the editor range view!
Funny, I put out a video today on targeting in a tower defense game today as well 😁. Though mine was more focused on determining which enemy to shoot at if there are multiple enemies in range.
The approach I took was a hybrid between the Collider and Physics methods. Basically I called the Physics.Overlap method when an enemy enters the detection trigger or when the tower comes off attack cooldown. If there are enemies in range, then the tower makes a determination of which tower to fire at based off a selected attack strategy (i.e. first, last, strongest, weakest, etc.)
Great video though! Really liked how you broke down multiple ways to accomplish this behavior and talked about the pros/cons
2 and 3 are better, but if the enemies are really (like really) fast, the point when they get detected it will probably vary from enemy to enemy, so for my prototype I used the first method and the enemies got added to a list as soon as they enter the collider and then the target will change based on the player preferences (attack the enemy with most hp, attack the one that moves faster, if enemy have half hp change target, etc). Amazing video as always!
Great video! I wanna add at 7:48 that when working in 3D the method is "OverlapSphere" :)
I was thinking about how I would handle the way to find targets and found this. Nice video!
With colliders, you can also take advantage of the layers system - so that only the correct things can trigger collisions. You can also easily change the code to suit the project. In the case of a tower defense, instead of simply adding the first one as the target, you can instead add the target to a list/array. Doing so will then allow you to add sorting functionality(by type/most health/least health/etc) that you often see in other Tower Defense games.
In this specific example(find target only* when in range) - the other two aren't even worth considering.
In the pros/cons page, it would have been better if you went over ideal use cases.
First Method is buggy because if second enemy gets inside collider before first one dies tower should switch to second one and ignore the alive one forever. However it could be easily improved by instead of setting target to the enemy triggered we can just add them to list and remove them when they live the collider or die and target the enemies in order from the list.
Second method is unthinkable when there is lots of enemies. Distance is costly function and running hundreds of each frame is not recommended at all.
Third method is best for the purpose. We dont need to call physics every frame. First we can check if we have a current target if we do we can skip casting. If we dont then we cant check it compared to towers fire rate. For example if tower fires 5 times /second and if we check 5 times / second it wont be too obvious. Then we dont have to loop through foreach for every member. As soon as we found an alive enemy we can break foreach loop.
Thanks to Code Monkey I was able to recover from the down that Brackeys left when he retired!!
I've really been enjoying your builder/defender course on Udemy and I just wanted to thank you again for these great videos that illustrate solutions to common problems using Clean Code! I've read the Clean Code book several times back when I was a professional Android developer and it has been so great to see you always stick to those principles. I watch other Unity tutorials where a solution is presented but in a really error-prone or non-scalable way, and it just reminds me of why I keep coming back to your channel - you write beautiful, clean, self-documenting code! It's awesome! Keep it up!
Thanks! I'm glad you're enjoying the course and the videos!
I've been looking for unity tutorials/courses that apply clean coding and software architecture principles, have you followed other code monkey courses and if so would you say he applies these principles in all of them?
@@DoomCatcher I would say yes. He has of course grown and evolved over time as he gains more experience and learns new things, but he always tries to do things the "clean" way that will make projects extensible and easy to maintain.
Good video. I have also used a Grid to determine if an object's Cell Number is within a range (of cells) of another object's Cell Number, which performs great in certain cases since you don't need distance/physics math like other methods.
Normally use 1 or 2, but the below mentioned method of using method two with a grid seems pretty good.
I think about using method 3 to register the tower on all tiles in range and use events to inform it when an enemy enters
Im making a tower defense game and im using a more heavy performance version of the list solution(Just making every turret search for every enemy on its own), so ill be upgrading my logic with the help of this video. Also when i was performance issues i thought "why dont i add a timer", but instantaniously thought "Someone may notice" and didnt do so without thinking that in a second there a probably 60 frames or more so i just could check 6 times less often without reducing object responsiveness.
Anyway loved the vid, because it was good as always!
Yeah no one will notice if the Tower takes 100ms longer to find a target. Depending on the speed of your Units you can make it even more infrequent without a noticeable difference.
Thank you so much, I think I got something very useful from here. If you wonder, don't anyone think having a Identity script (which isn't a Monobehaviour) in every single object in the game would help in Unity.
I usually use the collider trigger for trigger objects that I end up deleting once the player steps on the collider. I will also code it as Trigger.. Vector3 distance is really useful for having baddies that shot at the player at a distance. Helpful video with the comparisons!
Great video - hadn't thought about the 3rd method at all. A build on your second option would be to have a grid system where enemies add and remove themselves from a each square when they move. This way, you only circle through those enemies nearby, which can help when you have a larger map. Also, would use sqrDistance to improve performance.
Yup, combining it with a Quadrant System is indeed a very performant way to do it.
That's what I did in my massive DOTS test ua-cam.com/video/hP4Vu6JbzSo/v-deo.html
Thats a nice approach, which I will try next time I need something like this
Edit: I think about using method 3 to register the tower on all tiles in range and use events to inform it when an enemy enters
thanks for the Vector3.Distance idea it was very useful
Thanks! I've only used the second method. I didn't know about the third.
Thank you so much for this tutorial. What kind of method should we use when trying to find the closest character to each character in a game with hundreds of moving characters?
I would use the Physics query method
lots of love to you sir from India❤❤❤
You can compare distances using Vector3.sqrMagnitude and squaring the compared value too. I think it's more performant as Unity doesn't need to perform a square root calculation (which is slow) as in Vector3.Distance(). I might be wrong tho haha. Nice video :)
sqrMagnitude is indeed a lot faster especially if you don't care about the actual value and just need it for comparison like finding the closest one.
great tutorial. helped me to solve my collider issue
Respect! It is super good and detailed explained! It is also begginer-friendly, thank you!
can you make a video about how to make joystick or button for auto aim shooting
Thank you so much! BTW you can make a video about clean code/ how to make your code lees performance heavy and more efficient ?
Performance is a topic I'd like to cover but it's very difficult to make something that is applicable to lots of scenarios
@@CodeMonkeyUnity ok thanks For Answering!
I'm wondering, is it possible to do the distance check using the Job system? Doing OverlapSphereAll and going all through the list using the Job system and Burst compiler?
Thanks a lot i hope you are happy always
Finally Got the third option working! Man you are the GOAT for making all of this free man. The only issue I'm having right now is my bullets target will die while it's on the way and stops moving. I cant figure out how to destroy the bullet after that.
"public class Projectile : MonoBehaviour
{
public float projectileSpeed;
private Transform ValidTarget;
private Vector2 target;
private int projectileDmg = 2;
void Start()
{
ValidTarget = GameObject.FindGameObjectWithTag("Enemy").transform;
target = new Vector2(ValidTarget.position.x, ValidTarget.position.y);
}
void Update()
{
transform.position = Vector2.MoveTowards(transform.position, ValidTarget.position, projectileSpeed * Time.deltaTime);
}
void OnTriggerEnter2D(Collider2D other)
{
Enemy enemy = other.GetComponent();
if (enemy != null)
{
enemy.Damage(projectileDmg);
Destroy(gameObject);
}
}
}
You need to check if ValidTarget is null, if so the enemy is already destroyed so either destroy the bullet when that happens or let it keep moving along the last known direction.
Question: why do you recommend running the physics overlap onUpdate? Would it not be sufficient to run it once a tower can shoot (cooldown ready), thus only running when knowing what targets are in range matters for the shot? It would need to run on a timer or update while it's not on cooldown I suppose? Am I missing something?
Sure, you could optimize it to only look for targets when its ready to fire, but that will still run on every frame while waiting for enemies to get within range which may cause performance issues.
Great video! Fixed some problem that i had (Y)
On the Collider method, I would have checked Tags instead of the name of the script component. Feels more solid choice to me.
Tags are very brittle and error prone due to the fact that they are strings, you should not use tags to identify objects.
Great video! Love your content
Thanks! Glad you like it!
The video is very useful, and I didn't expect anything else. "CM is very cool. You just had to add about your method of finding the nearest enemy or I'm wrong and it will also work when several enemies appear at the same time at a distance of a shot ))) (perhaps there is a sequence inside "Unity", which element is detected first, etc ... or will all of them be attacked at the same time ? or will there be an error? )
Yes in the video I only handled detection, didn't worry about selection. You can easily add some more conditions if you want to target the closest out of multiple
Really good video.Thank you
Sir is there is any way to secure our assets (3d models and textures also Scenes) from tools like utineyripper, asset bundle extractor
You can try to protect it but there's no such thing as absolute protection.
Unless you have a very specific thing you need to protect I would say don't worry about it. Your game will be pirated no matter what.
Thanks for great video, can you clarify the following please;
I am not sure how true it is to say that "Collider Trigger" are not on update, I think it gives an illusion of it not being on any update, the event is constantly checking for collisions on physics update. Anyway this is what I was told, and what I experienced when I made an RTS game. but please do clarify if I have misunderstood, I think behind the scene its just spamming Physics overlap,(you can test this by disabling and enabling and object with onCollisionEnter/onTriggerEneter of an object that already has targets within range).
again please clarify if you think otherwise
I am not familiar with the inner workings of the Unity Physics System but a core part of any Physics system is how you don't constantly act on every single object on every single update. Instead it's extremely optimized to only test objects that might have potential collisions. If your object never sleeps then technically it might be working on every Update but for the most part your object will sleep when not needed and in those cases it usually is not part of any per-frame update.
@@CodeMonkeyUnity thank you for reply, I was also informed that Collision detection modes, are simply representing refresh rate (Update rate), which to me, makes a lot of sense, personally, I would love it if it was working the way you explained it, would reduce the processing cost dramatically. One thing you would notice, fast projectiles collision detection could become a problem, this can be reduced with continuous detection instead of discrete but it comes at a cost, similarly to moving a function from FixedUpdate to Update. This whole thing has been bugging me for a really long time. And I have gotten mixed information about this. At the end, I gave up on the project and decided only to revisit my RTS after I learn DOTS.
what about DOTS ECS 1.0 Targeting System Physic system ?
I might disagree with physics.overlapsphere be good performance. I build td currently and i put this method into stress test. After placing around 60towers on screen my fps tanks from 260 to 80. Fix was next. Use overlapspherenonaloc with mask. I skip all non related colliders and only count it, populating buffer array. Second one - brake iteration when u cath enemy in target. This was win and fps up to 220 in the same conditions.
Did you use the profiler to identify exactly what the issue was? I highly doubt it was the physics query, this is insanely fast. Sounds like the issue was in your for cycle and not the OverlapSphere, probably when sorting for closest.
Also remember that you don't have to test on every single Update (unless your enemies move insanely fast)
A super easy performance boost is to only find targets something like 10 times per second, and make the timers offset so different towers are looking for targets at different times.
@@CodeMonkeyUnity I ll look closely, and recreate this scenario. To see what exactly couse this issue. If u interested will provide detailed info. In profiler highly grow script time. And there was only towers on scene. I tested with enemies(like around couple hundreds) towers separately.
Can OnTriggerStay2D switch which collider it's detecting, if that collider doesn't meet a certain criteria?
I'm trying to switch target once a variable has changed in the current target. (two targets in total)
It's for a treasure chest, and the targets are units that the player controls.
It should detect whichever target is currently "active". (only one unit is active at a time)
The problem is that it doesn't update, if both units are already inside the trigger when the variable changes.
Example;
First unit enters trigger. Chest can open, as it detects the active unit.
Second unit is activated and enters trigger. Chest can open, as it detects the new active unit.
*First* unit is activated again. Chest *cannot* open, as it still checks the *second* unit. The first unit being active again is not detected.
What would be your approach on doing this for a turret in an isometric tilemap ? Loving your tower defense course btw!
I would probably use OverlapCircle, search for enemies about 3 times per second.
Thanks! I'm glad you're enjoying hte course!
Thank you 😌
Yay I need this
My approach to handle targeting? I don't! I let these videos handle it for me :D
But when push come to shove. I use distance since I don't need to add another component to my game objects.
Hello Sir, I am New to Unity 3d. When I am trying to import assets from unity asset store, the asset became pink in Colour. How can I Fix this issue. I using unity 2019. 4.13. Please help me!
It has to do with the Render Pipeline. You're probably using the Built-in pipeline and the asset uses URP or HDRP
i am curious as to what your set target function was
It just sets a targetTransform field and then on Update it tests if that is not null and counts down the shoot timer.
I covered how the tower works a bit more here ua-cam.com/video/Hp0ovwSC4FE/v-deo.html
@@CodeMonkeyUnity Thank You!! very helpful for my game, love your content and tutorials
Good day! What’s the main difference between using Shader Graph in Unity and writing unlit shader on your own using GLSL? Is the first variant optimized in comparison with second one?
Writing your own shaders will probably end up more performant than the ones made in Shader Graph.
But that's really on the most extreme use cases, most of the times Shader Graph is more than performant enough.
Thanks for great guide! Is there anyway to see that range in scene?
Draw a circle sprite and set the game object scale to match the range
@@CodeMonkeyUnity Wow, I didnt know actually scale size is coordinated with range number! :)
I didn't quite understand why calling GetComponent in a loop in Update is good performance
Im just wondering, What is the difference between getcomponent and trygetcomponent, because i’ve never seen trygetcomponant before?
GetComponent returns the component type or null if not found
TryGetComponent returns true if it finds a component and sets the out variable to that component, returns false if it does not find that component.
Its simpler to use TryGetComponent inside an if than to do GetComponent and then compare with null
I have to say that 2nd method feels wrong to me modeling wise, aside from the need to manually handle objects table, it sorts of a contradiction that a targeting system would allready know about all the enemies in the world, the other methods allow for the existence of a decection and target.
does anyone have a version of the second method where the turret targets the first enemy it sees until it dies or leaves the range even if there are more enemies in range?
You just store a field for the enemy, if that field is null you check for targets, when you find a target set that field, if the field is not null you don't check for targets and just attack that one. As you are attacking that one check the distance, if too far then reset that field to null
How would I check for different types of colliders?(on same object) Use box collider for body and sphere for head?
You can have multiple non-trigger colliders and a single trigger collider. If you have multiple trigger colliders you can't identify which one fired the event.
In that case you can add trigger colliders onto separate children game objects.
@@CodeMonkeyUnity oh right,I get you, thanks
For performance, is "physics overlap" the best?
Usually yes but depends on how many Physics objects you have in your world.
Thank you for answers.
I'll try to do overlap physics.
Best method is creating a hash grid
hello, I'm creating a drone game, where I have bows that must pass, 5 bows, all start in red, as it goes through the bow it turns green, you can't jump a bow, from 1 jump to 3 you can't, it goes red still, could help in this system, how to do?
Havent profiled it, but the second option seems terribly slow to me. For all the towers, you enumerate through all the enemies, and do branching and an expensive distance function.
Usually you would combine it with a timer in order to search much less often than once per frame.
But yes, as with anything it all depends on your particular scenario.
Thanks for all the tutorials. I find them very helpful in my learning.
I have a question. Is there a way to add enemies to a list that are only in view of the camera?
I have been able to set a trigger collider to follow the exact size and transform of the camera and add and remove them from a list as they enter or leave. My only issue is wheni move the player the camera follows which then has to continuously update the position of the trigger collider.
I fear this may be a very heavy way to implement this but can't figure out how to just use the camera viewpoint to achieve the same outcome.
Thanks
You can convert a World position into a Screen position with Camera.WorldToScreenPoint
Then you can do some math with Screen.width and Screen.height to find out if it's within the camera bounds.
@@CodeMonkeyUnity Thanks a lot. Ill give it a try :)
Hello, when will there be a video about multiplayer, preferably a guide
Currently I'm focused on researching Machine Learning so don't know when I'll get to Multiplayer
Sorry, but is this some sort of joke or some thing. When you display the text under the 3 ways to find targets. The heading and pro \ con text is readable. But the actual text for the rest of it is just random blocks, nothing the even resembles text, let alone readable. And yes, I have the video quality on HD!
Yes it's intentionally blurry in the beginning, then throughout the video I'm explaining everything and sum up all the pros and cons at 10:40
3 months ago i came up with the List system for my game, and it works fiine. However I used one List on each Object because I didnt know how to implement a public List ... In your example you use one public List in the Enemy class. But the Enemy class is on each enemy gameObject right? Doesnt that mean you have one List per enemy, each containing only itself, and not all?
The List is defined as static so there's only a single List
@@CodeMonkeyUnity Ah thats how static works, thank you. I solved my issue with events. Everytime an enemy spawns and dies every List will be updated. One static List seems now so simple ...
10:15 line 17 "foreach" is there a way to ask if the array has anything?
If it has anything? do List.Count > 0
If it has a specific object? do List.Contains();
Why have no timesteps?
Why don´t declare in the header that is a 2d tutorial ?
What's a timestep?
2D and 3D are 99% the same, just swap Physics2D for Physics and 2D components for 3D unitycodemonkey.com/video.php?v=3zxTigjJr24
Code Monkey
Is it possible to combine these methods?
Sure, you can for example do a distance check after doing a OverlapCircle()
Why would you try to get a component called Enemy? You're creating a component on the object named Enemy just for that line of code?... Why not just do the normal way of detecting things... y'know... comparetag?..
The Enemy component handles the Enemy, it's not being created in that line, it simply tries to get it and returns true if the object does have an Enemy component.
Tags are very brittle and error prone due to the fact that they are strings, you should not use tags to identify objects.
We want to see your face,Prnice.
first one is the easiest
hEY!
fIRST
pLS GIVE ME A HEART
PLS
@Mactavish haha yes