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.

And the winner is...

Discussion in 'Editor & General Support' started by Omega, Jan 13, 2009.

  1. Omega

    Omega

    Joined:
    Jul 31, 2007
    Posts:
    125
    I'm working on a racing game, which is coming along, and I'm stuck. Again. Well, not exactly stuck, but I would appreciate suggestions.
    How do you figure out who is in first, second, etc. and keep track of the laps?

    My current idea is to have the track covered in waypoints with triggers that call a function on the vehicle to increment its waypoint index, if it's the right waypoint. Laps are counted when it hits the end of the array.
    Does this sound good, or is there a better way to do it?
    Thanks in advance.
     
  2. HiggyB

    HiggyB

    Unity Product Evangelist

    Joined:
    Dec 8, 2006
    Posts:
    6,183
    There's a related post here, although it doesn't offer much beyond what you have here already. It seems that you're on the right track, you store the lap count and "waypoint" count for each racer, those with a higher lap count, those with a higher waypoint count, and those that are closer to the next waypoint are deemed "ahead" of others. Should be straightforward to sort out, although I'd be keen on hearing from anyone out there that's done a racing game and whether they think this is a good path to take. Anyone?
     
  3. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    It's a pretty good way to go. The key thing, actually, is to subtract the current waypoint from the one that follows it to get a vector pointing in the direction of the track.

    Code (csharp):
    1. trackDir = nextWaypoint - currWaypoint;
    If you have two or more cars that have passed the same number of waypoints, then subtract the current waypoint from each of their positions to get a vector pointing from the waypoint to each car.

    Code (csharp):
    1. carHeading = car.position - currWaypoint;
    You can find out how far each car is from the waypoint using the dot product of the two vectors (ie, the car with the largest dot product is the leader, and so on):-

    Code (csharp):
    1. distance = Vector3.Dot(carHeading, trackDir);
    The advantage of this over just using the distance from the waypoint is that it ignores the sideways position of the car on the track.

    You can also use a dot product of the car's forward direction and the track direction to implement one of those "wrong way" detectors. The value will be negative if the car is basically pointing backwards relative to the track:-

    Code (csharp):
    1. if (Vector3.Dot(car.forward, trackDir) < 0) {
    2. /* Wrong way alert */
    3. }
     
  4. Omega

    Omega

    Joined:
    Jul 31, 2007
    Posts:
    125
    Thank you, you've been helpful. Took me a while to figure out what you were doing, but it makes sense. Actually, it makes more sense than what I was doing. :D Yet again, I wish I had something to give you kind people other than warm fuzzies.

    By the way, Vector3.Dot is computationally cheaper than Vector3.Distance, right?
     
  5. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    It is, but in practice you would probably just use the vectors' sqrMagnitude property to get the squared lengths (if a is greater than b, then a * a will be greater than b * b). Vector3.Dot is about the same computational cost as sqrMagnitude.
     
  6. Omega

    Omega

    Joined:
    Jul 31, 2007
    Posts:
    125
    Interesting.
    I'm stuck on how to display the positions of the vehicles, though. My main problem is getting the data into one script to analyze it. Any thoughts?
     
  7. HiggyB

    HiggyB

    Unity Product Evangelist

    Joined:
    Dec 8, 2006
    Posts:
    6,183
    You need to sort each racer by current lap, current waypoint and distance from the current waypoint to the next waypoint*. Where in there are you stuck?

    *Using the dot production solution andeeee described above.
     
  8. Omega

    Omega

    Joined:
    Jul 31, 2007
    Posts:
    125
    The problem is not so much "How do I do this", but rather "How do I do this in Unity". The racer scripts are per vehicle, but I need the data in one place to process it, such as my main control script.
    Now that I say that, I think the best way to do this would to be to dispense with the racer scripts and do all the math in my launcher script. Supplement Network.Instantiate with an RPC call to register the transform, then let the script figure out where the racers are. Hmmm.... should work...
     
  9. huxley

    huxley

    Joined:
    Apr 27, 2009
    Posts:
    334
    I am dealing with the same issue as you omega, with regard to racing scripts.

    I'm having difficultly deciding where to put the data for car position and laps completed. I too was applying a car status script to each car in the race which would check against waypoints on the track. This approach works fine to control the car which is applied to, but makes it difficult to pass that data to any other scripts.

    I was wondering how you finally solved this issue.
     
  10. Omega

    Omega

    Joined:
    Jul 31, 2007
    Posts:
    125
    If I remember correctly, the method I used was to capture the transform returned from the instantiation of the vehicles, then use the global script to track all of the transforms, waypoints, etc. Keeps the code in one place.

    Hope it helps.
     
  11. fdfragoso

    fdfragoso

    Joined:
    Nov 15, 2010
    Posts:
    35
    I know that this post is old, but i have the same problem!

    First I did like andeeee said in his fisrt post, but i couldn't, didn't works fine.

    Second - To know who is in first, second, thirth, ... I trying to do like HiggyB said, but I can't figure out how I can know de lap, I have a variable that puts the lap of all cars, but I tryng to pick this up to know the position, I using an sorting algorithm but this returns only the lap and I lost the car.

    Following the code:

    // Variaveis para determinar em qual volta cada carro esta
    var LapCars : Timer;
    var lapCars : Array;
    LapCars = new Array();
    var index : int = 0;
    var j : int = 0;
    var i : int = 0;

    // Atribui as variaveis seus respectivos valores com base no script Timer
    LapCars = GameObject.Find("Chegada").GetComponent(Timer);
    lapCars[0] = LapCars.lapPlayer;
    lapCars[1] = LapCars.lapIA01;
    lapCars[2] = LapCars.lapIA02;
    lapCars[3] = LapCars.lapIA03;
    lapCars[4] = LapCars.lapIA04;

    for(i = 0; i <= lapCars.length; i++)
    {
    index = LapCars;
    j = i;
    while ((j > 0) (lapCars[j-1] > index))
    {
    lapCars[j] = lapCars[j-1];
    j = j - 1;
    }
    lapCars[j] = index;

    }

    Sorry for my english.

    Thanks,
    Felipe
     
  12. sheva

    sheva

    Joined:
    Nov 22, 2010
    Posts:
    157
    Hi Omega, I'm working for a racing car game too and I have your same issue.
    I hope you solved it, did you?

    Nik
     
  13. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    @Sheva: the techniques mentioned in this thread are basically sound but they might need a bit more explanation. What part exactly are you having trouble with?
     
  14. kiranmaya

    kiranmaya

    Joined:
    May 27, 2010
    Posts:
    215
    Im so struggling with the same thing ranking here .i unable to get an idea of sorting here :confused:,the car which had highest lapcount, highest checkpoint and highest dot value to next checkpoint is the winner.
    im getting a negitive values for dot to next chekpoint
    this is ranking script

    Code (csharp):
    1.  
    2. var aicar1 : GameObject;
    3. var aicar2 : GameObject;
    4. var aicar3 : GameObject;
    5. var aicar4 : GameObject;
    6. var playerCar: GameObject;
    7.  
    8. var car1 : AICar_Script_modified;
    9. var car2 : AICar_Script_modified;
    10. var car3 : AICar_Script_modified;
    11. private var nextdistance:float = 0.0;
    12. var count:int =0;
    13. var arraysort = new Array (0.0,0.0,0.0,0.0);
    14.  
    15. var str1:String ;
    16. var str2:String ;
    17. var str3:String ;
    18. function start()
    19. {
    20.    
    21.     car1  = aicar1.GetComponent("AICar_Script_modified");
    22.     car2 = aicar2.GetComponent("AICar_Script_modified");
    23.     car3  = aicar3.GetComponent("AICar_Script_modified");
    24. }
    25.  
    26.  
    27.  
    28. function Update () {
    29.    
    30.    
    31.     //Invoke("whoislead", 1);
    32.     //InvokeRepeating("whoislead", 1, 1);
    33.      whoislead();
    34. }
    35.  
    36.  
    37.  
    38. function whoislead()
    39. {
    40.      var car1finalvar:float = car1.currentWaypoint ;//+ car1.getDot();
    41.      var car2finalvar:float = car2.currentWaypoint ;//+ car2.getDot();
    42.      var car3finalvar:float = car3.currentWaypoint ;//+ car3.getDot();
    43.  
    44.       //print("the dot is "+ car3finalvar );
    45.  
    46.  
    47.      ar playerCarchecks:float =playerCar.GetComponent("playerCheckpoints").checkPoints;
    48.     arraysort[0]=car1finalvar ;
    49.     arraysort[1]=car2finalvar;
    50.     arraysort[2]=car3finalvar;
    51.     arraysort[3]=playerCarchecks;
    52.     //print("the coint is "+ count++);
    53.    
    54.      
    55.      arraysort.Sort();
    56.  
    57.     switch(arraysort[3])
    58.     {
    59.       case car1finalvar:
    60.        
    61.            str1="Car1 is Lead";
    62.       break;
    63.  
    64.       case car2finalvar:
    65.           str1="Car2 is Lead";
    66.        
    67.       break;
    68.  
    69.       case car3finalvar:
    70.         str1="Car3 is Lead";
    71.          break;
    72.  
    73.         case playerCarchecks:
    74.         str1="PLAYER IS LEAD";
    75.            
    76.       break;
    77.      
    78.     }
    79.  
    80.  
    81. }
    82. function OnGUI () {
    83. GUI.Label (Rect (100, 180, 100, 20), str1);
    84.  
    85.  
    86. }
    87.  
    this is the getDot()
    Code (csharp):
    1.         function   getDot()
    2.      
    3.      
    4.          var trackDir:Vector3 =waypoints[currentWaypoint+1].position-waypoints[currentWaypoint].position;
    5.          var carHeading:Vector3 = transform.position-waypoints[currentWaypoint].position;
    6.          dotis=Vector3.Dot(carHeading,trackDir);
    7.           print("the dot is called and dot is  "+ dotis ++);
    8.      //   dotis=( transform.position-waypoints[currentWaypoint+1].position).sqrMagnitude;
    9.        
    10.           }
    11.  
     
  15. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Should these:

    Code (csharp):
    1. var car1finalvar:float = car1.currentWaypoint ;
    Be ints rather than floats?

    And isn't this:

    Code (csharp):
    1. ar playerCarchecks:float =playerCar.GetComponent("playerCheckpoints").checkPoints;
    A syntax error? (Also, what does the 'checkPoints' variable represent? Is it actually just a single float value?)
     
  16. kiranmaya

    kiranmaya

    Joined:
    May 27, 2010
    Posts:
    215
    ya what u said is all true,but
    my problem here is not syntax error nor filling the float var with integer value.
    at first i intended to put the values like "checkpoints.dotvalue" like 23.45566 ,23 is checkpoint count and 45566 is dot to next point.and i thought sort will done in one shot .
    but having two positive variables like lap count and checkpoint and a minus values dot value ,i don't know ,how to calculate them.
     
  17. kiranmaya

    kiranmaya

    Joined:
    May 27, 2010
    Posts:
    215
    Code (csharp):
    1. to put it simple
    2.  
    3. class ranking
    4. {
    5.  int lapCount;
    6.  int checkpoint;
    7.  int dotToNextCheckPoint;
    8.  int position;
    9. }
    10.  
    11. ranking c1 = new ranking()
    12.  c1.lapCount=car1.lapCount;
    13. c1.checkpoint =car1.currentWaypoint;
    14. c1. dotToNextCheckPoint=ca1.dotTonextPoint;
    15.  
    16. ranking c2 = new ranking()
    17.  c2.lapCount=car2.lapCount;
    18. c2.checkpoint =car2.currentWaypoint;
    19. c2. dotToNextCheckPoint=ca2.dotTonextPoint;
    20.  
    21. ranking c3 = new ranking()
    22.  c3.lapCount=car3.lapCount;
    23. c3.checkpoint =car3.currentWaypoint;
    24. c3. dotToNextCheckPoint=ca3.dotTonextPoint;
    will can direct me ,how to do sorting withes mixed variable .writing a 50+ if cases will do work maybe ,but i wann know how others will do?
     
  18. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Although I'm having a little trouble following the question, it seems what you might be looking for is a custom comparator implementing a lexicographical ordering on the fields in question. This is off the top of my head, but the comparison function might look something like this (pseudocode):

    Code (csharp):
    1. if (car1.lapCount < car2.lapCount) { return -1; }
    2. if (car1.lapCount > car2.lapCount) { return 1; }
    3. if (car1.checkpoint < car2.checkpoint) { return -1; }
    4. if (car1.checkpoint > car2.checkpoint) { return 1; }
    5. if (car1.dotToNextCheckPoint < car2.dotToNextCheckPoint) { return -1;}
    6. if (car1.dotToNextCheckPoint > car2.dotToNextCheckPoint) { return 1; }
    7. return 0;
    (I'm not sure how custom comparators are handled in UnityScript, so I can't provide a more specific example than that.)
     
  19. kiranmaya

    kiranmaya

    Joined:
    May 27, 2010
    Posts:
    215
    like i said before ,do we need to write those number if statements ,and setting up the rank positions to cars is to complicated for me ,by the way i think u understand my question.
     
  20. kiranmaya

    kiranmaya

    Joined:
    May 27, 2010
    Posts:
    215
    Code (csharp):
    1. i want to explain my problem again
    2. here it is
    3. class ranking
    4. {
    5.  int lapCount;
    6.  int checkpoint;
    7.  int dotToNextCheckPoint;
    8.  int position;
    9. }
    10.  
    11. ranking c1 = new ranking()
    12.  c1.lapCount=1;
    13. c1.checkpoint =22;
    14. c1. dotToNextCheckPoint=-35236
    15.  
    16. ranking c2= new ranking()
    17.  c2.lapCount=1;
    18. c2.checkpoint =22;
    19. c2. dotToNextCheckPoint=-25236
    20.  
    21. ranking c3 = new ranking()
    22.  c3.lapCount=1;
    23. c3.checkpoint =22;
    24. c3. dotToNextCheckPoint=-45236
    25.  
    the car having having highest lapcount,checkpoint and dot is winner ,so car2 is winner here .

    so how i can put them to array ,to do sorting for me
     
  21. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    You only have to write that code once.

    The process is:

    1. Create the record for each car (c1, c2, and c3 in your latest example)
    2. Put the records in a 'sortable' container such as List or an array
    3. Sort them using one of the .NET 'sort' functions and a custom comparator implemented as shown above

    As I said I can't provide a UnityScript example off the top of my head, but maybe someone else can help with that.
     
  22. kiranmaya

    kiranmaya

    Joined:
    May 27, 2010
    Posts:
    215
    ok,i will try to make it work.
     
    Last edited: Feb 4, 2011
  23. kiranmaya

    kiranmaya

    Joined:
    May 27, 2010
    Posts:
    215
    do u have any other example?
     
  24. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Just check the MSDN docs for (e.g.) Array.Sort() or List.Sort(); they'll show you how to use the function and how to implement a custom comparison function. (It can be a little confusing, but if you run into any trouble, post back and I or someone else should be able to help further.)
     
  25. kiranmaya

    kiranmaya

    Joined:
    May 27, 2010
    Posts:
    215
    Code (csharp):
    1. var aicar1 : GameObject;
    2. var aicar2 : GameObject;
    3. var aicar3 : GameObject;
    4. var aicar4 : GameObject;
    5. var playerCar: GameObject;
    6.  
    7. var car1 : AICar_Script_modified;
    8. var car2 : AICar_Script_modified;
    9. var car3 : AICar_Script_modified;
    10. private var nextdistance:float = 0.0;
    11. var count:int =0;
    12. var arraysort = new Array (0.0,0.0,0.0);
    13.  
    14. class ranking
    15. {
    16.  var lapCount:int;
    17.  var checkpoint:int;
    18.  var dotToNextCheckPoint:int;
    19.  var Id:int;
    20.  var position:int;
    21. }
    22.  
    23.  
    24. var str1:String ;
    25. var str2:String ;
    26. var str3:String ;
    27.  
    28.  var c1:ranking;
    29.   var c2:ranking;
    30.    var c3:ranking;
    31.  
    32. function start()
    33. {
    34.    
    35.     car1  = aicar1.GetComponent("AICar_Script_modified");
    36.     car2 = aicar2.GetComponent("AICar_Script_modified");
    37.     car3  = aicar3.GetComponent("AICar_Script_modified");
    38.  
    39.         c1   = new ranking();
    40.       c1.checkpoint =car1.currentWaypoint;
    41.       c1.dotToNextCheckPoint=car1.getDot();
    42.       c1.position=1;
    43.       c1.Id=1;
    44.  
    45.        c2  = new ranking();
    46.       c2.checkpoint =car2.currentWaypoint;
    47.       c2.dotToNextCheckPoint=car2.getDot();
    48.       c2.position=2;
    49.       c2.Id=2;
    50.  
    51.  
    52.        c3   = new ranking();
    53.       c3.checkpoint =car3.currentWaypoint;
    54.       c3.dotToNextCheckPoint=car3.getDot();
    55.       c3.position=3;
    56.       c3.Id=3;
    57.  
    58.  
    59.  
    60.  
    61.  
    62.  
    63. }
    64.  
    65.  
    66.  
    67. function Update () {
    68.    
    69.    
    70.     //Invoke("whoislead", 1);
    71.     //InvokeRepeating("whoislead", 1, 1);
    72.      whoislead();
    73. }
    74.  
    75.  
    76.  
    77. function whoislead()
    78. {
    79.      
    80.        
    81.  
    82.       c1.checkpoint =car1.currentWaypoint;
    83.       c1.dotToNextCheckPoint=car1.getDot();
    84.      
    85.       c2.checkpoint =car2.currentWaypoint;
    86.       c2.dotToNextCheckPoint=car2.getDot();
    87.      
    88.       c3.checkpoint =car3.currentWaypoint;
    89.       c3.dotToNextCheckPoint=car3.getDot();
    90.      
    91.      
    92.        carCompare(c1,c2);
    93.        carCompare(c1,c3);
    94.        carCompare(c2,c3);
    95.        carCompare(c3,c2);
    96.  
    97.  
    98.      //arraysort.Sort();
    99.      
    100.      str1="the car1 position is "+ c1.position;
    101.      str1="the car2 position is "+ c2.position;
    102.      str1="the car3 position is "+ c3.position;
    103.    
    104.  
    105.  
    106.  
    107. }
    108.  
    109.  
    110.  
    111. function carCompare( var car1:ranking ,var car2:ranking)
    112. {
    113.          if(car1.checkpoint == car2.checkpoint)
    114.          {
    115.                  if(car1.dotToNextCheckPoint < car2.dotToNextCheckPoint)
    116.                  {
    117.                           var a:int=car1.position;
    118.                           car1.position=car2.position;
    119.                           car2.position=a;
    120.                  }
    121.          }
    122.      
    123.  
    124. }
    125.  
    126.  
    127.  
    128.  
    129. ////////////////////////////////////////////////////////////////////////////////////////////////////
    130. function OnGUI () {
    131. GUI.Label (Rect (100, 180, 100, 20), str1);
    132. GUI.Label (Rect (100, 200, 100, 20), str2);
    133. GUI.Label (Rect (100, 220, 100, 20), str3);
    134.  
    135. }
    136.  
    137. ////////////////////////////////////////////////////////////////////////////////////////////////////
    138.  
    139.  
    here im getting an error
    Code (csharp):
    1. function carCompare( var car1:ranking ,var car2:ranking)
    Assets/Scripts/Car Control/ranking.js(111,22): BCE0043: Unexpected token: var.
    Assets/Scripts/Car Control/ranking.js(111,26): BCE0044: expecting EOF, found 'car1'.

    is javascript will not allow this method?:confused:
     
  26. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    It doesn't quite look like you have things set up right yet (conceptually, at least). The compare function should simply perform a comparison like I showed earlier, and return a value indicating whether the places for the two cars are the same, or one is ahead of the other.

    I wish I could give you an example in UnityScript, but again, I'm going to have to leave that to others. But, I'm sure *someone* knows how it's done in UnityScript, so with any luck someone will see this and help out :)
     
  27. kiranmaya

    kiranmaya

    Joined:
    May 27, 2010
    Posts:
    215
  28. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    I don't know what your new code looks like, but you shouldn't have to use a lot of 'if' statements.

    As for what the pros would do, they'd use a 'sort' function as I mentioned earlier. If you're having trouble figuring out how to do that in UnityScript, I'd recommend making a new thread with a very specific title, like 'How to use custom comparators in UnityScript', and then describe what you're trying to do. (You might have more luck getting a response to that particular question this way.)
     
unityunity