Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Recursive Coroutine Freeze my game, massive GC allocations

Discussion in 'Scripting' started by VeryHotShark, Dec 5, 2018.

  1. VeryHotShark

    VeryHotShark

    Joined:
    Mar 11, 2017
    Posts:
    13
    Hi guys !
    i'm currently working on project for my school and basically i have a script for my Spike Platform which :

    1. wait at the beginnig for x seconds
    2. moves it along local Z direction for specified amount
    3. wait at destination for x seconds
    4. comes back to initial position
    5. waits again and the process repeat

    I do it all inside a coroutine where at the end of the routine and start it again . and i want this process to repeat forever which it does but after some time it allocates some much GC to the point that unity crashes.

    Here is a picture of how much it allocates memory from profiler (sorry for the picture taken by phone)

    https://ibb.co/2dHbKR0

    And here is my code :

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class TrapMovement : MonoBehaviour
    6. {
    7.     public float moveUnit;
    8.     public float moveTime;
    9.     public AnimationCurve moveCurve;
    10.     public float returnTime;
    11.     public float startYieldTime;
    12.     public float destinationYieldTime;
    13.     public float returnWaitTime;
    14.  
    15.     Vector3 startPos;
    16.     Vector3 endPos;
    17.  
    18.     bool returning = false;
    19.  
    20.     WaitForSeconds yieldTime;
    21.     WaitForSeconds yieldReturnTime;
    22.     WaitForSeconds yieldDestinationTime;
    23.  
    24.     void Start()
    25.     {
    26.         Init();
    27.     }
    28.  
    29.     void Init()
    30.     {
    31.         startPos = transform.localPosition;
    32.         endPos = startPos + transform.forward * moveUnit;
    33.  
    34.         yieldTime = new WaitForSeconds(startYieldTime);
    35.         yieldReturnTime = new WaitForSeconds(returnWaitTime);
    36.         yieldDestinationTime = new WaitForSeconds(destinationYieldTime);
    37.  
    38.                 StartCoroutine(StartYieldTime());
    39.     }
    40.  
    41.     IEnumerator StartYieldTime()
    42.     {
    43.         yield return yieldTime;
    44.         StartCoroutine(MoveToDestination(returning));
    45.     }
    46.  
    47.     // Update is called once per frame
    48.     IEnumerator MoveToDestination(bool isReturning)
    49.     {
    50.         float curvedPercent = 0f;
    51.         float percent = 0f;
    52.         float speed = 1f / (isReturning ? returnTime : moveTime);
    53.  
    54.         Vector3 start = isReturning ? endPos : startPos;
    55.         Vector3 end = isReturning ? startPos : endPos;
    56.        
    57.         while(percent < 1f)
    58.         {
    59.             percent += Time.deltaTime * speed;
    60.             curvedPercent = moveCurve.Evaluate(percent);
    61.             transform.localPosition = Vector3.Lerp(start, end, isReturning ? percent : curvedPercent);
    62.  
    63.  
    64.             yield return null;
    65.         }
    66.  
    67.        
    68.  
    69.         yield return (isReturning ? yieldReturnTime : yieldDestinationTime);
    70.  
    71.         returning = !returning;
    72.  
    73.         StartCoroutine(MoveToDestination(returning));
    74.     }
    75. }
    76.  

    Do you know what is the cause of it and how can i fix it?
    Thanks in advance
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,522
    I would not approach it this way.

    Just make an animation of the spike doing what you want it to do and play that animation.

    If you absolutely MUST code the spike's movement, do this (this is python-esque pseudocode in a single coroutine)

    Code (csharp):
    1. while true:
    2.   wait a few seconds
    3.   while not fully extended:
    4.      extend it a bit
    5.      yield return null
    6.   wait a few seconds
    7.   while not fully retracted:
    8.      retract it a bit
    9.      yield return null
    Done. I'll let you sort out the syntax since you're obviously at least passingly familiar with coroutines.
     
    Joe-Censored likes this.
  3. ClaudiaTheDev

    ClaudiaTheDev

    Joined:
    Jan 28, 2018
    Posts:
    331
    Your code looks to complicated.
    Do a Coroutine with your whole process and another one for handling the movement.
    Code (CSharp):
    1. IEnumerator SpikePlatformRoute()
    2.     {
    3.         while (true)
    4.         {
    5.             //WAIT
    6.             yield return new WaitForSeconds(timeToWaitAtStartPos);
    7.  
    8.             //MOVE
    9.             yield return StartCoroutine(MoveFromTo(startPos, endPos));
    10.  
    11.             //WAIT
    12.             yield return new WaitForSeconds(timeToWaitAtEndPos);
    13.  
    14.             //RETURN
    15.             yield return StartCoroutine(MoveFromTo(endPos, startPos));
    16.         }
    17.     }
    18.  
    19.     IEnumerator MoveFromTo(Vector3 start, Vector3 end)
    20.     {
    21.        ...
    22.     }
     
  4. VeryHotShark

    VeryHotShark

    Joined:
    Mar 11, 2017
    Posts:
    13
    Thank you for your suggestion , I will definitely check it out and give you a respond :)
     
  5. VeryHotShark

    VeryHotShark

    Joined:
    Mar 11, 2017
    Posts:
    13
    I will give it a go :) . Thank you