Search Unity

How to make object not-move within area of another object before it makes first step?

Discussion in 'Scripting' started by Anon1234, Apr 27, 2015.

  1. Anon1234

    Anon1234

    Joined:
    Feb 17, 2014
    Posts:
    78
    I'm having ObjectX, that orbits ObjectY. How it does that, is it takes Random.Range, and applies it to distance and angle. Then it moves over there, problem is, the ObjectX cannot be too close to ObjectY. But I can't think of a way to stop it from moving through ObjectY. ObjectY is relatively small, but it's "orbit" is bigger (I dare to say that ObjectY and it's orbit are on scale on this image).

    Lots of pep talk, how can I detect, whether it's Vector2.Lerp movement will go through orbit of ObjectY? And how to forbid it? How to execute the "ChangeVars()" when it turns out that it's Vector2 is past ObjectY's orbit?

    It may be not fully understandable, that's why I made image, which should be able to partially explain it.



    On red. Execute ChangeVars(). How to?
     
    Last edited: Apr 27, 2015
  2. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    If you reframe the problem, all you're asking is weather or not objectX is within a radius around objectY:

    Code (CSharp):
    1. bool IsWithinRadius(GameObject other, float radius) {
    2.    
    3.      Vector3 relPos = transform.position - other.transform.position;
    4.      return relPos.magnitude <= radius;
    5.  
    6. }
    7.  
    8. void Update() {
    9.    
    10.      if (IsWithinRadius(objectY, 10f))
    11.           ChangeVars();
    12.  
    13. }
     
    Anon1234 likes this.
  3. Anon1234

    Anon1234

    Joined:
    Feb 17, 2014
    Posts:
    78
    Sorry for my bad English, I'm not Anglo-phone so I don't precisely know how to form my sentences properly.

    But that's not exactly what the "problem" is. The problem is, that I need to call ChangeVars() if Unity will find out that next Vector2.Lerp will bring ObjectX through ObjectY's orbit.

    Not when ObjectX already will be there.
    But before the ObjectX will even attempt any movement.

    If you look at the picture, if the movement will go past ObjectY's orbit, I need to call ChangeVars() that's why it's red, because in future, within 10 seconds, it's about to go through ObjectY's orbit, that's why ChangeVars() is called, to change variables into something else to not allow ObjectX come into ObjectY's orbit, into another Vector2, which then again will be tested for this.

    Once again, sorry for my incomplete English, still trying to my best to bring words a proper form.
     
  4. hamsterbytedev

    hamsterbytedev

    Joined:
    Dec 9, 2014
    Posts:
    353
    You'll need some math for that calculation.
     
  5. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    Ah, I see! Well then, once again to reframe your question, you're asking for the equation to determine weather a line intersects a circle. You COULD do a Physics2D.Raycast, but that would require a circle collider being on your other gameObject, but it would probably be less resource intensive to use an algorithm that doesn't depend on the physics system.

    This is a formula that I found on stackoverflow that does the trick. I have no idea how it works:
    Code (CSharp):
    1.     bool LineIntersectsCircle(Vector2 lineStart, Vector2 lineEnd, Vector2 circleCenter, float circleRadius) {
    2.  
    3.         Vector2 d = lineEnd - lineStart;
    4.         Vector2 f = lineStart - circleCenter;
    5.  
    6.         float a = Vector2.Dot( d, d ) ;
    7.         float b = 2f * Vector2.Dot( f, d ) ;
    8.         float c = Vector2.Dot( f, f ) - circleRadius * circleRadius ;
    9.      
    10.         float discriminant = b * b -4 * a * c;
    11.  
    12.         if( discriminant < 0f )
    13.             return false;
    14.      
    15.         else {
    16.             discriminant = Mathf.Sqrt( discriminant );
    17.  
    18.             float t1 = (-b - discriminant)/(2*a);
    19.             float t2 = (-b + discriminant)/(2*a);
    20.          
    21.             if( t1 >= 0 && t1 <= 1 )
    22.                 return true ;
    23.  
    24.             if( t2 >= 0 && t2 <= 1 )
    25.                 return true ;
    26.  
    27.             return false ;
    28.         }
    29.     }
    Your use case:


    Code (CSharp):
    1.     void Update () {
    2.  
    3.         if (LineIntersectsCircle(transform.position, nextLerpPosition, objectY.transform.position, objectYRadius))
    4.             ChangeVars();
    5.  
    6.     }
     
    Fajlworks and Anon1234 like this.
  6. Anon1234

    Anon1234

    Joined:
    Feb 17, 2014
    Posts:
    78
    Exactly! It works precisely great! Or I've been quite lucky that it never Random.Ranged over ObjectY's orbit.

    Thanks! You saved hours of work.
     
  7. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    I should also point out that your english is pretty damn good. I didn't read your first post carefully enough, that's all.