odd
odd

Reputation: 1

In my buoyancy project, why is my object jittering when it settles in the water?

I'm working on a buoyancy mechanic and have an issue that I've been trying to solve for a couple of days. Everything is working as intended, aside from the fact that when an object settles in the water, it jitters like crazy. I've tried messing with drag to no avail. My angular drag is set to 3. Any ideas as to what the problem could be? Here's my code and a few gifs of the issue (don't mind the messiness):

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);

        }

    }

}

Upvotes: 0

Views: 52

Answers (1)

Neighborhood Ghost
Neighborhood Ghost

Reputation: 844

Let's first talk about the issue/reason that this is happening. So when our script apply force for buoyancy it send the object above 0(zero), and when object reaches somewhere above 0(zero) we stop applying force onto it. Now because we have rigidbody it will apply gravity thus sending the object below 0(zero) and cycle repets.

I've modified one of your function and added another function.

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));
}

Here Remap() function's work is to check the position.y and depending on its position it will return the intensity of the force that should be added/applied. Here as the object will go below 0 the intensity will increase and if above 0 it will decrease, and if the object is below -0.2f the intensity will be 1 meaning full force, and if above 0.2f the intensity will be the lowest 0.

Note The minimum value should not be 0 and should always be below zero, as this will result in a similar situation as you have right now.

Upvotes: 1

Related Questions