不幸的是,我认为没有一种方法可以实现这一点,这在某种程度上是不可思议的并且性能密集。
当然你可以计算它(假设LineRenderer
从位置计数 = 0 开始),例如
public LineRenderer line;
private int positionCount;
private float totalLengthOld;
private void AddPoint(Vector3 position, float width)
{
// increase the position count by one
positionCount++;
// set the count back to the line
line.positionCount = positionCount;
// add our new point
line.SetPosition(positionCount - 1, position);
// now get the current width curve
var curve = line.widthCurve;
// Is this the beginning of the line?
if (positionCount == 1)
{
// First point => simply set the first keyframe
curve.MoveKey(0, new Keyframe(0f, width));
}
else
{
// otherwise get all positions
var positions = new Vector3[positionCount];
line.GetPositions(positions);
// sum up the distances between positions to obtain the length of the line
var totalLengthNew = 0f;
for (var i = 1; i < positionCount; i++)
{
totalLengthNew += Vector3.Distance(positions[i - 1], positions[i]);
}
// calculate the time factor we have to apply to all already existing keyframes
var factor = totalLengthOld / totalLengthNew;
// then store for the next added point
totalLengthOld = totalLengthNew;
// now move all existing keys which are currently based on the totalLengthOld to according positions based on the totalLengthNew
// we can skip the first one as it will stay at 0 always
var keys = curve.keys;
for (var i = 1; i < keys.Length; i++)
{
var key = keys[i];
key.time *= factor;
curve.MoveKey(i, key);
}
// add the new last keyframe
curve.AddKey(1f, width);
}
// finally write the curve back to the line
line.widthCurve = curve;
}
就像一个小演示一样
public class Example : MonoBehaviour
{
public LineRenderer line;
public Transform pen;
[Range(0.01f, 0.5f)] public float width;
public float drawThreshold = 0.1f;
private int positionCount;
private float totalLengthOld;
private Vector3 lastPenPosition;
private void Awake()
{
line = GetComponent<LineRenderer>();
line.useWorldSpace = true;
line.positionCount = 0;
lastPenPosition = pen.position;
}
private void Update()
{
// just for the demo simply ping-pong the width over time
width = Mathf.Lerp(0.01f, 0.8f, Mathf.PingPong(Time.time, 1f));
var currentPenPosition = pen.position;
if (Vector3.Distance(lastPenPosition, currentPenPosition) >= drawThreshold)
{
lastPenPosition = currentPenPosition;
AddPoint(currentPenPosition, width);
}
}
private void AddPoint(Vector3 position, float width)
{
positionCount++;
line.positionCount = positionCount;
line.SetPosition(positionCount - 1, position);
var curve = line.widthCurve;
if (positionCount == 1)
{
curve.MoveKey(0, new Keyframe(0f, width));
}
else
{
var positions = new Vector3[positionCount];
line.GetPositions(positions);
var totalLengthNew = 0f;
for (var i = 1; i < positionCount; i++)
{
totalLengthNew += Vector3.Distance(positions[i - 1], positions[i]);
}
var factor = totalLengthOld / totalLengthNew;
totalLengthOld = totalLengthNew;
var keys = curve.keys;
for (var i = 1; i < keys.Length; i++)
{
var key = keys[i];
key.time *= factor;
curve.MoveKey(i, key);
}
curve.AddKey(1f, width);
}
line.widthCurve = curve;
}
}
当然,在达到一定数量的点后,这会达到性能极限。但我认为这是您目前可以使用的LineRenderer
。否则LineRenderer
可能只是不是正确的绘图工具。
当然,您可以采取一些技巧,在一定数量的点之后,使用以下方法将现有线烘焙成单独的固定网格LineRenderer.BakeMesh https://docs.unity3d.com/ScriptReference/LineRenderer.BakeMesh.html并开始一条新的线,仅将最后一个点作为起点。
这样,只有线条尚未烘焙的部分实际上会受到宽度曲线键移动的影响。
有点像例如
public int meshBakeThreshold = 50;
private void AddPoint(Vector3 position, float width)
{
......
if (positionCount >= meshBakeThreshold)
{
CreateSnapShotAndStartOver(position, width);
}
}
private void CreateSnapShotAndStartOver(Vector3 position, float width)
{
// create a new GameObject that will receive the line snapsho mesh
var snapshotObject = new GameObject("LineSnapshot", typeof(MeshRenderer), typeof(MeshFilter));
// set the material
var renderer = snapshotObject.GetComponent<Renderer>();
renderer.material = line.material;
// bake and set the mesh
var meshFilter = snapshotObject.GetComponent<MeshFilter>();
var mesh = new Mesh();
line.BakeMesh(mesh, Camera.main, true);
meshFilter.mesh = mesh;
// start with a new line at the same current position
positionCount = 0;
AddPoint(position, width);
}
你必须稍微调整一下阈值,50
可能有点低,只是用于演示。您希望在迭代所有关键帧和烘焙网格的性能成本之间找到平衡点;)