function behaves unexpectedly inside a coroutine.

the function look like this:

private void Shrink(Animation anim)
    {
        AnimationClip clip = new AnimationClip();
        clip.legacy = true;

        char[] c = { 'x', 'y', 'z' };
        float rot = Random.value * 360 - 180;
        Vector3 toPosition = transform.position + (Random.value * radius * 5 / 6 + radius / 6) * new Vector3(Mathf.Cos(rot), Mathf.Sin(rot));
        float scaleMul = Random.value / 4 + 1.0f / 2.0f;
        float duration = (transform.position - toPosition).magnitude / speed;
        for (int i = 0; i < 3; i++)
        {
            Keyframe[] keys;
            keys = new Keyframe[2];
            keys[0] = new Keyframe(0.0f, transform.position*);*

keys[1] = new Keyframe(duration, toPosition*);*
curve = new AnimationCurve(keys);
clip.SetCurve(“”, typeof(Transform), “localPosition.” + c*, curve);*
}
for (int i = 0; i < 3; i++)
{
Keyframe[] keys;
keys = new Keyframe[2];
keys[0] = new Keyframe(0.0f, transform.localScale*);*
keys[1] = new Keyframe(duration, transform.localScale * scaleMul);
curve = new AnimationCurve(keys);
clip.SetCurve(“”, typeof(Transform), “localScale.” + c*, curve);*
}

// now animate the GameObject
anim.AddClip(clip, clip.name);
anim.Play(clip.name);
}
all it does is that it sort of animate the shrinking of a border and moving it to some random location inside a radius. the function works fine if I call it on its own but I want the function to be called every x seconds so I wrote this coroutine:
IEnumerator ShrinkCR(float time)
{
for (int i = 0; i < 3; i++)
{
yield return new WaitForSeconds(time);

Shrink(anim);
}
}
and simply called it inside update():
private void Update()
{
StartCoroutine(ShrinkCR(10));
}
but when I do that the border goes crazy and instead going to some random location inside some radius it just accelerate to the right indefinitly. What did I do wrong???

The way you have your code set up in nested layers is creating multiple versions of your coroutine that all run at the same time. The end result is that in each frame, your code creates multiple new animations, and multiple calls to anim.Play, creating the janky motion that you are seeing.

In detail, this is what happens:

Frame 1:

  • Update starts your Coroutine for the first time. We’ll call this Coroutine #1. That coroutine runs Shrink, which creates an animation, and starts to play that animation. So far, so good.

Frame 2:

  • Update starts up a fresh version of your coroutine. We’ll call this Coroutine #2. Coroutine #2 runs Shrink, which creates a new animation, and starts to play that new animation.

{Time passes}

Frame at time seconds:

  • Update starts up a fresh version of your coroutine. We’ll call this Coroutine X. Coroutine X runs
    Shrink(), which creates a new animation, and starts to play that new animation.
  • AND, because time seconds have passed, Coroutine #1 wakes up. The loop in Coroutine #1 continues onwards, with i=1. It runs Shrink, which creates yet another new animation, and starts to play that new animation.
  • Punchline of Frame at time seconds: Shrink is called two times, which means you create two new animations, an start playing both of them.

And things just get more complicated from there …

My advice: Move your StartCoroutine(ShrinkCR(10)) to Start(). That way, you get just one instance of your coroutine, and it runs Shrink once every time seconds. Alternately, you could call InvokeRepeating in Start(). With InvokeRepeating, you get the same effect, but with slightly simpler code.

Don’t call StartCoroutine() in Update(). That could start hundreds of separate coroutines a second. Call it once from Start() or some other method when you want it to run.