0
\$\begingroup\$

I'm using Unity version 5.3.5.

I'm having problems to synchronize the movement of three different objects from point A to point B and vice versa. To move the objects I use the following code:

public float time;
public Vector3 endPos;
private Vector3 startPos;

 void Start()
 {
     startPos = transform.position;
 }

 void FixedUpdate()
 {
     if(transform.position == startPos)
     {
         StartCoroutine(Move(gameObject.transform, startPos, endPos, time));
     }
     if(transform.position == endPos)
     {
         StartCoroutine(Move(gameObject.transform, endPos, startPos, time));
     }
  }

 public IEnumerator Move(Transform thisTransform, Vector3 startPosition, Vector3 endPosition, float time)
 {
     float i = 0f;
     float rate = 1/(time);
     while(i < 1)
     {
         i += Time.deltaTime * rate;
         thisTransform.position = Vector3.Lerp(startPosition, endPosition, i);
         yield return null;
     }
 }

As long as all of the objects have the same "time" value, their movements is correctly synchronized regardless the distance that they have to cover. The problems arises when they all have different "time" value. For example, if they have to move backwards and forwards from startPos(0,0,0) and endPos(5,0,0) with the following "time" value:

  • Object A time = 1 second
  • Object B time = 2 second
  • Object C time = 4 second

After 4 second, they should all be again at the same start position. However, what happen is that the fastest object (Object A) has a delay over the other two and this delay increase over time.

How can i fix this problem?

\$\endgroup\$
  • \$\begingroup\$ Are they supposed to loop back and forth infinitely? How many times, on average, is Move()s yield return reached for the object a,b and c? e.g. add two counters private int callCount, yieldCount = 0; public Move(...) { int yc = 0; ... while (i < 1) { ... yc++; yield return null; } callCount++; yieldCount += yc; } and I would be interested what float averge = (float)yieldCount / callCount; for individual objects after a while running. \$\endgroup\$ – wondra Jul 3 '16 at 21:56
  • \$\begingroup\$ They are supposed to move until a certain event is triggered. Usally the event happens within 3 minutes. I checked the average time that you asked for the three object after five minutes: Object A = 60,99661 Object B = 121 Object C = 241.9865 \$\endgroup\$ – RationeUtor Jul 4 '16 at 19:33
  • \$\begingroup\$ Not what I was expecting, but will post my guess what is wrong anyway - it might be helpful. \$\endgroup\$ – wondra Jul 5 '16 at 13:10
0
\$\begingroup\$

I would say the reason is there is small numeric error in position computation. Because you i += the error starts accumulating resulting in out-of-sync after some time. In order to overcome this, I would suggest a different implementation. Try calculating the position from total time on move:

public float startTime;
public float time;
public bool move = true;

void Start()
{
   //you probably want to re-set the start time if you resume moving later
   startTime = Time.time; 
}

void FixedUpdate()
{
   if(!move) return;
   float delta = Time.time - startTime; //note: not Time.deltaTime
   //get remainder for round trip
   float tripTime = Mathf.Repeat(delta, time * 2.0f/*time back and forth*/); 
   if(tripTime < time) //from start to end
   {
      thisTransform.position = Vector3.Lerp(startPosition, endPosition, (tripTime / time));
   }
   else //from end to start, tripTime is between (1.0, 2.0)
   {
      //subtract 1 to get into (0.0, 1.0) range, and 1 to reverse movement
      thisTransform.position = Vector3.Lerp(startPosition, endPosition, 2.0f - (tripTime / time));
   }
}

note: code not tested, but I hope you get the idea

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.