The start and end points of the Unity dashboard make a custom dial automatically match the pointer position

make a meter

Effect:

Please add a picture description

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:

insert image description here

 float percentage = 
 (pointerValue - startValue) / (endValue - startValue);
 //得到百分比
Mapped to angles:

insert image description here

/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
Please add a picture description

 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

Guess you like

Origin blog.csdn.net/CTangZe/article/details/126489675