Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by TheEmeraldRuby · Aug 31, 2018 at 04:03 PM · physics2dcollider2ddetectionoverlaprandom spawn

How to Detect if a Collider is in the Area, Move Away, Rinse and Repeat?

Hello, everyone. In my 2D game, since I couldn't figure out how to prevent them from originally spawning on top of each other, a few random platforms are generated within a certain area by an empty gameobject. Once they spawn in, I want them to detect if there are other platforms within a certain distance using Physics2D.OverlapCircleAll(transform.position, radius);. The platforms have edge colliders. If they detect one or more other platforms within the circle, they will teleport a random position, rinse and repeat. However, instead of doing what I meant to happen, they just teleport all over the screen or don't do anything after spawning in, regardless to whether they're touching another platform or not. I don't understand why. Here is the code attached to the platform prefab:

 using System;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class PlatformCfg : MonoBehaviour {
 
     bool canStayHere = true;
     float height = 2;
     float radius = 2;
     float width = 2;
 
     Collider2D[] colliders;
 
     // Use this for initialization
     void Start () {
 
     }
 
     // Update is called once per frame
     void Update()
     {
         CheckForPlatforms();
 
         if (!canStayHere)
         {
             Displace();
         }
     }
 
     void CheckForPlatforms()
     {
         colliders = Physics2D.OverlapCircleAll(transform.position, radius);
         if (colliders.Length >= 1)
         {
             canStayHere = false;
             Array.Clear(colliders, 0, colliders.Length);
         }
         else canStayHere = true;
     }
 
     void Displace()
     {
         float randX = UnityEngine.Random.Range(transform.position.x - width, transform.position.x + width);
         float randY = UnityEngine.Random.Range(transform.position.y - height, transform.position.y + height);
         transform.position = new Vector2(randX, randY);
     }
 }

If anyone can tell me why this happens and how to fix this, I would be thankful. If you have a better solution to prevent the platforms from spawning too close to each other, please tell me! Thank you.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Ermiq · Sep 01, 2018 at 01:43 PM

You should somehow prevent the CheckFoPlatforms() execution on the platforms which are already placed. Because, as it is now, both platforms (that one which was at the place and the new one) will jump from this place 'cause they both detect that they can't stay here.
Also, you should add some check to be sure the platform can't detect itself. I would do this like that:

 colliders = Physics2D.OverlapCircleAll(transform.position, radius);
 canStayHere = true; // if something will be detected in next code,
     // then it will be 'false', otherwise it'll stay 'true'
     foreach (Collider col in colliders) {
         if (col.transform //just to be sure that collided object has an actual transform
             && col.transform != transform) // check if it's not this platform itself
             canStayHere = false;
             Array.Clear(colliders, 0, colliders.Length);
             //forcibly exit the foreach statement as we already know what we need
             break;
         }
     }



UPDATE:

To prevent unnessesary checks I would make the platforms instantiation code as a coroutine, so every new platform would be instantiated in new frame, and not all at once.
Don't know how exactly you instantiate the platform prefabs in the scene, so I just assume that you use some array or a number of places which determines how much platforms should be instantiated:

 private IEnumerable SpawnPlatforms (int quantity) {
     for (int i = 0; i < quantity; i++) {
         // instantiate one of the platforms here
         // and take a pause until the next 'Update()'
         yield return new WaitForEndOfFrame();
     }
 }
 private SomeMethod () {
     // that's how you start the coroutine
     StartCoroutine (SpawnPlatforms (5));
 }


Now, the platforms could be placed in some order, one by one, frame by frame. And there's no risk of detecting each other, no mess, everything is ordered.


Lets go further and make it so platform could be placed and will not be displaced when another platform instantiated within the circle.
To do this, you should make so this another platform checks the place and doesn't take the place unless it's sure that the place is not occupied.
So, CheckForPlatforms() should be modified, so it takes some position, checks it and returns true if the platform can go there.

 bool CheckForPlatforms (Vector2 positionToCheck)
 {
     colliders = Physics2D.OverlapCircleAll (positionToCheck, radius);
     if (colliders.Length >= 1)
     {
         // if the 'positionToCheck' is already occupied by some platform
         return false;
     }
     else return true;
 }

Also, makes it so the platform checks it's current place in its Start() so it could check if the spawn point is occupied. And if it's occupied, try to find new place to jump there:

 void Start () {
     if (!CheckForPlatforms (transform.position)) // if spawn point is occupied already
     {
         Displace (transform.position);
     }
     // otherwise, if the spawn point is not occupied, the platform will stay here and never go away
     // because the 'Start()' is called only once when the platform is instantiated,
     // so the platform won't check anything in the future.
 }
 void Displace(Vector2 currentPosition)
 {
     // some random position relative to 'currentPosition' parameter
     Vector2 randomPos;
     float randX = UnityEngine.Random.Range (currentPosition.x - width, currentPosition.x + width);
     float randY = UnityEngine.Random.Range (currentPosition.y - height, currentPosition.y + height);
     randomPos = new Vector2 (randX, randY));
     // check this random position
     if (CheckForPlatforms (randomPos) { // if it's not occupied
         // take this place
         transform.position = randomPos;
     }
     // otherwise, try to find another place relative to this randomPos
     // since it's occupied, so the platform can't be placed here
     else Displace (randomPos);
 }

So, the platform will be trying to find free space, everytime the randomPos is occupied, the platform will call Dispace() again sending new positions in this method to look for another places.
Once the randomPos is not occupied, the platform will go there and stay there.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image TheEmeraldRuby · Sep 01, 2018 at 05:42 PM 0
Share

@Ermiq Doesn't this block of code prevent the execution once it has not detected any colliders for a frame? if (!canStayHere) { Displace(); }

Once canStayHere is true, the function never runs again, meaning it can never be set back to false unless by other means. Is there a flaw I just don't notice?

avatar image Ermiq TheEmeraldRuby · Sep 01, 2018 at 06:08 PM 0
Share

How I see it:
The platform is placed at the spawn position in Update(), another platform is placed in the same position in its own Update().
In the next frame CheckForPlatforms() is called on both 1st platform and 2nd one. Both platforms detect that something else is here and both of them get canStayHere = false, both of them call their Displace().
Next frame. Platforms are getting their new positions and both are calling CheckForplatforms(). There's nothing that could prevent them from checking it once they have been placed. So, if all of a sudden they both were displaced at the same new direction or some other platforms are already placed there, they all detect something in the circle again, and all of them get canStayHere = false again.
Rinse and repeat. :)

avatar image TheEmeraldRuby Ermiq · Sep 01, 2018 at 06:30 PM 0
Share

@Ermiq How would I do that? I tried calling CheckForPlatforms() inside the if (!canStayHere){} statement, but that did nothing. What exactly would I do to tell it not to run again?

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

94 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Performance of player detection: Colliders/Triggers vs OverlapCircle 2 Answers

Physics2D.OverlapCircleAll and OverlapCapsuleAll behaves differently? 0 Answers

Physics2D.OverlapArea inaccurate? 2 Answers

Physics2D.OverlapBoxAll and Physics2D.OverlapAreaAll are inaccurate. 0 Answers

How to use OverlapCollider? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges