问题描述
美好的一天,
我想编写一个在两个固定物体(object1
,object2
)之间传递的不断移动的球(object3
),并能够动态设置传递轨迹的最大高度Y
I'd like to program a constantly moving ball (object3
) being passed between two stationary objects (object1
, object2
), with the ability to set the max height Y
of the pass trajectory dynamically.
您会争论为这个概念编程球物理的最佳方法是什么?
What would you argue is the best way to program the ball physics for this concept?
我看过在带有刚体的默认球体上使用addForce
的情况.似乎应该存在一个方程,该表达式表示从object1
的x到object2
的x的object3
的轨迹...在已知的情况下,给定speed
,且已知的设置mass
,以及已知的重力环境.
I've looked at using addForce
on a default sphere w/ a rigidbody. It seems like there should be an equation that expresses the trajectory of a pass of object3
from object1
's x to object2
's x... at a known, given speed
, with a known, set mass
, and a known gravity environment.
但是,目前我有一个Vector3.Lerp
插值球,每个FixedUpdate()
的两个对象之间的球都以t
表示:
However, currently I have a Vector3.Lerp
interpolating the ball between the two objects on each FixedUpdate()
with t
expressed as:
`(Mathf.Sin(speed * Time.time) + 1.0f) / 2.0f;`
一切正常,但是使用这种方法,似乎没有明确的方法将height
添加到球的轨迹中.我已经考虑过将height
添加到object2
中的Y
值,直到球居中,然后将其设置回原始的Y
位置...但是感觉很不对!有想法吗?
It works and all, but with this approach, it seems there's no clear way to add height
to the trajectory of the ball path. I've considered adding the height
to the Y
value in object2
until the ball is half way there, and then setting it back to the original Y
position... but it just feels wrong! Thoughts?
谢谢!
推荐答案
好的,如果我目前对您的理解正确,
Okey so if I understand you correctly currently you are doing
privte void FixedUpdate()
{
var factor = (Mathf.Sin(speed * Time.time) + 1.0f) / 2.0f;
object1.MovePosition(Vector3.Lerp(object2.position, object3.position, factor));
}
可以使乒乓球在object1
和object2
位置之间移动,但只能是平面.
which moves the ball pingpong between object1
and object2
position but only planar.
假设目前这些对象将仅在XZ平面内移动,并且永不具有不同的Y位置,为了获得具有高度的曲线,您可以分别处理: -和以前一样在两个位置之间进行插值 -使用窦或任何其他数学曲线函数分别计算Y位置-对于现实物理学来说,实际上可能是抛物线
Assuming for now the objects will only be moving within the XZ plane and never have different Y position in order to rather get a curve with height you could treat the separatly: - Interpolate between both positions as before - Separately calculate the Y position with sinus or any other mathematical curve function - for realistic physics probably rather a parabola actually
看起来很像
public class Example : MonoBehaviour
{
public Rigidbody object1;
public Transform object2;
public Transform object3;
// adjust in the Inspector
public float speed = 1;
public float Amplitude = 0;
// Just for debug
[Range(0, 1)] [SerializeField] private float linearFactor;
[SerializeField] private float yPosition;
private void FixedUpdate()
{
// This always returns a value between 0 and 1
// and linearly pingpongs forth and back
linearFactor = Mathf.PingPong(Time.time * speed, 1);
// * Mathf.PI => gives now a value 0 - PI
// so sinus returns correctly 0 - 1 (no need for +1 and /2 anymore)
// then simply multiply by the desired amplitude
var sinus = Mathf.Sin(linearFactor * Mathf.PI);
yPosition = sinus * Amplitude;
// As before interpolate between the positions
// later we will ignore/replace the Y component
var position = Vector3.Lerp(object2.position, object3.position, linearFactor);
object1.MovePosition(new Vector3(position.x, yPosition, position.z));
}
}
您还可以选择尝试在Y方向上添加一些转储,以使垂直运动更加逼真(达到峰值时变慢).我尝试使用像这样的倒置SmoothStep
You could optionally also try and add some dumping in the Y direction in order to make the vertical movement more realistic (slow down when reaching the peak). I tried a bit using inverted SmoothStep
like
// just for debug
[Range(0, 1)] [SerializeField] private float dampedSinusFactor;
[Range(0, 1)] [SerializeField] private float linearFactor;
[SerializeField] private float yPosition;
private void FixedUpdate()
{
// Use two different factros:
// - a linear one for movement in XZ
// - a smoothed one for movement in Y (in order to slow down when reaching the peak ;) )
linearFactor = Mathf.PingPong(Time.time * speed, 1);
dampedSinusFactor = InvertSmoothStep(linearFactor);
// * Mathf.PI => gives now a value 0 - PI
// so sinus returns correctly 0 - 1 ()
// then simply multiply by the desired amplitude
var sinus = Mathf.Sin(dampedSinusFactor * Mathf.PI);
yPosition = sinus * Amplitude;
// later we will ignore/replace the Y component
var position = Vector3.Lerp(object2.position, object3.position, linearFactor);
object1.position = new Vector3(position.x, yPosition, position.z);
}
// source: https://stackoverflow.com/a/34576808/7111561
private float InvertSmoothStep(float x)
{
return x + (x - (x * x * (3.0f - 2.0f * x)));
}
但是对于慢速移动,这看起来有些奇怪.但是您可以提出任何其他数学曲线,从而得出x=[0,1]
;)
However for slow movements this looks a bit strange yet. But you can come up with any other maths curve that results in the expected behavior for x=[0,1]
;)
这篇关于球力学-这是最好的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!