Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Bhanuka_Dassanayake · Apr 30 at 09:36 AM · targetfinddots

Unity Job System based Target Finding

Can someone help me to convert this to use Job System?

 void FindNearestTarget()
 {
     for (int i = 0; i < targetManager.TroopsArray.Length; i++)
     {
         shortestDistanceToTarget_sq = Mathf.Infinity;
         Transform nearestTarget = null;
         foreach (GameObject Target in targetManager.LootTargetsArray)
         {
             float distanceToTarget_sq = math.distancesq(targetManager.TroopsArray[i].transform.position, Target.transform.position);
             if (distanceToTarget_sq < shortestDistanceToTarget_sq)
             {
                 shortestDistanceToTarget_sq = distanceToTarget_sq;
                 nearestTarget = Target.transform;
             }
         }
         if (nearestTarget != null)
         {
             targetManager.TroopsArray[i].GetComponent<MovementH>().Movement((nearestTarget.position - targetManager.TroopsArray[i].transform.position).normalized);
         }
     }
 }


Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by andrew-lukasik · Apr 30 at 06:40 PM

FindNearestTargetJob

 [Unity.Burst.BurstCompile]
 public struct FindNearestTargetJob : IJobParallelFor
 {
     [ReadOnly] public NativeList<float3> Origins;// reads one per jobIndex
     [ReadOnly][NativeDisableParallelForRestriction] public NativeList<float3> Targets;// reads all per jobIndex
     [WriteOnly] public NativeArray<int> Results;
     void IJobParallelFor.Execute ( int jobIndex )
     {
         float3 origin = Origins[jobIndex];
         int candidate = -1;
         float candidateDistSq = float.PositiveInfinity;
         for( int i=0 ; i<Targets.Length ; i++ )
         {
             float distSq = math.distancesq( origin , Targets[i] );
             if( distSq<candidateDistSq )
             {
                 candidateDistSq = distSq;
                 candidate = i;
             }
         }
         Results[jobIndex] = candidate;
     }
 }


find nearest target


Here is a full, working example based not on entities but common gameObjects.

(sourcing these positions from entities is a much easier case)


