Wednesday 8 October 2014

UniParallel - New features in version 0.6

Download it free from the Unity Asset Store

For Android, iOS, Windows Phone, Windows, MacOS, Linux and probably a whole set of other platforms that support .Net natively. Try it, it's free!

If you are new to UniParallel, please read the post Using PTaskScheduler - UniParallel Unity package first.

Version 0.6 of the UniParallel package adds a new type of task scheduler called  PSyncTaskScheduler  which has the same functionalities of the  PTaskScheduler  adding to it the ability to execute a routine in the main game Thread after a task is finished.
Only 3 of types of tasks are supported, named slightly different:

  • Use SyncImmediateTask if you want to schedule a task for immediate execution
  • Use SyncTimedTask if you want to schedule a task for delayed execution
  • Use SyncRepeatableTask to execute tasks a certain number of times on a interval

Infinite synchronized tasks are supported, obviously, since the purpose of the sync tasks is to execute another routine when finished.

And every starts with and instance of  PSyncTaskScheduler 
 [...]
 PSyncTaskScheduler scheduler = new PSyncTaskScheduler();
 // schedule your tasks
 [...]
 // check if there's any tasks finished and execute it's post completion routine
 scheduler.Update(); 

The line
scheduler.Update();
Is extremely important and must be included in your MonoBehaviour update loop. This call is responsible for executing and post-completion routine scheduled. That is, if there's any completed tasks. Calling PSyncTaskScheduler.Update() when there are no tasks completed or scheduled is completely safe and will cause no impact on your application performance whatsoever.
Let's see an example of a immediate task that will execute a heavy operation in the background and notify the game when completed
 
 [...]
 PSyncTaskScheduler scheduler = new PSyncTaskScheduler();
 SyncImmediateTask task = new SyncImmediateTask(MethodThatCanBlockMyGame, MethodToRunAfterBlockingMethodIsDone);
 scheduler.Enqueue(task);
 [...]

 // The MonoBehaviour update loop
 void Upate()
 {
    scheduler.Update()
 }
 object MethodThatCanBlockMyGame()
 {
    // this is running in the background and allowing your game to continue smoothly
    Boolean isDone = true;
    // Do a few very heavy operations
    ThisIsGoingToTakeALongTime();
    // isDone is the argument passed to MethodToRunAfterBlockingMethodIsDone
    return isDone;
 }
 
 void MethodToRunAfterBlockingMethodIsDone(object result)
 {
   // this is running inside the game's main thread and MUST BE very light-weight code
   Boolean booleanResult = (Boolean) result;  // result is coming from  MethodThatCanBlockMyGame
   if(result)
   {
     Debug.Log("Completed successfully");
   }
   else
   {
     Debug.Log("Ooops");
   }
 }

Note the signatures of the methods  MethodThatCanBlockMyGame  and  MethodToRunAfterBlockingMethodIsDone : they *must* work with only object types, the background method returning and object that will be passed as an argument to the method executed after the background routine is completed.
Let's take a look at the other 2 types of synchronized tasks. They are just as simple to use as immediate tasks. First, timed tasks
 
 [...]
 const int delay = 1000; // 1 second
 PSyncTaskScheduler scheduler = new PSyncTaskScheduler();
 SyncTimedTask timedTask = new SyncTimedTask(MethodToStartAfterDelay, MethodToExecuteAfterComplete, delay); 
 scheduler.Enqueue(timedTask);
 [...]

 // The MonoBehaviour update loop
 void Upate()
 {
    scheduler.Update()
 }
 object MethodToStartAfterDelay()
 {
    // this is running in the background, starting after the specified delay
    Integer calculationResult = DoSomeMath();
    return calculationResult;
 }
 
 void MethodToExecuteAfterComplete(object result)
 {   
   Debug.Log("The calculated number is "+result);   
 }

Then, SyncRepeatableTask tasks. This time of task is not only useful for executing heavy operations in background but also delayed repeatable operations that will result in something to be rendered, like a countdown timer
 
 [...]

 const int delay = 1000;// run every second ...
 const int executionCount = 10; // and 10 times
 
 int mInitialTimerValue = 10;

 PSyncTaskScheduler scheduler = new PSyncTaskScheduler();
 //count down 10 seconds
 SyncRepeatableTask repeatableTask = new SyncRepeatableTask(CountDown, OnEachCountDown, 
                delay, executionCount);
 scheduler.Enqueue(repeatableTask);

 // The MonoBehaviour update loop
 void Upate()
 {
    scheduler.Update()
 }
 
 object CountDown()
 {
    mInitialTimerValue--;
    return mInitialTimerValue;
 }
 
 void OnEachCountDown(object result)
 {   
   Debug.Log("The timer now is at "+result);   
   RenderTimer(mInitialTimerValue);
 }

No comments: