Search Unity

Vector3 has same value after job as it did before job

Discussion in 'Entity Component System' started by Demkeys, Apr 27, 2018.

  1. Demkeys

    Demkeys

    Joined:
    Nov 14, 2014
    Posts:
    32
    Hey everyone. I'm still getting used to the different way of writing code when using the Job System so I'm not sure what I'm doing wrong here. I have the following code.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Jobs;
    5. using Unity.Jobs;
    6. using Unity.Collections;
    7.  
    8. public class CubeScript01 : MonoBehaviour {
    9.  
    10.     public float Refinement = 0f;
    11.     public float YPosMultiplier = 0f;
    12.     public Vector3 TargetPosition;
    13.  
    14.     SinglePerlinJob mySinglePerlinJob;
    15.     JobHandle mySinglePerlinJobHandle;
    16.  
    17.     struct SinglePerlinJob : IJob
    18.     {
    19.         public float jRefinement;
    20.         public float jYPosMultiplier;
    21.         public Vector3 jPos;
    22.         public float elapsedTime;
    23.  
    24.         public void Execute()
    25.         {
    26.             jPos.y = Mathf.PerlinNoise(jPos.x * jRefinement, (jPos.z * jRefinement) + elapsedTime);
    27.             jPos.y *= jYPosMultiplier;
    28.         }
    29.     }
    30.  
    31.     // Use this for initialization
    32.     void Start () {
    33.         TargetPosition = transform.localPosition;
    34.  
    35.     }
    36.  
    37.     // Update is called once per frame
    38.     void Update ()
    39.     {
    40.         UpdateCubeWithJob();
    41.      
    42.         // UpdateCube();
    43.     }
    44.  
    45.     void UpdateCubeWithJob()
    46.     {
    47.         mySinglePerlinJob = new SinglePerlinJob()
    48.         {
    49.             jRefinement = Refinement, jYPosMultiplier = YPosMultiplier,
    50.             jPos = TargetPosition, elapsedTime = Time.time
    51.         };
    52.  
    53.         mySinglePerlinJobHandle = mySinglePerlinJob.Schedule();
    54.         mySinglePerlinJobHandle.Complete();
    55.         transform.localPosition = mySinglePerlinJob.jPos;
    56.     }
    57.  
    58.     void UpdateCube()
    59.     {
    60.         TargetPosition.y = Mathf.PerlinNoise(
    61.             TargetPosition.x * Refinement, (TargetPosition.z * Refinement) + Time.time);
    62.         TargetPosition.y *= YPosMultiplier;
    63.         transform.localPosition = TargetPosition;
    64.     }
    65. }
    66.  
    The script is meant to be attached to 5000 or more GameObjects. In my scene I have atleast one (it could be many more) GameObject with this script attached to it. When I enter Play Mode, the position of the GameObject doesn't change. I tried having about 1000 other such GameObjects with this script attached in the scene. I checked the Profiler, and it shows that jobs are running. I tried adding Debug.Log() in the Execute method to check the value of the jPos variable. The value is changed, so I know the calculation is happening. But after the job has been completed, when I read the value of jPos, it still has the same value that it did when the job was first initialized.

    What am I doing wrong here? Also, I'm using Unity 2018.1.0b13, if that info is relevant.
     
    Last edited: Apr 27, 2018
  2. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Schedule is an extension method that passes the job struct by value. So it's a copy of your job that is having it's Execute method called. You need to pass data back and forth from jobs to the main thread via a native container like NativeArray.
     
    Demkeys likes this.
  3. Demkeys

    Demkeys

    Joined:
    Nov 14, 2014
    Posts:
    32
    Oh wow! Yeah that worked. Appreciate the help! I guess I really need to dive into the Job System documentation to understand it better.
    Here's the working code, if anyone else wants to try this out:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Jobs;
    5. using Unity.Jobs;
    6. using Unity.Collections;
    7.  
    8. public class CubeScript01 : MonoBehaviour {
    9.  
    10.     struct SinglePerlinJob : IJob
    11.     {
    12.         public float jRefinement;
    13.         public float jYPosMultiplier;
    14.         public NativeArray<Vector3> jPos;
    15.         public float elapsedTime;
    16.  
    17.         public void Execute()
    18.         {
    19.             for(int i = 0; i < jPos.Length; i++)
    20.             {
    21.                 Vector3 pos = jPos[i];
    22.                 pos.y = Mathf.PerlinNoise(pos.x * jRefinement, (pos.z * jRefinement) + elapsedTime);
    23.                 pos.y *= jYPosMultiplier;
    24.                 jPos[i] = pos;
    25.             }
    26.            
    27.         }
    28.     }
    29.  
    30.     public float Refinement = 0f;
    31.     public float YPosMultiplier = 0f;
    32.     public Vector3 TargetPosition;
    33.  
    34.     SinglePerlinJob mySinglePerlinJob;
    35.     JobHandle mySinglePerlinJobHandle;
    36.  
    37.     // Use this for initialization
    38.     void Start () {
    39.         TargetPosition = transform.localPosition;
    40.  
    41.     }
    42.    
    43.     // Update is called once per frame
    44.     void Update ()
    45.     {
    46.         UpdateCubeWithJob();
    47.        
    48.         // UpdateCube();
    49.     }
    50.  
    51.     void UpdateCubeWithJob()
    52.     {
    53.        
    54.         NativeArray<Vector3> tempjPos = new NativeArray<Vector3>(1, Allocator.TempJob);
    55.         tempjPos[0] = transform.localPosition;
    56.  
    57.         mySinglePerlinJob = new SinglePerlinJob()
    58.         {
    59.             jRefinement = Refinement, jYPosMultiplier = YPosMultiplier,
    60.             jPos = tempjPos, elapsedTime = Time.time
    61.         };
    62.  
    63.         mySinglePerlinJobHandle = mySinglePerlinJob.Schedule();
    64.         mySinglePerlinJobHandle.Complete();
    65.         transform.localPosition = mySinglePerlinJob.jPos[0];
    66.  
    67.         tempjPos.Dispose();
    68.     }
    69.  
    70.     void UpdateCube()
    71.     {
    72.         TargetPosition.y = Mathf.PerlinNoise(
    73.             TargetPosition.x * Refinement, (TargetPosition.z * Refinement) + Time.time);
    74.         TargetPosition.y *= YPosMultiplier;
    75.         transform.localPosition = TargetPosition;
    76.     }
    77. }
    78.