【发布时间】:2021-09-12 22:54:18
【问题描述】:
【问题讨论】:
-
会用 B 位置减去 C 位置来得到方向 Vector 并使用 AddForce(Vector3 force, ForceMode.Force) 方法施加力;工作吗?
-
@Armin no ... OP 希望在实际物理发生之前预览行;)
标签: c# unity3d prediction direction
【问题讨论】:
标签: c# unity3d prediction direction
您宁愿使用Physics.SphereCast(根据您的球形状)而不是Raycast,或者您也可以使用Rigidbody.SweepTest 来获取如果您反对的命中信息会移动。
两者都为您提供信息
是否被击中(例如,通过标签检查首先击中的是墙还是另一个球)
两者都给你一个RaycastHit,其中包含详细信息,例如
其余的是The Math and Physics of Billard 或Physics of Billard 等,你会发现完整的答案对于这个页面来说是复杂的;)
在手动计算物理时,有很多事情需要考虑,首先你需要确定你想要的实际程度。有旋转、摩擦、跳跃,你知道在现实世界中根本不存在任何完全弹性的碰撞......所以男孩,如果你要手动预先计算所有这些,你也可以自己写物理引擎;)
现在作为所有这些的完全替代方法,它根本不需要您计算任何东西:
您可以模拟整个物理学!
你可以
Physics.Simulate,作为条件检查两个调用之间是否有任何球体移动 -> 如果没有(或在某个预览时间之后)则中断。=> 你已经获得了 LineRenderer 每个球的所有跟踪点;)
您甚至可以使用位置来爱自己的球,而不是再次使用物理来显示实际的运动;)
对于大型系统,这当然会导致巨大的延迟(也取决于您的目标预览时间范围)。但我会说,对于有限数量的球来说,这应该没问题。
这是我在几分钟内拼凑起来的一小段代码(当然不完美)
public class Example : MonoBehaviour
{
public Ball[] balls;
public Ball whiteBall;
public Vector3 direction;
public float force;
private class TransformData
{
public Vector3 Position;
public Quaternion Rotation;
private readonly Transform _transform;
public TransformData(Transform transform)
{
_transform = transform;
Update();
}
public void Update()
{
Position = _transform.position;
Rotation = _transform.rotation;
}
}
public float maxPreviewTime = 10;
public bool continousUpdates;
private const float physicsSteps = 0.02f;
private readonly Dictionary<Ball, TransformData> initialPositions = new Dictionary<Ball, TransformData>();
private readonly Dictionary<Ball, List<Vector3>> simulatedPositions = new Dictionary<Ball, List<Vector3>>();
private void Awake()
{
foreach (var ball in balls)
{
initialPositions.Add(ball, new TransformData(ball.transform));
simulatedPositions.Add(ball, new List<Vector3>());
}
}
private void Update()
{
if (continousUpdates)
{
UpdateLines();
}
if (Input.GetKeyDown(KeyCode.Space))
{
whiteBall.Rigidbody.AddForce(direction.normalized * force, ForceMode.Impulse);
}
}
[ContextMenu("Update Preview Lines")]
public void UpdateLines()
{
foreach (var transformData in initialPositions.Values)
{
transformData.Update();
}
foreach (var list in this.simulatedPositions.Values)
{
list.Clear();
}
Physics.autoSimulation = false;
var somethingChanged = true;
var simulatedTime = 0f;
whiteBall.Rigidbody.AddForce(direction.normalized * force, ForceMode.Impulse);
while (somethingChanged && simulatedTime < maxPreviewTime)
{
somethingChanged = false;
Physics.Simulate(physicsSteps);
foreach (var kvp in simulatedPositions)
{
var ball = kvp.Key;
var positions = kvp.Value;
var currentPosition = ball.transform.position;
var hasChanged = positions.Count == 0 || (positions.Count > 0 && currentPosition != positions[positions.Count - 1]);
if (hasChanged)
{
positions.Add(currentPosition);
}
somethingChanged = somethingChanged || hasChanged;
}
simulatedTime += physicsSteps;
}
foreach (var kvp in initialPositions)
{
kvp.Key.Rigidbody.velocity = Vector3.zero;
kvp.Key.Rigidbody.angularVelocity = Vector3.zero;
kvp.Key.Rigidbody.position = kvp.Value.Position;
kvp.Key.Rigidbody.rotation = kvp.Value.Rotation;
}
foreach (var kvp in simulatedPositions)
{
var ball = kvp.Key;
var positions = kvp.Value;
ball.Line.positionCount = positions.Count;
ball.Line.SetPositions(positions.ToArray());
}
Physics.autoSimulation = true;
}
}
【讨论】: