#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
параметр немного ниже этого. и вы должны быть готовы к работе. потому что здесь происходит то, что по мере того, как объект становится все выше и выше, прикладываемая сила ослабевает / уменьшается, поэтому, когда объект находится наверху, сила будет присутствовать, но настолько мала, что она не будет заметна.