Car speedometer dial

Not every man can make speedos work. I’m just one of the lucky few, I guess :wink:

Attached is an example of how to make a gauge with a rotating needle on a dial. I’ve designed it around the idea of a car speedometer but the basic technique can be applied to any similar kind of dial.

A little tip for getting the start and end angles right for your dial. Set the speed to 0mph and set the game running. Then, change the stopAngle value until it matches the the 0mph point on your dial. Note the number and then set the speed to the top speed. Now, change the topSpeedAngle value until it matches the upper limit of the dial and note this number down. When you stop the game, you just need to put the noted numbers back in the variables. And the job’s a good 'un.

408217–14116–$SpeedoPrefab.zip (20.2 KB)

2 Likes

Hi Andeeee,

Thanks so much for going above and beyond on my account. This is an awesome gift and you are very very kind. Your helpful tip to define the topSpeedAngle is inspired too. You are awesome!

Best regards,
Tom

Cool, thanks :slight_smile:

hug

I love thee. Bookmarked.

Does this dial need anymore script to read a rigidbody for example? My box collider I have assigned to the car is reading the ‘Player’ tag and my score updates, but the needle on this dial still does not move. I don’t want to be looking at a gift horse power in the mouth and know that there is a trick here I am missing. I am presently combining the Car tutorial with the Lerpz tutorial adopting all the game assets to create a test drive that knocks a point off every road cone you hit. It is very entertaining and would like to share it with you when its finished.

Please provide another clue.

The position of the needle is determined by the value of the speed variable, so you need to set the speed yourself from another script. (If you’re wondering, I deliberately didn’t tie the script to using a rigidbody, since the game doesn’t necessarily use physics). A simple way to get the rigidbody’s speed is to get the magnitude of the velocity vector. However, it is more realistic (and also more efficient, surprisingly) to get the speed the car is moving in its forward direction. You can do that easily using a dot product as follows:-

function ForwardSpeed() {
  return Vector3.Dot(rigidbody.velocity, transform.forward);
}

You can then assign this value to the speed variable of the speedometer script to get the needle to move.

how could i modify this as an altimeter? been trying to create an altimeter for my flight sim game but not having much luck.

thanks for any help you can offer.

Getting the height value should be no problem (in most cases it would just be the Y coordinate, but if you’ve got a spherical planet, for example, then it would be the distance from the centre of the sphere). Other than that, it’s just a matter of remembering that where the script says “speed”, it really means height from your point of view. Naturally, you can do a find-and-replace on the script to make things clearer if necessary.

The follow code:

function ForwardSpeed() {
return Vector3.Dot(rigidbody.velocity, transform.forward);
}

returns speeds in miles? RPM? KM/h?

Thanks.

Can’t really answer that question as it’s a function of your world’s scale. A value returned of 100 obviously doesn’t mean the same thing if your model is 100 unity units large vs .01.

If the model is built/imported into Unity at 1 unit = 1 meter, then the value will obviously be in meters per second.

I don’t mean to sound really stupid, but I’m new with trying to code with Unity, or anything really. How would I get the speed on the speedometer to link with the rigidbody speed exactly? I understand the math and the coding in the script itself, but not how I can target the rigidbody.

The code in the ForwardSpeed function posted above is all you need to get the speed. You can then use that to set the speedometer reading. The easiest way to go is to add an Update function to the speedometer script which contains the active code from the function:-

function Update() {
  speed = Vector3.Dot(rigidbody.velocity, transform.forward);
}

It would have been sensible for me to add that to the file commented out, really

Putting the update function in the speedo code still doesn’t cause the needle to move for me. The position is still being determined by the speed input in the inspector. Am I just missing something obvious?

Actually, is the script attached to the car, a GUI texture, or a new empty? I know, I’m dumb.

This is unpossibly awesome. How does you do this!? HOW DOES?!

Quick question. How difficult do you think this would be to implement as a tachometer(Thing that measures RPM… That’s a tachometer right?)? I got it basically setup. But it jumps back to the zero position when gears change. I’m guessing I’d need to implement some kind of reset pause that brings the needle back down.

Anybody find some nice speedometer / rpm gauge art out there?

@ WetFloor - With this piece of update code all you have done is updated the speed variable. You still have to set the speed attribute of the game object component to which your speedo script is attached.

c# Version :

using UnityEngine;
using System.Collections;

public class SpeedometerUI : MonoBehaviour {
public Texture2D dialTex;
public Texture2D needleTex;
public Vector2 dialPos;
public float topSpeed=0;
public float stopAngle=0;
public float topSpeedAngle=0;
public float speed=0;


void  OnGUI (){
	GUI.DrawTexture( new Rect(dialPos.x, dialPos.y, dialTex.width, dialTex.height), dialTex);
	Vector2 centre= new Vector2((dialPos.x + dialTex.width) / 2, (dialPos.y + dialTex.height) / 2);
	Matrix4x4 savedMatrix= GUI.matrix;
	float speedFraction= speed / topSpeed;
	float needleAngle= Mathf.Lerp(stopAngle, topSpeedAngle, speedFraction);
	GUIUtility.RotateAroundPivot(needleAngle, centre);
	GUI.DrawTexture( new Rect(centre.x, centre.y - needleTex.height / 2, needleTex.width, needleTex.height), needleTex);
	GUI.matrix = savedMatrix;
}
}
1 Like