如何使用线渲染器绘制从 A 点到 B 点的正弦波
How to draw a sine wave using line renderer from point A to point B
在 this tutorial 之后,我正在尝试使用 Line Renderer 组件使用输入的鼠标位置绘制从 A 点到 B.I' 的正弦波。但是到目前为止我所做的没有用,它只是沿着 x 轴绘制正弦波,我需要从起点到输入鼠标位置绘制它。
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Vector3 newPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
newPos.z = 0;
CreatePointMarker(newPos);
GenerateNewLine();
}
}
private void CreatePointMarker(Vector3 pointPosition)
{
Instantiate(linePointPrefab, pointPosition, Quaternion.identity);
}
private void GenerateNewLine()
{
GameObject[] allPoints = GameObject.FindGameObjectsWithTag("PointMarker");
Vector3[] allPointPositions = new Vector3[allPoints.Length];
var pointList = new List<Vector3>();
for (int i = 0; i < 50; i ++)
{
var dir = allPoints[0].transform.position - allPoints[1].transform.position;
float x = dir.x * i;
float y = Mathf.Sin(x * Time.time);
var sine = new Vector3(x, y, 0f);
var tangentLine = allPoints[0].transform.position + sine;
pointList.Add(tangentLine);
}
SpawnLineGenerator(pointList.ToArray());
}
}
private void SpawnLineGenerator(Vector3[] linePoints)
{
GameObject newLineGen = Instantiate(lineGeneratorPrefab);
LineRenderer lRend = newLineGen.GetComponent<LineRenderer>();
lRend.positionCount = linePoints.Length;
lRend.SetPositions(linePoints);
}
作为替代方案,我建议改用
lineRenderer.useWorlsSpace = false;
所以这些点不再设置在世界space中,而是在相对于线性渲染器变换的局部space中。
现在您可以简单地旋转 linerenderer 变换以指向最新的用户输入位置。
我无法使用您的代码示例,因为我不知道您的预制件是什么,所以我根据给定视频中的代码创建了自己的预制件。我希望你能reuse/recreate需要的部分
public class SinusWave : MonoBehaviour
{
public Vector3 initalPosition;
public int pointCount = 10;
public LineRenderer line;
private Vector3 secondPosition;
private Vector3[] points;
private float segmentWidth;
private void Awake()
{
line = GetComponent<LineRenderer>();
line.positionCount = pointCount;
// tell the linerenderer to use the local
// transform space for the point coorindates
line.useWorldSpace = false;
points = new Vector3[pointCount];
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
// Camera.main.ScreenToWorldPoint needs a value in Z
// for the distance to camera
secondPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition - Vector3.forward * Camera.main.transform.position.z);
secondPosition.z = 0;
var dir = secondPosition - initalPosition;
// get the segmentWidth from distance to end position
segmentWidth = Vector3.Distance(initalPosition, secondPosition) / pointCount;
// get the difference angle in the Z axis between the current transform.right
// and the direction
var angleDifference = Vector3.SignedAngle(transform.right, dir, Vector3.forward);
// and rotate the linerenderer transform by that angle in the Z axis
// so the result will be that it's transform.right
// points now towards the clicked position
transform.Rotate(Vector3.forward * angleDifference, Space.World);
}
for (var i = 0; i < points.Length; ++i)
{
float x = segmentWidth * i;
float y = Mathf.Sin(x * Time.time);
points[i] = new Vector3(x, y, 0);
}
line.SetPositions(points);
}
}
顺便说一句,我只是假设 GameObject.FindGameObjectsWithTag("PointMarker");
实际上会重新调整所有到目前为止生成的 linePointPrefab
对象。
当你像
一样生成它们时,最好立即存储它们
private List<Transform> allPoints = new List<Transform>();
...
allPoints.Add(Instantiate(linePointPrefab, pointPosition, Quaternion.identity).transform);
那么你可以完全跳过FindObjectsWithType
的用法
为了采用此本地 space 位置也适用于您实例化的线点预制件,只需将它们实例化为 linerenderer 变换的子级或在同一父级下生成它们和 linerenderer,以便相对位置相同。在这种情况下,您不会旋转线性渲染器,而是旋转整个父对象,因此生成的线点会随之旋转
在 this tutorial 之后,我正在尝试使用 Line Renderer 组件使用输入的鼠标位置绘制从 A 点到 B.I' 的正弦波。但是到目前为止我所做的没有用,它只是沿着 x 轴绘制正弦波,我需要从起点到输入鼠标位置绘制它。
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Vector3 newPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
newPos.z = 0;
CreatePointMarker(newPos);
GenerateNewLine();
}
}
private void CreatePointMarker(Vector3 pointPosition)
{
Instantiate(linePointPrefab, pointPosition, Quaternion.identity);
}
private void GenerateNewLine()
{
GameObject[] allPoints = GameObject.FindGameObjectsWithTag("PointMarker");
Vector3[] allPointPositions = new Vector3[allPoints.Length];
var pointList = new List<Vector3>();
for (int i = 0; i < 50; i ++)
{
var dir = allPoints[0].transform.position - allPoints[1].transform.position;
float x = dir.x * i;
float y = Mathf.Sin(x * Time.time);
var sine = new Vector3(x, y, 0f);
var tangentLine = allPoints[0].transform.position + sine;
pointList.Add(tangentLine);
}
SpawnLineGenerator(pointList.ToArray());
}
}
private void SpawnLineGenerator(Vector3[] linePoints)
{
GameObject newLineGen = Instantiate(lineGeneratorPrefab);
LineRenderer lRend = newLineGen.GetComponent<LineRenderer>();
lRend.positionCount = linePoints.Length;
lRend.SetPositions(linePoints);
}
作为替代方案,我建议改用
lineRenderer.useWorlsSpace = false;
所以这些点不再设置在世界space中,而是在相对于线性渲染器变换的局部space中。
现在您可以简单地旋转 linerenderer 变换以指向最新的用户输入位置。
我无法使用您的代码示例,因为我不知道您的预制件是什么,所以我根据给定视频中的代码创建了自己的预制件。我希望你能reuse/recreate需要的部分
public class SinusWave : MonoBehaviour
{
public Vector3 initalPosition;
public int pointCount = 10;
public LineRenderer line;
private Vector3 secondPosition;
private Vector3[] points;
private float segmentWidth;
private void Awake()
{
line = GetComponent<LineRenderer>();
line.positionCount = pointCount;
// tell the linerenderer to use the local
// transform space for the point coorindates
line.useWorldSpace = false;
points = new Vector3[pointCount];
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
// Camera.main.ScreenToWorldPoint needs a value in Z
// for the distance to camera
secondPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition - Vector3.forward * Camera.main.transform.position.z);
secondPosition.z = 0;
var dir = secondPosition - initalPosition;
// get the segmentWidth from distance to end position
segmentWidth = Vector3.Distance(initalPosition, secondPosition) / pointCount;
// get the difference angle in the Z axis between the current transform.right
// and the direction
var angleDifference = Vector3.SignedAngle(transform.right, dir, Vector3.forward);
// and rotate the linerenderer transform by that angle in the Z axis
// so the result will be that it's transform.right
// points now towards the clicked position
transform.Rotate(Vector3.forward * angleDifference, Space.World);
}
for (var i = 0; i < points.Length; ++i)
{
float x = segmentWidth * i;
float y = Mathf.Sin(x * Time.time);
points[i] = new Vector3(x, y, 0);
}
line.SetPositions(points);
}
}
顺便说一句,我只是假设 GameObject.FindGameObjectsWithTag("PointMarker");
实际上会重新调整所有到目前为止生成的 linePointPrefab
对象。
当你像
一样生成它们时,最好立即存储它们private List<Transform> allPoints = new List<Transform>();
...
allPoints.Add(Instantiate(linePointPrefab, pointPosition, Quaternion.identity).transform);
那么你可以完全跳过FindObjectsWithType
的用法
为了采用此本地 space 位置也适用于您实例化的线点预制件,只需将它们实例化为 linerenderer 变换的子级或在同一父级下生成它们和 linerenderer,以便相对位置相同。在这种情况下,您不会旋转线性渲染器,而是旋转整个父对象,因此生成的线点会随之旋转