- Home /
Logic on calculating positions in a race.
I'm doing a race game, and trying to calcualte the order the players are. I have a list of cars, and three int arrays indicating in witch lap, checkpoint and position. (The current lap of the car in carList[0] is currentLap[0]).
I read that i have to compare by lap, if there are 2 cars in the same lap, compare by checkpoint and if there are 2 cars in the same lap and checkpoint compare by distance to the next checkpoint. The problem is I have no idea how to code it.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class RaceManager : MonoBehaviour {
public Waypoint startWaypoint;
public List<Waypoint> waypointsList;
public List<Car> carList;
public int[] currentLap;
public int[] currentWaypoint;
public int[] positions;
// Use this for initialization
public void Initialize() {
currentWaypoint = new int [carList.Count];
currentLap = new int [carList.Count];
positions = new int [carList.Count];
waypointsList.Clear();
Waypoint tempWaypoint;
waypointsList.Add(startWaypoint);
tempWaypoint = startWaypoint;
while(tempWaypoint.nextWaypoint != startWaypoint){
if(tempWaypoint.nextWaypoint == null){
Debug.LogError("Next waypoint is null");
}
waypointsList.Add(tempWaypoint.nextWaypoint);
tempWaypoint = tempWaypoint.nextWaypoint;
}
for (int i = 0; i < waypointsList.Count; i++) {
waypointsList[i].raceManager = this;
}
AssignIDToWaypoints();
}
public void PassedThroughWaypoint(int carID, int waypointID){
//cars ID start at 1.
if(currentWaypoint[carID-1] == waypointID - 1){
currentWaypoint[carID-1]++;
}else{
if(currentWaypoint[carID-1] == waypointsList.Count - 1 && waypointID == 0){
currentWaypoint[carID-1] = 0;
currentLap[carID-1]++;
}
}
}
private void AssignIDToWaypoints(){
for (int i = 0; i < waypointsList.Count; i++) {
waypointsList[i].waypointID = i;
}
}
private void CalculatePositions(){
//Here is where I need help.
}
}
any body tell me ho to do this stuff on photon CLOUD ??
Hi, I have the same problem that Czeus. Any solution? Thanks!
Answer by Tomer-Barkan · May 23, 2013 at 05:00 PM
Use this code. Each waypoint must have a trigger collider, and must be tagged "1", "2", "3"... according to the number of the waypoint.
Each Car object should be assigned with the Car script.
The RaceManager should be assigned with the race manager script, and you need to drag & drop each Car gameobject to the carObjects
variable in the script, so it has a reference to all cars.
What this does, is keep for each car the current waypoint, lap and the transform of the last waypoint. Then each car can calculate the distance traveled. Then each car can calculate it's position in the race, by comparing to all other cars. The race manager then keeps an array of carOrder, which has all the cars in the correct order.
using UnityEngine;
using System.Collections;
public class Car : MonoBehaviour {
public int currentWaypoint;
public int currentLap;
public Transform lastWaypoint;
private static int WAYPOINT_VALUE = 100;
private static int LAP_VALUE = 10000;
// Use this for initialization
public void Initialize() {
currentWaypoint = 0;
currentLap = 0;
}
public void OnTriggerEnter(Collider other) {
string otherTag = other.gameObject.tag;
currentWaypoint = System.Convert.ToInt32(otherTag);
if (currentWaypoint == 1) // completed a lap, so increase currentLap;
currentLap++;
lastWaypoint = other.transform;
}
public float GetDistance() {
return (transform.position - lastWaypoint.position).magnitude + currentWaypoint * WAYPOINT_VALUE + currentLap * LAP_VALUE;
}
public int GetCarPosition(Car[] allCars) {
float distance = GetDistance();
int position = 1;
foreach (Car car in allCars) {
if (car.GetDistance() > distance)
position++;
}
return position;
}
}
public class RaceManager : MonoBehaviour {
public GameObject[] carObjects;
public Car[] allCars;
public Car[] carOrder;
public void Start() {
// set up the car objects
allCars = new Car[carObjects.Length];
carOrder = new Car[carObjects.Length];
for (int i = 0; i < carObjects.Length; i++) {
allCars[i] = carObjects[i].GetComponent<Car>();
}
}
// this gets called every frame
public void update() {
foreach (Car car in allCars) {
carOrder[car.GetCarPosition(allCars) - 1] = car;
}
}
}
Is this code still working? I would like to use it in simple top down race game but "Array index is out of range" error show and carOrder array have duplicate car positions (and last car seems to drop out of array list sometimes). Also lap counter of each car increases by 2 with each lap.
Yeah, it should work. it was just missing an initialization for carOrder. I added this line: carOrder = new Car[carObjects.Length];
Nothing have changed. Still there is out of range error and its pointing at 57 line at above script. I have changed script with invokeRepeating("", 0.5f, 0.5f) and now positions dont change so fast but both duplicates and droping out of array list reamains.
Hi, I have the same problem that Czeus. Any solution? Thanks!
Answer by marclar83 · Jan 25, 2016 at 07:23 PM
Here's a new version of Tomer Barkan' scripts with a couple of improvements.
1) The old Car script didn't filter wrong direction and multiple laps increase. 2) The RaceManager script has one too many array to store the car references, so i removed carObject!
Each waypoint must have a trigger collider, and must be tagged "1", "2", "3"... according to the number of the waypoint.
Each Car object should be assigned with the Car script.
You have to manually set the total number of Waypoints to the nbWaypoint variable and it's preferable that you set lastWaypoint variable to the last waypoint before beginning, so the script would work before the first lap and without console's errors.
The RaceManager should be assigned with the race manager script, and you need to drag & drop each Car gameobject to the allCars variable in the script, so it has a reference to all cars' script.
The Script "Car.cs":
using UnityEngine;
using System.Collections;
public class Car : MonoBehaviour {
public int currentWaypoint;
public int currentLap;
public Transform lastWaypoint;
public int nbWaypoint; //Set the amount of Waypoints
private static int WAYPOINT_VALUE = 100;
private static int LAP_VALUE = 10000;
private int cpt_waypoint = 0;
// Use this for initialization
public void Initialize() {
currentWaypoint = 0;
currentLap = 0;
cpt_waypoint = 0;
}
public void OnTriggerEnter(Collider other) {
string otherTag = other.gameObject.tag;
currentWaypoint = System.Convert.ToInt32(otherTag);
if (currentWaypoint == 1 && cpt_waypoint == nbWaypoint) { // completed a lap, so increase currentLap;
currentLap++;
cpt_waypoint = 0;
}
if (cpt_waypoint == currentWaypoint - 1) {
lastWaypoint = other.transform;
cpt_waypoint++;
}
}
public float GetDistance() {
return (transform.position - lastWaypoint.position).magnitude + currentWaypoint * WAYPOINT_VALUE + currentLap * LAP_VALUE;
}
public int GetCarPosition(Car[] allCars) {
float distance = GetDistance();
int position = 1;
foreach (Car car in allCars) {
if (car.GetDistance() > distance)
position++;
}
return position;
}
}
The Script "RaceManager.cs":
using UnityEngine;
using System.Collections;
public class RaceManager : MonoBehaviour {
public Car[] allCars;
public Car[] carOrder;
public void Start() {
// set up the car objects
carOrder = new Car[allCars.Length];
InvokeRepeating ("ManualUpdate", 0.5f, 0.5f);
}
// this gets called every frame
public void ManualUpdate() {
foreach (Car car in allCars) {
carOrder[car.GetCarPosition(allCars) - 1] = car;
}
}
}
hi , its work fine, but its have one issue on this script ,it it can't consider the no of Lap and no of way point its travels, because in my game car A in second Lap with position 1 and car B in first lap with 2 second position but its change change their position based on distance so please help me, how to add lap, way point travels.
thanks
Answer by Irfan_06 · Jun 28, 2018 at 12:17 PM
if (other.tag == "CheckPoint")
{
currentWaypoint = int.Parse (other.name);
Debug.Log (this.gameObject.name + "-check: " + currentWaypoint);
if (currentWaypoint == 1 && cpt_waypoint == nbWaypoint)
{ // completed a lap, so increase currentLap;
currentLap++;
cpt_waypoint = 0;
}
if (cpt_waypoint == currentWaypoint - 1)
{
lastWaypoint = other.transform;
cpt_waypoint++;
}
}
Instead of giving tag to Waypoints name them "1","2",..... and tag all waypoints... I tagged them 'CheckPoint'.
Answer by claudioal · Oct 03, 2017 at 11:13 PM
Is my mistake in this?
FormatException: Input string was not in the correct format System.Int32.Parse (System.String s) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/Int32.cs:629) System.Convert.ToInt32 (System.String value) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/Convert.cs:1270) Car.OnTriggerEnter (UnityEngine.Collider other) (at Assets/Scripts/Car.cs:25)