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 7 replies, 3 voices, and was last updated 2 weeks, 2 days ago by
Alp Apustaja.
-
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.
February 25, 2025 at 6:11 pm #17321::Hi Lukas! It looks like you’re on the right track with your code for detecting the closest enemy using
Physics2D.OverlapBoxAll
. However, there are a few things you can check to ensure everything works as expected. Let’s go over your code and fix potential issues.1. Check Layer Mask
Make sure that the “Monster” layer is correctly assigned to the enemy game objects in your scene. If the layer is not properly set,
Physics2D.OverlapBoxAll
won’t detect them.2. Overlap Box Size and Position
Ensure that the size of your overlap box and its position are correct. The size should encompass the area you expect to find monsters. You can also use
Debug.DrawLine
orDebug.DrawRay
to visualize the area you’re checking.3. Ensure Collider2D is Active
Make sure the colliders on the monsters are active and not marked as “Is Trigger” if you want them to be detected by
OverlapBoxAll
.4. Debugging
You can add some debug statements to see what colliders are being detected. For example:
private Collider2D[] GetMonsterColliders() { Vector3 size = new Vector3(40, 30, 1); Collider2D[] colliders1 = Physics2D.OverlapBoxAll(owner.transform.position, size, 0f, LayerMask.GetMask("Monster")); Debug.Log("Detected Monsters: " + colliders1.Length); foreach (var collider in colliders1) { Debug.Log("Detected Monster: " + collider.name); } return colliders1; }
5. Improving the Closest Enemy Logic
Your
GetClosestEnemy
method looks good, but ensure that you are passing in the colliders you get fromGetMonsterColliders
. Here’s how you can call it:void Update() { Collider2D[] monstersColliders = GetMonsterColliders(); Transform closestEnemy = GetClosestEnemy(monstersColliders); if (closestEnemy != null) { Debug.Log("Closest Enemy: " + closestEnemy.name); } }
Final Code Suggestion
Here is your code with the updates:
private Collider2D[] GetMonsterColliders() { Vector3 size = new Vector3(40, 30, 1); Collider2D[] colliders1 = Physics2D.OverlapBoxAll(owner.transform.position, size, 0f, LayerMask.GetMask("Monster")); Debug.Log("Detected Monsters: " + colliders1.Length); foreach (var collider in colliders1) { Debug.Log("Detected Monster: " + collider.name); } return colliders1; } Transform GetClosestEnemy(Collider2D[] monstersColliders) { Transform tMin = null; float minDist = Mathf.Infinity; Vector2 currentPos = owner.transform.position; foreach (Collider2D monsterCollider in monstersColliders) { float dist = Vector2.Distance(monsterCollider.transform.position, currentPos); if (dist < minDist) { tMin = monsterCollider.transform; minDist = dist; } } return tMin; } void Update() { Collider2D[] monstersColliders = GetMonsterColliders(); Transform closestEnemy = GetClosestEnemy(monstersColliders); if (closestEnemy != null) { Debug.Log("Closest Enemy: " + closestEnemy.name); } }
Summary
Make sure your layer masks, collider settings, and overlap box parameters are correct. Use debugging to see what colliders you are detecting and ensure that they are the expected ones. With these improvements, your closest enemy detection should work as intended! If you continue to experience issues, feel free to provide additional details for further assistance. Happy coding!
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: