Forum begins after the advertisement:
[Part 16] Auto-aiming weapon sometimes targets off screen enemy
Home › Forums › Video Game Tutorial Series › Creating a Rogue-like Shoot-em Up in Unity › [Part 16] Auto-aiming weapon sometimes targets off screen enemy
- This topic has 5 replies, 2 voices, and was last updated 3 days, 9 hours ago by Terence.
-
AuthorPosts
-
January 31, 2025 at 12:08 am #17168::
Here’s a great question from LukasKazda on our Part 16 video:
hi, i was wondering if we could attach a box collider to the player which covers 80% or the entire visible screen. enemies which enter the box collider get added to an list of possible targets (for auto aiming weapons), on exit they get removed from the list. this would not only benefit the lightning ring weapon, but also any other weapon we want to implement with auto aim, since the performance would be better (right? i am not sure about that lol). also my autoaiming weapon with the current system is firing off screen at random enemies because it sometimes uses off screen enemy as target. Thx for your effort!
January 31, 2025 at 12:28 am #17169::That’s a great question.
Whether limiting the picked targets to the visible area will be more optimal depends on how your game is set up, how many enemies there are, as well as how big the play area is. The thing about collision checks is, to determine whether objects are colliding, Unity has to cycle through every GameObject on the map and check whether they collide, and adding 1 more trigger collider means 1 more check through all the GameObjects in the Scene — unless the trigger performs some other purpose as well, it may not be the most efficient to add a collider just to do that. Unity uses broad-based collision detection to optimise collider interactions, but if you have a lot of enemies entering and exiting the trigger volume, it won’t be able to help a lot.
If you need to have the weapon only target visible enemy, a more effective way is to simply do a
Physics2D.OverlapBox()
whenever the weapon is cooled down. Since the weapon doesn’t fire every frame, this will optimise things by a lot, as compared to a trigger volume which has to be maintained every frame.Here’s an idea of how this can be done. Add
GetEnemiesOnScreen()
to your weapon script and call it to get all the enemies within your screen. The function works by drawing a box equal to the size of the camera, at the camera’s position.EnemyStats[] GetEnemiesOnScreen() { Camera cam = Camera.main; // Convert screen edges to world space Vector3 bottomLeft = cam.ScreenToWorldPoint(new Vector3(0, 0, depth)); Vector3 topRight = cam.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, depth)); // Get the center and size in world units Vector3 center = (bottomLeft + topRight) / 2f; Vector3 size = new Vector3(topRight.x - bottomLeft.x, topRight.y - bottomLeft.y, depth); // OverlapBox call to get colliders Collider[] colliders = Physics.OverlapBox(center, size / 2f, Quaternion.identity, enemyLayer); // Filter for GameObjects that have the EnemyStats component return colliders .Select(c => c.GetComponent<EnemyStats>()) // Get EnemyStats component .Where(es => es != null) // Ensure it's not null .ToArray(); // Convert to array }
Let me know if you have any further questions.
January 31, 2025 at 4:11 am #17170::I understand, thank you for the explaination and for providing a better solution! :)
- 1 anonymous person
February 1, 2025 at 10:25 pm #17174::so, i tried for the past 15 hours to get “closest enemy” Detection to work and this is what i ended up with:
private Collider2D[] GetMonsterColliders() { //just some random values (its the size of my screen i believe xD 40 width, 30 height) Vector3 size = new Vector3(40, 30, 1); Collider2D[] colliders1 = Physics2D.OverlapBoxAll(owner.transform.position, size , 0f, LayerMask.GetMask("Monster")); print(colliders1.ToString()); return colliders1; } Transform GetClosestEnemy(Collider2D[] monstersColliders) { Transform tMin = null; float minDist = Mathf.Infinity; Vector2 currentPos = owner.transform.position; foreach (Collider2D monsterCollider in monstersColliders) { //print(monsterStats.ToString()); float dist = Vector2.Distance(monsterCollider.transform.position, currentPos); if (dist < minDist) { tMin = monsterCollider.transform; minDist = dist; } } return tMin; }
For some reason i had big troubles drawing a overlapbox, thats why i used those values in the size variable instead of the camera code
February 1, 2025 at 10:27 pm #17175::now i remember, the issue i had with the overlapbox was that physics.overlapbox did not detect anything, i had to change everything to its 2D version. so Physics2D.overlapbox and Collider2D[] and so on
February 1, 2025 at 10:41 pm #17176::i tested the camera code part of yours now and it works perfectly fine! thanks again! :)
February 2, 2025 at 3:27 pm #17178::@LukasKazda great to hear you got everything to work! Feel free to make another post if you have further questions.
-
AuthorPosts
- You must be logged in to reply to this topic.