Unity'de doğru bir çizgi nasıl çizilir


27

Daha resmi olarak söylenen tek bir noktadan birkaç satır çizmemi gerektiren bir oyun üzerinde çalışıyorum.

Verilen nokta A, x, y koordinatlarıyla, i-th çizgisinin, xi, yi olarak adlandırılan koordinatlara sahip olduğu n çizgileri çiziyorum. Unity3D içerisindeki LineRenderer yetenekleri göz önüne alındığında, sadece polinler oluşturduğundan belirli bir noktadan birden fazla çizgi çizemedim.

Şu anda hattı başarıyla oluşturan Debug.DrawLine () yöntemini kullanıyorum. Unity örneğinde gösterildiği gibi GL.Begin () yöntemini kullanmayı denedim, ancak çizgilerimin çizildiğini göremiyorum.

Sorum şu: Bunu yapmak için başka yöntemler var mı? Eğer değilse, bana Debug.DrawLine () ile çizilen çizgiyi oyun modunda nasıl gösterebilirim? Gizmos.DrawLine () kullanabileceğimi gördüm ama kullanımının tam olarak farkında değildim.

Yanıtlar:


48

GL Lines'ın Kullanımı:

GL API'yi çizim çizgileri için kullanmanızı tavsiye ederim . Çizgi kalınlığı her zaman ekranda 1 piksel olacaktır ve onu değiştirme seçeneği yoktur. Aynı zamanda gölgeler de olmayacak.

GL yöntemi çağrıları derhal yürütülür, bu nedenle kamera hazırlandıktan sonra onları aradığınızdan emin olmanız gerekir.

Komut dosyasını kameraya eklemek ve Camera.OnPostRender () kullanarak oyun penceresinde işlemek için iyi çalışır. Editörde göstermelerini sağlamak için MonoBehaviour.OnDrawGizmos () öğesini kullanabilirsiniz. .

İşte GL API ile bir çizgi çekmek için barebones kodu:

public Material lineMat = new Material("Shader \"Lines/Colored Blended\" {" + "SubShader { Pass { " + "    Blend SrcAlpha OneMinusSrcAlpha " + "    ZWrite Off Cull Off Fog { Mode Off } " + "    BindChannels {" + "      Bind \"vertex\", vertex Bind \"color\", color }" + "} } }");

void OnPostRender() {
    GL.Begin(GL.LINES);
    lineMat.SetPass(0);
    GL.Color(new Color(0f, 0f, 0f, 1f));
    GL.Vertex3(0f, 0f, 0f);
    GL.Vertex3(1f, 1f, 1f);
    GL.End();
}

İşte verilen tüm noktaları ana noktaya bağlayan tam bir senaryo. Kod yorumlarında doğru şekilde ayarlanması ve neler olup bittiğiyle ilgili bazı talimatlar vardır.

Bağlantı hatlarının rengini değiştirme konusunda sorun yaşıyorsanız, hat malzemenizde gibi köşe rengini dikkate alan bir gölgelendirici kullandığınızdan emin olun Unlit/Color.

using UnityEngine;
using System.Collections;

// Put this script on a Camera
public class DrawLines : MonoBehaviour {

    // Fill/drag these in from the editor

    // Choose the Unlit/Color shader in the Material Settings
    // You can change that color, to change the color of the connecting lines
    public Material lineMat;

    public GameObject mainPoint;
    public GameObject[] points;

    // Connect all of the `points` to the `mainPoint`
    void DrawConnectingLines() {
        if(mainPoint && points.Length > 0) {
            // Loop through each point to connect to the mainPoint
            foreach(GameObject point in points) {
                Vector3 mainPointPos = mainPoint.transform.position;
                Vector3 pointPos = point.transform.position;

                GL.Begin(GL.LINES);
                lineMat.SetPass(0);
                GL.Color(new Color(lineMat.color.r, lineMat.color.g, lineMat.color.b, lineMat.color.a));
                GL.Vertex3(mainPointPos.x, mainPointPos.y, mainPointPos.z);
                GL.Vertex3(pointPos.x, pointPos.y, pointPos.z);
                GL.End();
            }
        }
    }

