c# - 如何创建以终点为鼠标位置但仅面向一个方向的线渲染器

标签 c# unity3d line

我有两个对象,一条线从一个到另一个,如下所示:

enter image description here

我想创建另一条线,起点是一个对象,终点是鼠标位置,但仍然面向第二个对象,这看起来就像第一条线填满了鼠标所在的位置,就像这样:

enter image description here

没有办法(据我所知)在 Unity 中设置线渲染器的方向,那么我该如何实现呢?

连接形状的代码:

 public void AddShape(GameObject shape) {
    selectedShape = shape;
    selectedShapeComp = shape.GetComponent<Shape>();

    if (!selectedShapes.Contains(selectedShape) && (selectedShapes.Count == 0 || selectedShape.CompareTag(selectedShapes[0].tag))) {
        currentAdjacentShapes = selectedShapeComp.GetAdjacentShapes();

        if (selectedShapes.Count == 0 && !selectedShapeComp.key) return; //If it's first and not a key, don't add it
        if (selectedShapes.Count == 0 && selectedShapeComp.key) activeKeys++; //If it's first and is a key, continue

        FindCurrentlyAdjacentShapes();

        if (currentAdjacentShapes != null && !currentAdjacentShapes.Contains(selectedShape)) return; //If it's not adjacent to previous shape, don't add it

        selectedShapes.Add(selectedShape);
        MarkShape();

        if (selectedShapes.Count > 1 && selectedShapeComp.key) MarkLeftOutShapes();

        SelectionLineSpawner.instance.SpawnLine();
    }

    ClearShapesAhead();
    CalculateSelectedShapesAmount();
}

private void RemoveShape(int index) {
    UnmarkShape(selectedShapes[index]);
    selectedShapes.RemoveAt(index);
}

private void ClearShapesAhead() {
    for (int i = selectedShapes.Count; i > selectedShapeComp.selectedPos; i--) {
        RemoveShape(i - 1);
    }
}

private void FindCurrentlyAdjacentShapes() {
    if (selectedShapes.Count > 1) {
        currentAdjacentShapes = selectedShapes[selectedShapes.Count - 1].GetComponent<Shape>().GetAdjacentShapes();
    }
}

private void MarkLeftOutShapes() {
    var shapes = new List<GameObject>();

    switch (selectedShape.tag) {
        case "Diamond":
            shapes = LevelLoader.instance.currentLevel.GetAllDiamonds();
            break;
        case "Triangle":
            shapes = LevelLoader.instance.currentLevel.GetAllTriangles();
            break;
    }

    foreach (var shape in shapes) {
        if (!selectedShapes.Contains(shape)) {
            Debug.Log("Not selected: " + shape.name);
        }
    }
}

private void MarkShape() {
    selectedShape.gameObject.GetComponent<SpriteRenderer>().color = Color.black;
    selectedShape.gameObject.GetComponent<Animator>().SetTrigger("select");
    selectedShapeComp.selected = true;
    selectedShapeComp.selectedPos = selectedShapes.Count;
}

private void UnmarkShape(GameObject shape) {
    var shapeComp = shape.GetComponent<Shape>();
    shapeComp.selected = true;
    shapeComp.selectedPos = 0;
    shape.gameObject.GetComponent<SpriteRenderer>().color = Color.white;
}

private void CalculateSelectedShapesAmount() {
    switch (selectedShape.tag) {
        case "Diamond":
            LevelLoader.instance.currentLevel.selectedDiamonds = selectedShapes.Count;
            break;
        case "Triangle":
            LevelLoader.instance.currentLevel.selectedTriangles = selectedShapes.Count;
            break;
    }
}

private void DrawLines() {
    foreach (var shape in LevelLoader.instance.currentLevel.GetAllShapes()) {
        var adjacentShapes = shape.GetComponent<Shape>().GetAdjacentShapes();

        foreach (var adjacentShape in adjacentShapes) {
            var lineClone = Instantiate(line);
            lineClone.transform.parent = shape.transform;
            var lineComp = lineClone.GetComponent<Line>();

            foreach (Transform child in adjacentShape.transform) {
                if (child.CompareTag("Line"))
                    if (child.GetComponent<Line>().origin != adjacentShape)
                        lineComp.DrawLine(shape, adjacentShape);
            }

            if (!lineComp.IsDrawn())
                Destroy(lineClone);
        }
    }
}

最佳答案

以下是实现您想要的内容的步骤:

  • 在由两个物体和相机定义的平面上找到鼠标的世界位置,
  • 找到从该位置到两个对象之间的线最近的点,
  • 绘制从起始对象到最近点的线

这是一个可以指导您的代码:

using UnityEngine;
public class Question : MonoBehaviour {
    public Vector3 startPosition = Vector3.left * 5;
    public Vector3 endPosition = Vector3.right * 5;

    void OnDrawGizmos() {
        Gizmos.color = Color.blue;
        Gizmos.DrawCube(startPosition, Vector3.one);
        Gizmos.DrawSphere(endPosition, 1);

        Gizmos.color = Color.yellow;
        Gizmos.DrawLine(startPosition, endPosition);

        var mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
        var mousePos = mouseRay.GetPoint(Mathf.Abs(Camera.main.transform.position.z));
        var pointOnLine = ClosestPointOnLine(startPosition, endPosition, mousePos, true);

        Gizmos.color = Color.black;
        Gizmos.DrawLine(startPosition, pointOnLine);
    }

    /// <summary> Returns the point nearest point to the [point] on the line given by start and end points, [lineStart] and [lineEnd]</summary>
    /// <param name="clampLine"> If true, the returned point will be on the line segment, rather than the line. </param>
    public static Vector3 ClosestPointOnLine(Vector3 lineStart, Vector3 lineEnd, Vector3 point, bool clampLine = false) {
        var dif = lineEnd - lineStart;
        var direction = Vector3.Normalize(dif);
        float closestPoint = Vector3.Dot((point - lineStart), direction) / dif.magnitude;
        if (clampLine)
            closestPoint = Mathf.Clamp(closestPoint, 0, 1);
        return lineStart + (closestPoint * dif);
    }
}

要测试此代码,只需将其粘贴到一个文件中,在场景中创建一个游戏对象并将此组件添加到其中。这仅适用于正交相机。

ClosestPointOnLine 方法可以在许多情况下为您提供帮助,因此我将其记录在案。

关于c# - 如何创建以终点为鼠标位置但仅面向一个方向的线渲染器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40377565/

相关文章:

javascript - 如何在 Cordova 读取本地文本文件?

java - Line2D 的 Android 替代品?

c# - 将 .NET 4 线程转换为 .NET 2

android - Unity3D:无需重新插入即可在两台 Android 设备上构建和运行

c# - 在检查器中设置值是否与在 Unity 中设置默认值相同?

ios - 为什么更新到 Xcode 12 后会出现链接错误?

c# - 如何在c#中的String末尾跳出while循环

c# - 如何在 wp7 的隔离存储中存储整数值?

c# - 寻找完全托管的 WeifenLuo(DockPanel Suite)替代品或实现替代品的提示

perl - 在perl中根据行号修剪行