make a meter
Effect:
need:
There are several different dashboards (thermo-hygrometer, oil temperature) with different ranges, and the input values need to be displayed in the correct position
Ideas:
- You need to define the value of the start position and end position, enter the interval value, and get the percentage of the input value in the interval
- Make three pointers, representing the start position, end position and input position respectively
- Map the resulting percentage value to a pointer
- Because sometimes the density represented on the dial is different (may become more and more dense) it is necessary to add an additional parameter adjustment
- Do a good job of behavioral constraints, the pointer position (including the start and end positions) cannot exceed the range
Get started:
A simple formula to get the percentage:
float percentage =
(pointerValue - startValue) / (endValue - startValue);
//得到百分比
Mapped to angles:
/2 is the middle position of the calculation, and the mapping percentage should be * percentage
The percentage is a floating-point number before 0 to 1. If I want to control the density, all I can think of is multiplying the percentage.
As for how many times to multiply, we can adjust it externally
pointerAngle.z =
EndAngle.z + (Mathf.Abs(EndAngle.z) + StartAngle.z) * Mathf.Pow(percentage, power);
//转换为角度
constraint:
- The starting angle value cannot be increased all the time. After 360 or -360, it must be cleared to ensure that it is a normal angle and easy to calculate.
- The end angle will not exceed the range of the start angle
- Pointer angle is between start angle and end angle
LimitAngle(ref startAngle);
if (endAngle > startAngle)
endAngle = startAngle;
if (endAngle < startAngle - 360)
endAngle = startAngle - 360;
if (pointerValue > endValue)
pointerValue = endValue;
if (pointerValue < startValue)
pointerValue = startValue;
void LimitAngle(ref float angle)
{
if (angle > 360)
{
angle -= 360;
}
if (angle < -360)
{
angle += 360;
}
}
other:
In fact, this is enough to deal with most of the dials, but the dial may be in a right-to-left style.
Finally, I added a parameter to adjust whether it is reversed.
At first I was thinking about adjusting the calculation of the formula, and then I had a flash of inspiration. Just adjust the percentage directly, the principle is: 1-percentage
Full code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Meter : MonoBehaviour
{
public Transform pointer;
public Transform startPoint;
public Transform endPoint;
public float startAngle = 0, endAngle = 0;
public float pointerValue = 0;
public float startValue = 0, endValue = 1;
[Range(0, 10)]
public float power = 1;
public bool reverse = false;
Vector3 pointerAngle;
Vector3 StartAngle, EndAngle;
public void UpdateMeter()
{
LimitAngle(ref startAngle);
if (endAngle > startAngle)
endAngle = startAngle;
if (endAngle < startAngle - 360)
endAngle = startAngle - 360;
if (pointerValue > endValue)
pointerValue = endValue;
if (pointerValue < startValue)
pointerValue = startValue;
StartAngle = Vector3.zero;
EndAngle = Vector3.zero;
StartAngle.z = startAngle;
EndAngle.z = endAngle;
float percentage = (pointerValue - startValue) / (endValue - startValue);//得到百分比
if (!reverse)
percentage = 1- percentage;
pointerAngle.z = EndAngle.z + (Mathf.Abs(EndAngle.z) + StartAngle.z) * Mathf.Pow(percentage, power);//转换为角度
LimitAngle(pointer, ref pointerAngle);
LimitAngle(startPoint, ref StartAngle);
LimitAngle(endPoint, ref EndAngle);
}
void LimitAngle(ref float angle)
{
if (angle > 360)
{
angle -= 360;
}
if (angle < -360)
{
angle += 360;
}
}
void LimitAngle(Transform target, ref Vector3 angle)
{
if (angle.z > 360)
{
angle.z -= 360;
}
if (angle.z < -360)
{
angle.z += 360;
}
target.localEulerAngles = angle;
}
private void OnValidate()
{
UpdateMeter();
}
}
Demo download link: Click to download