Как я могу рассчитать скорость движущегося объекта?

#c# #unity3d

#c# #unity3d

Вопрос:

Цель состоит в том, чтобы показать как скорость преобразования, так и скорость перемещения в text1 и text2.

 using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Follow : MonoBehaviour
{
    public Transform targetToFollow;
    public Text text;
    public Text text1;
    public Text text2;
    public float lookAtRotationSpeed;
    public float moveSpeed;

    private float minMoveSpeed = 0f;
    private Vector3 originPos;

    // Start is called before the first frame update
    void Start()
    {
        originPos = targetToFollow.position;
    }

    // Update is called once per frame
    void Update()
    {
        Vector3 lTargetDir = targetToFollow.position - transform.position;
        lTargetDir.y = 0.0f;
        transform.rotation = Quaternion.RotateTowards(transform.rotation,
            Quaternion.LookRotation(lTargetDir), Time.time * lookAtRotationSpeed);

        var distance = Vector3.Distance(transform.position, targetToFollow.position);

        text.text = "Transform Distance From Target "   distance.ToString();

        float ms = moveSpeed;

        if (distance > 5f)
        {
            ms = moveSpeed   0.5f; //move faster
        }
        else if (distance < 1.5f)
        {
            ms = Mathf.Max(minMoveSpeed, ms - 0.3f); // move slower
        }
        else
        {
default value that equal moveSpeed here
                transform.position = Vector3.MoveTowards(transform.position, targetToFollow.position, Time.deltaTime * ms);
        }

        if(distance < 0.5f amp;amp; originPos == targetToFollow.position)
        {
            ms = 0f;
        }

        transform.position = Vector3.MoveTowards(transform.position, targetToFollow.position, Time.deltaTime * ms);

        originPos = targetToFollow.position;
    }
}
 

Теперь я настраиваю текст на расстояние преобразования от цели.
Но теперь я хочу добавить к text1 и text2 скорость перемещения преобразования и цели.
В конце будет 3 текстовых интерфейса, которые будут показывать расстояние и скорость движения.

Я пробовал так для целевой скорости :

 var speedPerSec = Vector3.Distance(originPos, targetToFollow.position) / Time.deltaTime;
text1.text = "Target Speed Per Second "   speedPerSec.ToString();
 

но когда цель перемещает текст скорости, speedPerSec.toString() мигает быстро и не плавно, как расстояние в первом тексте.

может быть, он мигает, потому что он показывает скорость много после нулевой точки, например: 0.00656555?

Комментарии:

1. Когда вы нажимаете значение перемещения по умолчанию («значение по умолчанию, равное скорости перемещения здесь»), вы перемещаете свой объект дважды. Один раз в предложении else, а другой раз на 8 строк ниже. Просто назначьте ms в предложении else, и все в порядке.

Ответ №1:

Поскольку вы хотите отслеживать скорость нескольких объектов (вашего преобразования и цели), самый простой способ — ввести отдельный объект, обрабатывающий отслеживание, и использовать их массив.

 [Serializable]
private class SpeedTracking
{
    public Transform trackedObject;
    public Text uiOutput;
    private Vector3 _position;
    private float _speed;

    public void Update(float elapsedTime, float changeThreshold)
    {
        Vector3 newPos = trackedObject.position;
        float newSpeed = Vector3.Distance(newPos, _position) / elapsedTime;

        if ((newSpeed == 0 amp;amp; _speed != 0) || Mathf.Abs(newSpeed - _speed) > changeThreshold)
        {
            _speed = newSpeed;
            uiOutput.text = $"speed: {newSpeed:F3}";
        }
        _position = newPos;
    }
}

private const float SPEED_CHANGE_THRESHOLD = 0.001F;
[SerializeField]
private SpeedTracking[] _trackings;

void OnEnable()
{
    if (_trackings.Any(t => t.trackedObject == null || t.uiOutput == null))
    {
        Debug.LogError("at least one invalid tracking found");
        enabled = false;
    }
}

void Update()
{
    //[...]
    UpdateTrackings();
}

void UpdateTrackings()
{
    foreach (SpeedTracking tracking in _trackings)
    {
        tracking.Update(Time.deltaTime, SPEED_CHANGE_THRESHOLD);
    }
}
 

Я также добавил формат к вашей выходной строке (F3), показывающий только 3 десятичные цифры. (Это само по себе решило бы проблему мерцания, но зачем обновлять пользовательский интерфейс чаще, чем необходимо?)

Комментарии:

1. @Ruzihm Спасибо, да currentPos , был неправ. Я также обновил ответ, чтобы поддержать запрошенную оценку скорости нескольких объектов.

2. Томас, я попробовал ваше решение, и сначала я попробовал его только для цели, даже если цель стоит на месте, не двигаясь вообще, она показывает скорость. Скорость равна 2586.132, и она постоянно меняется, но остается в этом диапазоне значений для скорости, которую я создал одним элементом в массиве и перетащил в него text1 с целевым объектом. Это мой код с вашим решением по ссылке. pastebin.com/RmKfWfsR

3. Если я удалю эту строку transform.position = Vector3.MoveTowards(transform.position, targetToFollow.position, Time.deltaTime * мс); и оставлю ее только в else, преобразование вообще не будет перемещаться при запуске игры. Преобразование должно перемещаться при запуске игры к цели

4. Попробуйте изменить отслеживание скорости на класс. (Я обновил ответ)

5. Не удаляйте нижнюю строку перемещения, а ту, что указана в предложении else .

Ответ №2:

Если вы только хотите знать, какая скорость объекта за определенное время, вы можете сделать что-то вроде этого.

 public class VelocityDisplayer : MonoBehaviour
{

    public Transform Object; // your target gameobject
    public Text View; // your text object
    private Vector3 _position; // last position of target

    private void OnEnable() {
        _position = Object.transform.position;
    }

    private void Update() {
        var dt = Time.deltaTime;
        var current = Object.transform.position;
        var delta = Vector3.Distance(current, _position);
        var velocity = delta / dt;
        View.text = (velocity).ToString("#,##0.000");

        // replace current position
        _position = current;
    }

}
 

но это показывает фактическую скорость, которая зависит от игрового мира / физики объекта, а не от вашей установочной переменной скорости движения

ПС1. Я предпочитаю использовать обновление, потому что это область пользовательского интерфейса

PS2. Я предпочитаю разделить новый класс для отслеживания объекта