LetFindNearestTargets.cs

 // web* src = https://gist.github.com/andrew-raphael-lukasik/e9c3c1c85a149d2c041532e3632fe4e3
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.Jobs;
 using Unity.Mathematics;
 using Unity.Jobs;
 using Unity.Collections;
 using Unity.Profiling;
 
 public class LetFindNearestTargets : MonoBehaviour
 {
     public List<Transform>
         troopsToAdd = new List<Transform>() ,
         troopsToRemove = new List<Transform>() ,
         targetsToAdd = new List<Transform>() ,
         targetsToRemove = new List<Transform>();
     TransformAccessArray _troopsDataAccess, _targetsDataAccess;
     NativeList<float3> _troopPositions, _targetPositions;
     NativeList<int> _nearestTargetIndices;
     public JobHandle Dependency;
     ProfilerMarker
         ___proc_results = new ProfilerMarker("process job results") ,
         ___maintain_data_access = new ProfilerMarker("maintan data access") ,
         ___schedule_new = new ProfilerMarker("schedule jobs") ,
         ___schedule = new ProfilerMarker("schedule calls");
     const float k_tick_rate = 0.4f;// tick every 0.4s
     void OnEnable ()
     {
         InvokeRepeating( nameof(Tick) , k_tick_rate , k_tick_rate );
         _troopsDataAccess = new TransformAccessArray( 32 );
         _targetsDataAccess = new TransformAccessArray( 32 );
         _troopPositions = new NativeList<float3>( 32 , Allocator.Persistent );
         _targetPositions = new NativeList<float3>( 32 , Allocator.Persistent );
         _nearestTargetIndices = new NativeList<int>( 32 , Allocator.Persistent );
     }
     void OnDisable ()
     {
         CancelInvoke();
         Dependency.Complete();
         if( _troopsDataAccess.isCreated ) _troopsDataAccess.Dispose();
         if( _targetsDataAccess.isCreated ) _targetsDataAccess.Dispose();
         if( _troopPositions.IsCreated ) _troopPositions.Dispose();
         if( _targetPositions.IsCreated ) _targetPositions.Dispose();
         if( _nearestTargetIndices.IsCreated ) _nearestTargetIndices.Dispose();
     }
     #if UNITY_EDITOR
     void OnDrawGizmos ()
     {
         if( !Application.isPlaying ) return;
         Gizmos.color = Color.blue;
         for( int i=_troopsDataAccess.length-1 ; i!=-1 ; i-- )
             Gizmos.DrawWireCube( _troopsDataAccess[i].position , Vector3.one );
         Gizmos.color = Color.red;
         for( int i=_targetsDataAccess.length-1 ; i!=-1 ; i-- )
             Gizmos.DrawWireSphere( _targetsDataAccess[i].position , 1f );
     }
     #endif
     void Tick ()
     {
         Dependency.Complete();
 
         // process results
         ___proc_results.Begin();
         {
             // don't do this like I'm doing here, it's just for quick & dirty viz
             // i.e. avoid reading/writing from native collection outside jobs, it very slow (especially in big loops)
 
             int numResults = _nearestTargetIndices.Length;
             for( int i=0 ; i<numResults ; i++ )
             {
                 int nearestTargetIndex = _nearestTargetIndices[i];
                 Debug.DrawLine( _troopPositions[i]  , _targetPositions[nearestTargetIndex] , Color.yellow , k_tick_rate );
                 // Transform troop = _troopsDataAccess[i];
                 // Transform target = _targetsDataAccess[nearestTargetIndex];
             }
         }
         ___proc_results.End();
 
         // TransformAccessArray maintainance
         ___maintain_data_access.Begin();
         {
             int numTroopsToRemove = troopsToRemove.Count;
             if( numTroopsToRemove!=0 )
             {
                 for( int i=0 ; i<numTroopsToRemove ; i++ )
                 {
                     Transform next = troopsToRemove[i];
                     if( next!=null )
                     for( int k=_troopsDataAccess.length-1 ; k!=-1 ; k-- )
                     {
                         if( _troopsDataAccess[k]==next )
                         {
                             _troopsDataAccess.RemoveAtSwapBack( k );
                             break;
                         }
                     }
                 }
                 troopsToRemove.Clear();
             }
             
             int numTroopsToAdd = troopsToAdd.Count;
             if( numTroopsToAdd!=0 )
             {
                 for( int i=0 ; i<numTroopsToAdd ; i++ )
                     if( troopsToAdd[i]!=null )
                         _troopsDataAccess.Add( troopsToAdd[i] );
                 troopsToAdd.Clear();
             }
 
             int numTargetsToRemove = targetsToRemove.Count;
             if( numTargetsToRemove!=0 )
             {
                 for( int i=0 ; i<numTargetsToRemove ; i++ )
                 {
                     Transform next = targetsToRemove[i];
                     if( next!=null )
                     for( int k=_targetsDataAccess.length-1 ; k!=-1 ; k-- )
                     {
                         if( _targetsDataAccess[k]==next )
                         {
                             _targetsDataAccess.RemoveAtSwapBack( k );
                             break;
                         }
                     }
                 }
                 targetsToRemove.Clear();
             }
 
             int numTargetsToAdd = targetsToAdd.Count;
             if( numTargetsToAdd!=0 )
             {
                 for( int i=0 ; i<numTargetsToAdd ; i++ )
                     if( targetsToAdd[i]!=null )
                         _targetsDataAccess.Add( targetsToAdd[i] );
                 targetsToAdd.Clear();
             }
         }
         ___maintain_data_access.End();
 
         // schedule new jobs:
         ___schedule_new.Begin();
         int numTroops = _troopsDataAccess.length;
         int numTargets = _targetsDataAccess.length;
         if( numTroops!=0 && numTargets!=0 )
         {
             ___schedule.Begin();
             _troopPositions.Length = numTroops;
             _nearestTargetIndices.Length = numTroops;
             _targetPositions.Length = numTargets;
             
             JobHandle troopPositionsJobHandle = new ReadPositionsJob{ Results = _troopPositions }
                 .Schedule( _troopsDataAccess );
             JobHandle targetPositionsJobHandle = new ReadPositionsJob{ Results = _targetPositions }
                 .Schedule( _targetsDataAccess );
             
             var findNearestTargetJob = new FindNearestTargetJob
             {
                 Origins = _troopPositions ,
                 Targets = _targetPositions ,
                 Results = _nearestTargetIndices ,
             };
             Dependency = JobHandle.CombineDependencies( troopPositionsJobHandle , targetPositionsJobHandle , Dependency );
             Dependency = findNearestTargetJob.Schedule(
                 arrayLength:            numTroops ,
                 innerloopBatchCount:    math.max( numTroops/SystemInfo.processorCount/4 , 1 ) ,
                 dependsOn:                Dependency
             );
             ___schedule.End();
         }
         ___schedule_new.End();
     }
 }
 
 [Unity.Burst.BurstCompile]
 public struct ReadPositionsJob : IJobParallelForTransform
 {
     [WriteOnly] public NativeArray<float3> Results;
     void IJobParallelForTransform.Execute ( int index , TransformAccess transform )
         => Results[index] = transform.position;
 }


Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

136 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Else Statement Not Working 1 Answer

Find Transform in the scene 2 Answers

Look At Target? 2 Answers

FindClosestEnemy() change target? 1 Answer

I can't find the gameobject that my scriptis attached to 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges