В моем проекте плавучести, почему мой объект дрожит, когда он оседает в воде?

#c# #unity3d

Вопрос:

Я работаю над механикой плавучести, и у меня возникла проблема, которую я пытался решить пару дней. Все работает так, как задумано, за исключением того факта, что когда объект оседает в воде, он дрожит как сумасшедший. Я пытался возиться с перетаскиванием, но безрезультатно. Мое угловое сопротивление установлено на 3. Есть идеи относительно того, в чем может быть проблема? Вот мой код и несколько gif-файлов проблемы (не обращайте внимания на беспорядок):

https://gyazo.com/e6ccddc26516d6eba85cf410a20c11c0
https://gyazo.com/882d64c694296ab8cd80fb15513c1924

 public class Buoyancy : MonoBehaviour
{

    // Variables
    public float buoyancy, viscosity;

    public Transform[] floatPoints;
    [HideInInspector] public List<Vector3> floatPointPositions;

    public Vector3 centerPoint;

    Rigidbody objRb;

    private void Start()
    {

        objRb = GetComponent<Rigidbody>();

    }

    private void Update()
    {

        GetUnderwaterCenter();

        // Debug
        Debug.DrawLine(new Vector3(0, 10, 0), centerPoint, Color.yellow);

    }

    private void FixedUpdate()
    {

        ObjectBuoyancy();
        
    }

    void GetUnderwaterCenter()
    {

        floatPointPositions.Clear();

        if (transform.position.y <= 0)
        {

            for (int i = 0; i < floatPoints.Length; i  )
            {

                if (floatPoints[i].position.y <= 0)
                {

                    floatPointPositions.Add(new Vector3(floatPoints[i].position.x, floatPoints[i].position.y, floatPoints[i].position.z));

                }

            }

            centerPoint = Vector3.zero;

            for (int i = 0; i < floatPointPositions.Count; i  )
            {

                centerPoint  = floatPointPositions[i];

            }

            centerPoint /= floatPointPositions.Count;

        }

    }

    void ObjectBuoyancy()
    {

        if(floatPointPositions.Count > 0)
        {

            objRb.AddForceAtPosition(Vector3.up * buoyancy, centerPoint);
            objRb.AddForce(-objRb.velocity * viscosity);

        }

    }

}
 

Ответ №1:

Давайте сначала поговорим о проблеме / причине, по которой это происходит. Поэтому, когда наш скрипт применяет силу для плавучести, он отправляет объект выше 0(zero) , и когда объект достигает где-то выше 0(zero) , мы прекращаем применять к нему силу. Теперь, поскольку у нас есть rigidbody, он будет применять гравитацию, отправляя объект ниже 0(zero) и повторяя цикл.

Я изменил одну из ваших функций и добавил другую функцию.

 void ObjectBuoyancy()
{
    if (floatPointPositions.Count > 0)
    {
        float forceIntensity = Remap(1, 0, -0.2f, 0.2f, transform.position.y);
        objRb.AddForceAtPosition(Vector3.up * Mathf.Lerp(0, buoyancy, forceIntensity), centerPoint);
        objRb.AddForce(-objRb.velocity * Mathf.Lerp(0, viscosity, forceIntensity));
    }
}

float Remap(float remapMin, float remapMax, float valueMin, float valueMax, float value)
{
    return Mathf.Lerp (remapMin, remapMax, Mathf.InverseLerp (valueMin, valueMax, value));
}
 

Здесь Remap() работа функции заключается в проверке положения.y и в зависимости от его положения он вернет интенсивность силы, которая должна быть добавлена / применена. Здесь, когда объект опустится ниже 0, интенсивность увеличится, а если выше 0, она уменьшится, и если объект ниже -0.2f , интенсивность будет равна 1, что означает полную силу, а если выше 0.2f , интенсивность будет наименьшей 0.

Обратите внимание, что минимальное значение не должно быть 0 и всегда должно быть ниже нуля, так как это приведет к аналогичной ситуации, как у вас сейчас.

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

1. Я планирую добавить поддержку волн в будущем, когда уровень воды не будет точно равен y = 0 и будет колебаться. Могу ли я как-то изменить код для этого? Спасибо.

2. Итак, каким бы ни был ваш вертикальный предел, убедитесь, что valueMin параметр немного ниже этого. и вы должны быть готовы к работе. потому что здесь происходит то, что по мере того, как объект становится все выше и выше, прикладываемая сила ослабевает / уменьшается, поэтому, когда объект находится наверху, сила будет присутствовать, но настолько мала, что она не будет заметна.