Search Unity

Moving GameObjects, Calculating direction, cardinal coordinates

Discussion in 'Getting Started' started by vegetamaker, Apr 17, 2017.

  1. vegetamaker

    vegetamaker

    Joined:
    Feb 28, 2017
    Posts:
    37
    Hello! Again thanks so much for your help. I am still learning and practicing and I must admit that I can't advance without a little help. Or maybe alot, I am not sure.

    Let me start explaining my actuals problem, but first a look for what I am trying to do, more or less:


    Now let's start.

    I did a static StartPosition and EndPosition just for not be totally stopped. And managed to do the movement for all my GameObject in the Update, but it isn't very smoother.

    After it I did it in with a couritine thanks to other user that help me before.


    Code (CSharp):
    1.  
    2. IEnumerator ObjectMover(GameObject obj)
    3.     {
    4. float progress = 0;
    5.         while(progress < 1f)
    6.         {
    7.             progress += Time.deltaTime * speedItems;
    8.             obj.transform.position = Vector3.Lerp(startPosition, finishPosition, Mathf.Clamp(progress, 0, 1));
    9.             yield return null; //Wait until next frame to process again
    10.         }
    11.         Destroy(obj);
    12. }
    13.  
    This code, effectively, move my GameObjects smoother, but with two problems: They "teleports" to a startPosition instead their first random position AND they arrives all at same time to the FinishPosition.

    So, thinking from my novice knowledge, that they all arrive at same time is "progress" var faults AND that they "teleports" to startPosition is "Lerp" faults because it have a "startPosition".

    So I did the next:
    Code (CSharp):
    1.  
    2. IEnumerator ObjectMover(GameObject obj, Vector3 originalObjPosition)
    3.     {
    4. float fullDistance = Vector3.Distance (startPosition.transform.position, finishPosition.transform.position);
    5. float relativeDistance = Vector3.Distance (originalObjPosition, finishPosition.transform.position);
    6. float progress = relativeDistance / fullDistance;
    7.         while(progress < 0.95f)
    8.         {
    9.             progress += Time.deltaTime * speedItems;
    10.             obj.transform.position = Vector3.Lerp(originalObjPosition, finishPosition, Mathf.Clamp(progress, 0, 1));
    11.             yield return null; //Wait until next frame to process again
    12.         }
    13.         Destroy(obj);
    14. }
    15.  
    First I did a little code for check the Distance between FullDistance and relativeDistance. If we divide both we get the progress between 0 and 1.

    And changed the Lerp for use the obj Original Position.

    I changed too the while because, sometimes, they just keep so many time to dissapear, dunno why.

    Well, the result is... strange. They all teleports very close to FinishPosition, but finally they don't disappear at same time.

    If I use the same code but use again the StartPosition in the lerp the result is that all of my GameObjects teleport to the middle, making a perfect line/queue.

    At this point, dunno what I could try.

    -------------

    The next question is the direction. For now my objects are moving exactly from A to B, but I want really they move in a direction, with a constant speed.

    And when they arrive a certain point must be destroyed. Maybe this point should be the edge of a imaginarie circle (I am using already radius for generate my items around a point. I guess I could manage it).

    But anyway the point is.... How to move GameObjects in a direction?

    --------------

    Just continuing with the direction. I really don't want the StartPosition and the FinishPosition (they are for now two empty GameObjects placed where I want them exactly).

    The goal is make a combo-box with cardinals points. (Already done)

    So per example. If the user select "North" then the GameObjects should move to "South" (I know there aren't "really" cardinals points, they are just how we see it).

    Once time selected the North the program should calculate the Start Position as a Vector3 at a point in the edge of that imaginarie circle and the South just the oposite side.

    And then it should calculate the direction from where my GameObjects where start to move and where will finish.

    I tryed do it already, but the distance between points aren't correct. I am missing something here:

    Code (CSharp):
    1.     void PlacingTheStartAndFinishPositionInTheirFinalPositions(string coordinate)
    2.     {
    3.         switch (coordinate)
    4.         {
    5.         case "West":
    6.             startPositionVector = new Vector3 (radius, middlePoint.transform.position.y, 0);
    7.             finishPositionVector = new Vector3 (radius*-1, middlePoint.transform.position.y, 0);
    8.             break;
    9.         case "NorthWest":
    10.             startPositionVector = new Vector3 (radius, middlePoint.transform.position.y, radius);
    11.             finishPositionVector = new Vector3 (radius*-1, middlePoint.transform.position.y, radius*-1);
    12.             break;
    13.         case "North":
    14.             startPositionVector = new Vector3 (0, middlePoint.transform.position.y, radius);
    15.             finishPositionVector = new Vector3 (0, middlePoint.transform.position.y, radius*-1);
    16.             break;
    17.         case "NorthEast":
    18.             startPositionVector = new Vector3 (radius*-1, middlePoint.transform.position.y, radius);
    19.             finishPositionVector = new Vector3 (radius, middlePoint.transform.position.y, radius*-1);
    20.             break;
    21.         case "East":
    22.             startPositionVector = new Vector3 (radius*-1, middlePoint.transform.position.y, 0);
    23.             finishPositionVector = new Vector3 (radius, middlePoint.transform.position.y, 0);
    24.             break;
    25.         case "SouthEast":
    26.             startPositionVector = new Vector3 (radius*-1, middlePoint.transform.position.y, radius*-1);
    27.             finishPositionVector = new Vector3 (radius, middlePoint.transform.position.y, radius);
    28.             break;
    29.         case "South":
    30.             startPositionVector = new Vector3 (0, middlePoint.transform.position.y, radius*-1);
    31.             finishPositionVector = new Vector3 (radius, middlePoint.transform.position.y, radius);
    32.             break;
    33.         case "SouthWest":
    34.             startPositionVector = new Vector3 (radius*-1, middlePoint.transform.position.y, radius*-1);
    35.             finishPositionVector = new Vector3 (radius, middlePoint.transform.position.y, radius);
    36.             break;
    37.         }
    38.  
    39.         Debug.Log("Distance" + Vector3.Distance(startPositionVector,finishPositionVector));
    40.  
    41.     }
    Of course this code isn't correct. The Distance should be always the same if it is done correctly (diametre). I should work more with it, but for now I let this here waiting for better ideas.

    Btw, the Y axis isn't important at all, they are predefinide with other variable (middlePoint).

    ----

    And I guess that is all. Thanks so much for your help. I should go sleep a bit ^^.
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    OK, this looks like you just want an object to move directly to the right (i.e. in the +x direction) until it reaches the same X position of endPosition, and then it should be destroyed. This is pretty easy to do:

    Code (CSharp):
    1.  
    2.     [Tooltip("Movement speed, in units/second")]
    3.     public float speed = 2f;
    4.    
    5.     [Tooltip("End position we're moving towards (only X matters)")]
    6.     public Transform endPosition;
    7.    
    8.     [Tooltip("Flag to set to true when you want it to move!")]
    9.     public bool moving;
    10.  
    11.     void Update() {
    12.         if (moving) {
    13.             transform.position += Vector3.right * speed * Time.deltaTime;
    14.             if (transform.position.x > endPosition.position.x) {
    15.                 // all done!
    16.                 Destroy(gameObject);
    17.             }
    18.         }      
    19.     }
    Yeah. For what you're trying to do here, Lerp just isn't a good fit.

    Simply add something to their transform position (as I show above).

    You're still in the "magical" phase of your development, where you treat code snippets as incantations that cause things to happen, without really understanding. That's normal, but you must try to get out of it. There is no magic here. Transform.position is just a Vector3 (i.e. a combination of X, Y, and Z position), and you can do whatever you want to it, causing the object to change position. You can double the X and multiply the Y by 3.14. Or you can swap X and Z. Or you can use some function involving Mathf.Sin and Time.time to move your object in a sine wave.

    Or you can simply add a small amount each frame, causing your object to move in a straight line.

    OK, this is clearly different from what you described at the start of your post, and I don't fully understand it. But hopefully now you have the insight you need to do it. Don't bother with Lerp, and you should probably avoid coroutines as well (they are advanced magic). Just figure out where (or in which direction) you want to go, and add some appropriate small vector to your transform.position on each frame. Then figure out how to tell when you've gone far enough, and destroy the object.

    Best,
    - Joe
     
  3. vegetamaker

    vegetamaker

    Joined:
    Feb 28, 2017
    Posts:
    37
    Hello JoeStrout. Again thanks so much for your time and helps.

    Well, that was only an example.


    Really sorry. Trying explain it, but I faliled. Let me try again.

    I am creating a X amount of game objects (user can edit it in the Editor).
    They are created, selected from alist what GameObjects are and placed in an area:

    Code (CSharp):
    1.     //Instantiating Items and Adding them to a list.
    2.     List <GameObject> AddingItems()
    3.     {
    4.         List<GameObject> theItemList = new List<GameObject> ();
    5.         for (int xx= 0; xx < howManyItems; xx++)
    6.         {  
    7.             GameObject item = (GameObject)Instantiate (itemsTypeList [Random.Range (0, itemsTypeList.Count)]);      
    8.             item.transform.parent = middlePoint.transform;
    9.             item.transform.position = RandomPositionForItems ();  
    10.             item.transform.localScale = RandomScaleForItems (item);
    11.             item.transform.eulerAngles = RandomRotationForItems (item);
    12.             theItemList.Add (item);
    13.         }
    14.         return theItemList;
    15.     }
    And in this case the method that should be considered is the RandomPositionForItems. For this one I needed relearn about trigonometry, still trying to fully understand it. I only copied two things almost completely, this (I failed physics many years ago ^^). I added later the voidArea in the random.Range for X and Z (just for a "donut"/bagel effects when positioning the items).

    Code (CSharp):
    1.     //Give an item a random vector3, Y coord is static.
    2.     Vector3 RandomPositionForItems()
    3.     {
    4.         float radian = Random.Range(0f, Mathf.PI*2); // Calculates radians and a random degrees.
    5.         float x = Mathf.Round(Mathf.Cos(radian) * Random.Range(voidArea, radius));
    6.         float z = Mathf.Round(Mathf.Sin(radian) * Random.Range(voidArea, radius));
    7.         Vector3 position = new Vector3 (x, middlePoint.transform.position.y, z);
    8.         return position;
    9.     }
    I was using the courutine because the update, sometimes, was making the fps very bad (because I want to generate many GameObjects, 500 or more. It will depend completly the size of the prefabs chosen.

    ----

    And finally we arrive where the problems appears and what I asked for ^^.

    I want a "flow" effect with all my GameObjects. I mean they must be destroyed when go far away and appear again in the oposite side.

    For that effects, for now, I was using two empty GameObjects called EndPosition and StartPosition. But the idea is that they are generated automatically when selecting the direction (I guess I can manage todo it).

    ---

    Wow, actually writing neatly the problems that need solving helps a lot to know how to proceed and what to look for. I think I can solve this particular point on my own, I just need to better understand the trigonometry part.

    So I think the most important thing right now is to decide if the Update moving all those GameObjects will be enough to move them without affecting the FPS of the game. In some tests they were suffering alot.

    By the way, I think I did not say it, but the project is 3D, but I guess isn't important right now.

    ---

    Again thanks so much. You help is always welcome and greatly appreciated.
    And sorry for my English, isn't my natural language and sometimes I don't write it very well.

    I'll continue practicing :)
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Great stuff! Yes, the effort of clearly describing your problems often gives you what you need to solve it yourself. (See Rubber Duck Debugging, though I prefer the term Confessional Debugging.)

    I'm just going to respond to this part:

    This is based on a misconception. Coroutines are no better (or worse) for performance than using Update. Under the hood, Unity is invoking your Coroutines in exactly the same way as the Update methods. So choose what seems simplest and easiest to understand, and if you run into performance problems, then we can talk about how to tackle that.

    Best,
    - Joe
     
  5. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Your English is excellent by the way. You should see me struggling in Japanese!
     
  6. vegetamaker

    vegetamaker

    Joined:
    Feb 28, 2017
    Posts:
    37
    Hello JoeStrout. Thanks so much for your answer. Very interesting! Sorry for no reply before, was really busy at work. I'll continue practicing when finish :3

    Oh well, Japanese is really hard!