Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question I am getting worse performance when I implement this script, that uses jobs and burst.

Discussion in 'C# Job System' started by PG13park, Aug 17, 2023.

  1. PG13park

    PG13park

    Joined:
    Apr 25, 2022
    Posts:
    11
    The script has the positions of a bunch of trees and the camera. It enables the trees if they are within a certain distance of the camera and disables them if they aren't. I am getting worse performance when I use the script instead of just leaving everything active. NonJob Related= Initial spawning of trees, not important to performance of jobs. Potential PROBLEM AREA Below = suspected problem area, I know it takes a lot of processing power to set the activity of every tree sepratly, is there some way I could do this all at once? Is this the only thing holding the script back?


    Code (CSharp):
    1. using Unity.Collections;
    2. using Unity.Jobs;
    3. using Unity.Burst;
    4. using Unity.Mathematics;
    5. using UnityEngine;
    6. using Unity.Burst.CompilerServices;
    7. using System.Collections.Generic;
    8. using UnityEngine.Rendering;
    9.  
    10. public class ItemAreaSpawner : MonoBehaviour
    11. {
    12.     public void OnApplicationQuit()
    13.     {
    14.         treePositions.Dispose();
    15.         enabledTrees.Dispose();
    16.     }
    17.  
    18.     //ItemAreaSpawner Vars
    19.     public int numItemsToSpawn;
    20.  
    21.     public float itemXSpread = 10;
    22.     public float itemYSpread = 0;
    23.     public float itemZSpread = 10;
    24.  
    25.     //ForestSpawner Vars
    26.     private bool doneSpawning = false;
    27.     public GameObject[] grassItemsToPickFrom;
    28.     public float raycastDistance = 100f;
    29.     public float treeOverlapTestBoxSize = 3.2f;
    30.     public LayerMask spawnedObjectLayer;
    31.     public float maxSpawnHeight;
    32.     public float minSpawnHeight;
    33.     private Vector3 startPos;
    34.  
    35.     //Jobs Data
    36.     private JobHandle foJobHandle;
    37.     private ForestOptimizationJob forestOptimizationJob;
    38.  
    39.     float3 randPositionFloat3;
    40.     public float3 camPosition;
    41.     public Transform cam;
    42.     public NativeList<float3> treePositions;
    43.     private List<GameObject> trees = new List<GameObject>();
    44.     public NativeArray<bool> enabledTrees;
    45.     public float maxHeightForTreeOptimization;
    46.     public float disableTreeRadius;
    47.  
    48.     void Start()
    49.     {
    50.         startPos = transform.position;
    51.  
    52. //jobs data v
    53.         treePositions = new NativeList<float3>(1, Allocator.Persistent);
    54.  
    55.         for (int i = 0; i < numItemsToSpawn; i++)
    56.         {
    57.             transform.position = startPos;
    58.             Vector3 randPosition = new Vector3(UnityEngine.Random.Range(-itemXSpread, itemXSpread), UnityEngine.Random.Range(-itemYSpread, itemYSpread), UnityEngine.Random.Range(-itemZSpread, itemZSpread)) + startPos;
    59.        
    60. //jobs data v
    61.             randPositionFloat3.x = randPosition.x;
    62.             randPositionFloat3.y = randPosition.y;
    63.             randPositionFloat3.z = randPosition.z;
    64.  
    65.             transform.position = randPosition;
    66.        
    67.          // NonJob Related BELOW
    68.             RaycastHit hit;
    69.  
    70.             if (Physics.Raycast(transform.position, Vector3.down, out hit, raycastDistance))
    71.             {
    72.  
    73.                 Quaternion spawnRotation = Quaternion.Euler(new Vector3(UnityEngine.Random.Range(0, 3f), UnityEngine.Random.Range(0, 360f), UnityEngine.Random.Range(0, 3f)));
    74.                 Vector3 scale = Vector3.one * UnityEngine.Random.Range(0.9f, 1.25f);
    75.  
    76.                 //Tree
    77.                 Vector3 treeOverlapTestBoxScale = new Vector3(treeOverlapTestBoxSize, treeOverlapTestBoxSize, treeOverlapTestBoxSize);
    78.                 Collider[] treeCollidersInsideOverlapBox = new Collider[1];
    79.                 int treeNumberOfCollidersFound = Physics.OverlapBoxNonAlloc(hit.point, treeOverlapTestBoxScale, treeCollidersInsideOverlapBox, spawnRotation, spawnedObjectLayer);
    80.  
    81.                 if (treeNumberOfCollidersFound == 0)
    82.                 {
    83.                     if (hit.point.y > minSpawnHeight && hit.point.y < maxSpawnHeight)
    84.                     {
    85.                         int randomIndex = UnityEngine.Random.Range(0, grassItemsToPickFrom.Length);
    86.                         GameObject clone = Instantiate(grassItemsToPickFrom[randomIndex], hit.point, spawnRotation);
    87.                         clone.transform.localScale = scale;
    88.                      // NonJob Related ABOVE
    89.  
    90.                      //jobs data v
    91.                         treePositions.Add(randPositionFloat3);
    92.                         trees.Add(clone);
    93.                     }
    94.                 }
    95.             }
    96.         }
    97. //jobs data v
    98.         enabledTrees = new NativeArray<bool>(treePositions.Length, Allocator.Persistent);
    99.         doneSpawning = true;
    100.     }
    101.  
    102. //jobs stuff happens here v
    103.     private void Update()
    104.     {
    105.         camPosition.x = cam.position.x;
    106.         camPosition.y = cam.position.y;
    107.         camPosition.z = cam.position.z;
    108.         if (doneSpawning)
    109.         {
    110.             forestOptimizationJob = new ForestOptimizationJob()
    111.             {
    112.                 camPos = camPosition,
    113.                 maxHeight = maxHeightForTreeOptimization,
    114.                 disableRadius = disableTreeRadius,
    115.                 treePos = treePositions,
    116.  
    117.                 treeEnabled = enabledTrees,
    118. };
    119.  
    120.             foJobHandle = forestOptimizationJob.Schedule(treePositions.Length, 64);
    121.             JobHandle.ScheduleBatchedJobs();
    122.  
    123.        
    124.         }
    125.     }
    126.  
    127.     private void LateUpdate()
    128.     {
    129.         foJobHandle.Complete();
    130. // Potential PROBLEM AREA Below
    131.         for (int i = 0; i < treePositions.Length; i++)
    132.         {
    133.             trees.SetActive(forestOptimizationJob.treeEnabled);
    134.         }
    135.     }
    136. }
    137.  
    138. //extra notes
    139. //I think this script decreases performance );
    140. //Seperate The Shadows into there own job.
    141. //Add GPU Instancing.
    142.  
    143. Other Script v
    144. using Unity.Collections;
    145. using Unity.Jobs;
    146. using Unity.Burst;
    147. using Unity.Mathematics;
    148. using UnityEngine;
    149. using System.Collections;
    150. using System.Collections.Generic;
    151.  
    152. [BurstCompile]
    153. public struct ForestOptimizationJob : IJobParallelFor
    154. {
    155.     [ReadOnly] public float3 camPos;
    156.     [ReadOnly] public float maxHeight;
    157.     [ReadOnly] public float disableRadius;
    158.     [ReadOnly] public NativeList<float3> treePos;
    159.  
    160.     [WriteOnly] public NativeArray<bool> treeEnabled;
    161.  
    162.     public void Execute(int index)
    163.     {
    164.         // Check if the camera's y position is under the maxHeight
    165.         if (camPos.y < maxHeight)
    166.         {
    167.             float3 objectPosition = treePos[index];
    168.             objectPosition.y = camPos.y; // Use the camera's y position
    169.  
    170.             // Calculate the distance between the camera and the current object on the xz plane
    171.             float distance = math.distance(camPos, objectPosition);
    172.  
    173.             // Disable the object if it is within the disableRadius
    174.             bool enable = (distance <= disableRadius + 0.01f);
    175.             treeEnabled[index] = enable;
    176.         }
    177.  
    178.         else
    179.         {
    180.             treeEnabled[index] = true;
    181.         }
    182.     }
    183. }

    upload_2023-8-17_1-14-45.png
     
    Last edited: Aug 17, 2023
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    3,721
    Please put code in code tags!

    Don‘t suspect … profile! See: Windows => Analysis => Profiler
     
    Last edited: Aug 17, 2023
  3. PG13park

    PG13park

    Joined:
    Apr 25, 2022
    Posts:
    11
    Ok also how do I put code in code tags
     
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    3,721
    When you edit a post there‘s a toolbar at the top. The only non icon thing reads „Code:“ and the icon next to it opens the code edit box.
     
    PG13park likes this.
  5. PG13park

    PG13park

    Joined:
    Apr 25, 2022
    Posts:
    11
    So looks like unity editor loop is taking up around 75% percent of the CPU Usage when I move the camera in game view. upload_2023-8-17_15-14-1.png

    My script is only taking up like 5.5%
    upload_2023-8-17_15-10-20.png

    upload_2023-8-17_15-12-24.png

    So I don't know how to fix the Editor Loop? Is it cause I have too many packages? Will it go away when the game is built? I did put kind of a lot of packages in.
     

    Attached Files:

  6. PG13park

    PG13park

    Joined:
    Apr 25, 2022
    Posts:
    11
    I was gonna try and optimize shadows, but it seems like the main problem is this editor loop, not the shadows.
     
  7. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    3,721
    Enable Deep Profiling to see what the EditorLoop is doing. Most common culprit is the current scene selection as the Inspector view(s) will update their values every frame. Try deselecting all objects in the scene or at least select a child object with no custom scripts and no children.

    Generally speaking you have to ignore it. If you want reliable and realistic measurements you have to profile a build.
     
  8. PG13park

    PG13park

    Joined:
    Apr 25, 2022
    Posts:
    11
    ok