    // To show the lines in the game window whne it is running
    void OnPostRender() {
        DrawConnectingLines();
    }

    // To show the lines in the editor
    void OnDrawGizmos() {
        DrawConnectingLines();
    }
}

Gölgeler hakkında daha fazla not: Gölge yapmak için bir geometri gölgelendirici kullanarak araştırdım, ancak GL çağrıları derhal yürütüldüğünden, normal görüntü oluşturma hattında değiller AutoLight.cgincveLighting.cginc cevap vermem ShadowCastergeçmek.


Gölgeli ve Yarıçaplı Çizgiler

Çizgi kalınlığını değiştirmeniz gerekiyorsa ve gerçekçi gölgelere sahip olmak istiyorsanız. Sadece bir silindir ağ kullanın ve yüksekliği ölçeklendirin.

İşte her noktayı ana noktaya bağlamak için bir silindir yapacak bir betik. Boş bir oyun nesnesine yerleştirin ve parametreleri doldurun. Tüm ekstra bağlantı nesnelerini tutacaktır.

using UnityEngine;
using System.Collections;

public class ConnectPointsWithCylinderMesh : MonoBehaviour {

    // Material used for the connecting lines
    public Material lineMat;

    public float radius = 0.05f;

    // Connect all of the `points` to the `mainPoint`
    public GameObject mainPoint;
    public GameObject[] points;

    // Fill in this with the default Unity Cylinder mesh
    // We will account for the cylinder pivot/origin being in the middle.
    public Mesh cylinderMesh;


    GameObject[] ringGameObjects;

    // Use this for initialization
    void Start () {
        this.ringGameObjects = new GameObject[points.Length];
        //this.connectingRings = new ProceduralRing[points.Length];
        for(int i = 0; i < points.Length; i++) {
            // Make a gameobject that we will put the ring on
            // And then put it as a child on the gameobject that has this Command and Control script
            this.ringGameObjects[i] = new GameObject();
            this.ringGameObjects[i].name = "Connecting ring #" + i;
            this.ringGameObjects[i].transform.parent = this.gameObject.transform;

            // We make a offset gameobject to counteract the default cylindermesh pivot/origin being in the middle
            GameObject ringOffsetCylinderMeshObject = new GameObject();
            ringOffsetCylinderMeshObject.transform.parent = this.ringGameObjects[i].transform;

            // Offset the cylinder so that the pivot/origin is at the bottom in relation to the outer ring gameobject.
            ringOffsetCylinderMeshObject.transform.localPosition = new Vector3(0f, 1f, 0f);
            // Set the radius
            ringOffsetCylinderMeshObject.transform.localScale = new Vector3(radius, 1f, radius);

            // Create the the Mesh and renderer to show the connecting ring
            MeshFilter ringMesh = ringOffsetCylinderMeshObject.AddComponent<MeshFilter>();
            ringMesh.mesh = this.cylinderMesh;

            MeshRenderer ringRenderer = ringOffsetCylinderMeshObject.AddComponent<MeshRenderer>();
            ringRenderer.material = lineMat;

        }
    }

    // Update is called once per frame
    void Update () {
        for(int i = 0; i < points.Length; i++) {
            // Move the ring to the point
            this.ringGameObjects[i].transform.position = this.points[i].transform.position;

            // Match the scale to the distance
            float cylinderDistance = 0.5f*Vector3.Distance(this.points[i].transform.position, this.mainPoint.transform.position);
            this.ringGameObjects[i].transform.localScale = new Vector3(this.ringGameObjects[i].transform.localScale.x, cylinderDistance, this.ringGameObjects[i].transform.localScale.z);

            // Make the cylinder look at the main point.
            // Since the cylinder is pointing up(y) and the forward is z, we need to offset by 90 degrees.
            this.ringGameObjects[i].transform.LookAt(this.mainPoint.transform, Vector3.up);
            this.ringGameObjects[i].transform.rotation *= Quaternion.Euler(90, 0, 0);
        }
    }
}


2
Booo, çizgilerin gölgesi yok. : p
MichaelHouse

