Search Unity

Question Nested for loops with Job System

Discussion in 'Entity Component System' started by Respaekt, Apr 20, 2023.

  1. Respaekt

    Respaekt

    Joined:
    Dec 11, 2018
    Posts:
    15
    Hi programmers,

    i am looking into converting some code in my project to use the Job System. The problem i cant wrap my head around right now is how i can get this to work with nested (for) loops.
    For a single loop i think i understand and there a some examples out there. I create NativeArrays to get the variables into the Jobstruct and use the index to get through my loop. This is a test for single loop:

    Code (CSharp):
    1. public class ExampleJob : MonoBehaviour
    2. {
    3.     public List<BurningObject> burningObjects = new List<BurningObject>();
    4.  
    5.     private void Start()
    6.     {
    7.         BurningObject[] allBurningObjects = FindObjectsOfType<BurningObject>();
    8.         foreach (BurningObject burningObject in allBurningObjects)
    9.         {
    10.             if (burningObject != null)
    11.             {
    12.                 burningObjects.Add(burningObject);
    13.             }        
    14.         }
    15.     }
    16.  
    17.     private void Update()
    18.     {
    19.         // simplified code with a single loop i want to run with the job system
    20.         for (int i = 0; i < burningObjects.Count; i++)
    21.         {
    22.             burningObjects[i].temperature += Time.deltaTime;
    23.         }
    24.  
    25.         // From here with the job system
    26.         NativeArray<float> temperatureArray = new NativeArray<float>(burningObjects.Count, Allocator.Persistent);
    27.  
    28.         for (int i = 0; i < burningObjects.Count; i++)
    29.         {
    30.             temperatureArray[i] = burningObjects[i].temperature;
    31.         }
    32.  
    33.         BurningObjectJob burningObjectJob = new BurningObjectJob
    34.         {
    35.             deltaTime = Time.deltaTime,
    36.             temperature = temperatureArray,
    37.         };
    38.  
    39.         JobHandle jobHandle = burningObjectJob.Schedule(burningObjects.Count, 10);
    40.         jobHandle.Complete();
    41.     }
    42. }
    43.  
    44. public struct BurningObjectJob : IJobParallelFor
    45. {
    46.     public float deltaTime;
    47.     public NativeArray<float> temperature;
    48.  
    49.     public void Execute(int index)
    50.     {
    51.         temperature[index] += deltaTime;
    52.     }
    53. }

    My problem is with nested for loops, this is the simplyfied code i want to convert using the job system: Iam not quite clear how i can get the sceond loop out of the Job, its using the "OverLappingBurningObjectsList" from every burningObject and lists are nullable, so i cant put this into an NativeArray.

    Code (CSharp):
    1. public class BurningSystem : MonoBehaviour
    2. {
    3.     public List<BurningObject> burningObjects = new List<BurningObject>();
    4.  
    5.     private void Start()
    6.     {
    7.         BurningObject[] allBurningObjects = FindObjectsOfType<BurningObject>();
    8.         foreach (BurningObject burningObject in allBurningObjects)
    9.         {
    10.             burningObjects.Add(burningObject);
    11.         }
    12.     }
    13.  
    14.     private void Update()
    15.     {
    16.         for (int i = 0; i < burningObjects.Count; i++)
    17.         {
    18.             BurningObject burningObject = burningObjects[i];
    19.  
    20.             // Loop through all otherBurningObject inside Collider of burningObject
    21.             for (int j = 0; j < burningObject.OverLappingBurningObjectsList.Count; j++)
    22.             {
    23.                 GameObject gameObjectInsideOverlappingList = burningObject.OverLappingBurningObjectsList[j];
    24.                 BurningObject otherBurningObjectComponent = gameObjectInsideOverlappingList.GetComponent<BurningObject>();
    25.                 if (otherBurningObjectComponent != null)
    26.                 {
    27.                     // Calculate the distance from the center of the sphere collider
    28.                     float distance = Vector3.Distance(burningObject.transform.position, gameObjectInsideOverlappingList.transform.position);
    29.  
    30.                     // Calculate the temperature increase based on the distance
    31.                     float temperatureIncrease = Mathf.Lerp(0f, otherBurningObjectComponent.maxTemperatureIncrease, 1f - (distance / burningObject.sphereCollider.radius));
    32.  
    33.                     if (otherBurningObjectComponent.temperature + temperatureIncrease * Time.deltaTime > otherBurningObjectComponent.maxBurningTemperature)
    34.                     {
    35.                         // cap the temperature of the other burning object at maxBurningTemperature
    36.                         otherBurningObjectComponent.temperature = burningObject.maxBurningTemperature;
    37.                     }
    38.                     else
    39.                     {
    40.                         // Increase the temperature of the other burning object
    41.                         otherBurningObjectComponent.temperature += temperatureIncrease * Time.deltaTime;
    42.                     }
    43.                     //Debug.Log("BurningSystem: OtherGameObject" + gameObjectInsideOverlappingList.name + "; temperatureIncrease: " + temperatureIncrease);
    44.                 }
    45.             }
    46.  
    47.             // Heat up the burningObject if it's on fire
    48.             if (burningObject.isBurning)
    49.             {
    50.                 float temperatureIncrease = burningObject.maxTemperatureIncrease;
    51.                 if (burningObject.temperature + temperatureIncrease * Time.deltaTime > burningObject.maxBurningTemperature)
    52.                 {
    53.                     // cap the temperature at maxBurningTemperature
    54.                     burningObject.temperature = burningObject.maxBurningTemperature;
    55.                 }
    56.                 else
    57.                 {
    58.                     // Increase the temperature of the burning object
    59.                     burningObject.temperature += temperatureIncrease * Time.deltaTime;
    60.                 }
    61.             }
    62.         }
    63.     }
    64. }
     
    Last edited: Apr 20, 2023
  2. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Last edited: Apr 20, 2023
    Respaekt likes this.
  3. Respaekt

    Respaekt

    Joined:
    Dec 11, 2018
    Posts:
    15
    Thanks for the reply, got it working.
    Needed some time to wrap my head around stuff. So the difference in thinking when using DOTS/Jobs/Burst and Monobehaviour is, that DOTS means DATA oriented technology stack, obviously. So i dont need to pass a GameObject when i only, for example use the transform of the GameObject in my method, just pass the data you need to work with and then you dont get nullable objects and other errors...
     
    xVergilx likes this.