Search Unity

Sort and delegate working together

Discussion in 'Scripting' started by Learner, Nov 28, 2010.

  1. Learner

    Learner

    Joined:
    Dec 13, 2008
    Posts:
    91
    Hi all,

    Currently I am studying a video tutorial I found on Youtube and it has been a little difficult because I am not a programmer

    Basically, I am having some issues trying to understand "delegate" and "sort" working together. This is the code

    Code (csharp):
    1. targets.Sort(delegate(Transform t1, Transform t2)
    2.     {
    3.     return Vector3.Distance(myTransform.position,t1.transform.position)
    4.                 .CompareTo(
    5.                 Vector3.Distance(myTransform.position,t2.transform.position));
    6.     });
    7.  
    What I cannot get is this part of the code: (Transform t1, Transform t2)

    My questions are, variables t1 and t2 are used to retrieve values from the list "targets"? How "Sort" knows what values t1 and t2 should take?

    Thanks in advance for your answer
     
  2. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    Ah... This is a nested function inside a Class It is not defined like that in Javascript though, looks more like C#

    Also, the CompareTo is not a defined function of Vector3.

    This is more how it would be defined in Javascript:
    Code (csharp):
    1.  
    2. class targetClass{
    3.     var myTransform : Transform;
    4.    
    5.     function Sort(t1:Transform, t2:Transform){
    6.         return Vector3.Distance(myTransform.position,t1.transform.position)
    7.                 >(Vector3.Distance(myTransform.position,t2.transform.position));
    8.     }
    9. };
    10.  
    11. var targets : targetClass;
    12.  
    13. function Start(){
    14. if(targets.myTransform==null)return;
    15. print(targets.Sort(Vector3(0,0,0),Vector3(0,1,0)));
    16. }
    17.  
     
  3. Learner

    Learner

    Joined:
    Dec 13, 2008
    Posts:
    91
    Hi BigMisterB ,

    Sorry, I forgot to mention it is C#. The code is working but I wanted to understand the magic behind the lines.

    Regards
     
  4. Chris-Sinclair

    Chris-Sinclair

    Joined:
    Jun 14, 2010
    Posts:
    1,326
    Sort uses a built-in sorting method (uses the QuickSort algorithm) where given the list of items to sort, it uses the method you pass to it to determine which item goes first.

    So for example, say I had a list of integers that I needed to sort, it might be as simple as:
    Code (csharp):
    1. private bool IntCompare(int value1, int value2)
    2. {
    3.     if (value1 < value2)
    4.     {
    5.         return -1;
    6.     }
    7.     else if (value1 == value2)
    8.     {
    9.         return 0;
    10.     }
    11.     else
    12.     {
    13.         return 1;
    14.     }
    15. }
    16.  
    17. int[] list = new int[]{1,9,3,5,2,6};
    18. list.Sort(IntCompare);
    In this case, Unity automatically performs the sorting, but does so according to the rules you setup in "IntCompare". (return -1 means "value1" comes before "value2", 0 means they're equal, 1 means "value1" comes after "value2")

    In C#, referencing methods like that is done using "delgates". The code you posted is just a short-hand way of creating delegates. In my first example, I declared a full class member for the sorting. But it could just as easily be rewritten using an anonymous method (a method that doesn't strictly belong to a class):
    Code (csharp):
    1. int[] list = new int[]{1,9,3,5,2,6};
    2. list.Sort(delegate(int value1, int value2)
    3.     {
    4.         if (value1 < value2)
    5.         {
    6.             return -1;
    7.         }
    8.         else if (value1 == value2)
    9.         {
    10.             return 0;
    11.         }
    12.         else
    13.         {
    14.             return 1;
    15.         }
    16.     }
    17. );
    So these are useful when you want to apply special sorting rules for special objects (sort your transforms in order to say, an arbitrary central point. Sort them by their magnitude. Or whatever)

    It's late, so hopefully I didn't put much misinformation/mistakes in that. Hopefully that'll help you out.
     
  5. Learner

    Learner

    Joined:
    Dec 13, 2008
    Posts:
    91
    Hi FizixMan,

    Thanks for taking time to answer. I think, I understand the concept. In this case, the anonymous method is pointing CompareTo, right? That is why when I try this (Transform t1, Transform t2, Transform t3), the code does not work.

    Also, I found another way to write the same code using lamdda expression.

    Code (csharp):
    1. targets.Sort((t1, t2) =>
    2.             Vector3.Distance(myTransform.position,t1.transform.position)
    3.             .CompareTo
    4.             (Vector3.Distance(myTransform.position,t2.transform.position))
    5.             );
    6.     }
    Thanks again
     
  6. Chris-Sinclair

    Chris-Sinclair

    Joined:
    Jun 14, 2010
    Posts:
    1,326
    Sort is "type-safe." That means it is locked to comparing two entries. This is because the sort method is designed to sort the array by comparing only two items at once (the quicksort algorithm). Trying to give it 3 entries should result in a compile error 'cause the sort method doesn't know what to do with it. As you picked up on though, it's very easy to introduce more variables into your sorting method. Especially with your discovery of lambdas (which are awesome by the way)

    Also, you don't need to use the "CompareTo" in there, that's just an easier way of using a default comparison of floats (from low-to-high). You could have written the method as:
    Code (csharp):
    1. targets.Sort( (t1, t2) =>
    2. {
    3.     float t1Distance = Vector3.Distance(myTransform.position, t1.transform.position);
    4.     float t2Distance = Vector3.Distance(myTransform.position, t2.transform.position);
    5.    
    6.     if (t1Distance < t2Distance)
    7.     {
    8.         return -1;
    9.     }
    10.  
    11.     if (t1Distance > t2Distance)
    12.     {
    13.         return 1;
    14.     }
    15.  
    16.     return 0;
    17. });
    If you wanted to sort all even numbers before odd numbers, you wouldn't use CompareTo, but instead you would use something like "number % 2 == 0".
     
  7. Learner

    Learner

    Joined:
    Dec 13, 2008
    Posts:
    91
    Thanks FizixMan. Now I have a better understanding of delegate and Sort function.

    Regards from Costa Rica