Bu harika bir cevap. Orada benim için neyin olduğunu inceliyorum. Ayrıntı için çok teşekkürler, buna benzer bir şey başarabildim. Nerede yanlış gittiğimi görmek için örneğinize çok iyi bakacağım. Teşekkürler!
Christo

OnPostRender kullanmadan bunu yapabilir miyim?
Christo

Çünkü bunu mono davranıştan türetilmeyen özel bir sınıfta yapmam gerekiyor, bu yüzden OnPostRender yöntemim yok.
Christo

1
GL.Color () 'da hangi rengi koyduğum ya da hiç adlandırıp kullanmadığım önemli değil - çizgilerin rengi malzemenin renginde kalır. Çizgi malzemem şu anda gölgelendirici Unlit / Color kullanıyor.
Erhannis

5

Küp ile Gölgeler ve Yarıçapı olan çizgiler

Off gidiyor @ MadLittleMod cevabı burada, küp tabanlı çizgiler (kullanarak başka versiyonu : 12 tris yerine Silindir bazlı hatların (arasında) : 80 tris ):

using UnityEngine;
using System.Collections;

public class ConnectPointsWithCubeMesh : MonoBehaviour 
{

    // Material used for the connecting lines
    public Material lineMat;

    public float radius = 0.05f;

    // Connect all of the `points` to the `mainPoint`
    public GameObject mainPoint;
    public GameObject[] points;

    // Fill in this with the default Unity Cube mesh
    // We will account for the cube pivot/origin being in the middle.
    public Mesh cubeMesh;


    GameObject[] ringGameObjects;

    // Use this for initialization
    void Start() 
    {
        this.ringGameObjects = new GameObject[points.Length];
        //this.connectingRings = new ProceduralRing[points.Length];
        for(int i = 0; i < points.Length; i++) {
            // Make a gameobject that we will put the ring on
            // And then put it as a child on the gameobject that has this Command and Control script
            this.ringGameObjects[i] = new GameObject();
            this.ringGameObjects[i].name = "Connecting ring #" + i;
            this.ringGameObjects[i].transform.parent = this.gameObject.transform;

            // We make a offset gameobject to counteract the default cubemesh pivot/origin being in the middle
            GameObject ringOffsetCubeMeshObject = new GameObject();
            ringOffsetCubeMeshObject.transform.parent = this.ringGameObjects[i].transform;

            // Offset the cube so that the pivot/origin is at the bottom in relation to the outer ring     gameobject.
            ringOffsetCubeMeshObject.transform.localPosition = new Vector3(0f, 1f, 0f);
            // Set the radius
            ringOffsetCubeMeshObject.transform.localScale = new Vector3(radius, 1f, radius);

            // Create the the Mesh and renderer to show the connecting ring
            MeshFilter ringMesh = ringOffsetCubeMeshObject.AddComponent<MeshFilter>();
            ringMesh.mesh = this.cubeMesh;

            MeshRenderer ringRenderer = ringOffsetCubeMeshObject.AddComponent<MeshRenderer>();
            ringRenderer.material = lineMat;

        }
    }

    // Update is called once per frame
    void Update() 
    {
        for(int i = 0; i < points.Length; i++) {
            // Move the ring to the point
            this.ringGameObjects[i].transform.position = this.points[i].transform.position;

            this.ringGameObjects[i].transform.position = 0.5f * (this.points[i].transform.position + this.mainPoint.transform.position);
            var delta = this.points[i].transform.position - this.mainPoint.transform.position;
            this.ringGameObjects[i].transform.position += delta;

            // Match the scale to the distance
            float cubeDistance = Vector3.Distance(this.points[i].transform.position, this.mainPoint.transform.position);
            this.ringGameObjects[i].transform.localScale = new Vector3(this.ringGameObjects[i].transform.localScale.x, cubeDistance, this.ringGameObjects[i].transform.localScale.z);

            // Make the cube look at the main point.
            // Since the cube is pointing up(y) and the forward is z, we need to offset by 90 degrees.
            this.ringGameObjects[i].transform.LookAt(this.mainPoint.transform, Vector3.up);
            this.ringGameObjects[i].transform.rotation *= Quaternion.Euler(90, 0, 0);
        }
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.