Dynamische 3D-Straßensperrengenerierung

einführen

Im vorherigen Artikel wurde das zugrunde liegende Implementierungsprinzip von Mathf.Lerp vorgestellt. Hier stellen wir vor, wie die dynamische Roadblock-Generierung in Parkour-Spielen implementiert wird.
Dynamische Straßensperren sind tatsächlich einfacher zu generieren, aber was ist die Schwierigkeit? Wenn sie alle flach sind oder keine Kurven haben, ist es einfacher zu implementieren. Wenn die Implementierung dynamischer Straßensperren auf Steigungen, Gefälle oder Wendestellen trifft, wie gehen wir damit um? ?Wie sieht es mit der Drehung und Lage von Eckpunkten und Steigungen und Gefällen aus?

Designumsetzung

Lassen Sie uns kurz über die Designidee sprechen.
Der Endpunkt der Straße ist der Ursprung der Koordinaten (0,0,0), und unsere Straße zeigt in Richtung der Z-Achse. Das heißt, wenn wir Straßensperren generieren, werden wir Sie müssen nur die Tiefe der Z-Achse verwenden.
Wir erstellen mehrere leere Objekte zwischen dem Endpunkt und dem Startpunkt. Dieses leere Objekt wird verwendet, um zu bestimmen, zwischen welchen beiden leeren Objekten sich die erstellte Straßensperre befindet. Dann verwenden wir Lerp, um Interpolationsoperationen durchzuführen, damit wir die Straßensperren an Ecken und Hängen generieren können . Korrekte Drehung und Position der Barrikaden.
Beim Generieren einer Straßensperre wird die Straßensperre zufällig innerhalb des benutzerdefinierten Parameterentfernungsbereichs generiert und ihr Drehwinkel und ihre Höhe können anhand der Differenz zwischen den beiden oben genannten leeren Objekten berechnet werden.

1. Pflastererstellung

Das Folgende ist eine Straßenoberfläche, die ich einfach mit Plane gespleißt habe. Die Endposition der Straße ist Unity (0, 0, 0).
Hier beträgt meine Gesamtlänge 300, was bedeutet, dass die Startposition im Bild ( x, x, -300).
Fügen Sie hier eine Bildbeschreibung ein

2. Erstellung leerer Objekte

Erstellen Sie ein leeres Objekt mit Wegpunkten auf der Straße und platzieren Sie alle leeren Objekte, die wir später erstellen, darin.
Wir können unzählige leere Objekte auf der gesamten Straße erstellen, aber die Z-Achsen-Rotation und die Y-Achsen-Höhe des leeren Objekts müssen gleich sein gefolgt. Die Straßenoberfläche bleibt konsistent, da wir später die Position und Drehung dieses leeren Objekts verwenden werden, um Interpolationsoperationen durchzuführen, um die Position und den Drehwinkel der Straßensperre zu erhalten. Je mehr leere Objekte hier erstellt werden, desto genauer ist die Neigung und Die Straßensperre wird so gedreht, dass sie sich der Straßenoberfläche anpasst. Erstellen Sie abschließend ein Wegpunkt-Skript und hängen Sie es an Wegpunkten an, um alle von uns erstellten leeren Objekte zu erhalten. Wir können OnDrawGizmos() verwenden, um sie für unsere Bequemlichkeit zu zeichnen.

Die erstellte Position ist wie folgt.
Fügen Sie hier eine Bildbeschreibung ein
Hier können Sie sehen, dass ich den Z-Achsen-Rotationswinkel jedes Punkts an die Straßenoberfläche angepasst habe.

Das Skript lautet wie folgt:

[ExecuteInEditMode]
	public class waypoints : MonoBehaviour {
    
    

    	public Transform[] points;
    	void OnDrawGizmos()
    	{
    
    
        	for (int i = 0; i < points.Length; i++)
        	{
    
    
            	Gizmos.color = Color.red;
            	Gizmos.DrawWireSphere(points[i].transform.position, 5);
        	}
    	}
	}

3.Create.cs-Skripterstellung

using System.Collections;
	using System.Collections.Generic;
	using UnityEngine;

	public class Create : MonoBehaviour {
    
    

    /// <summary>
    /// 路障物体数组
    /// </summary>
    public GameObject[] obstacles;

    /// <summary>
    /// 路障在道路上出现的开始位置
    /// </summary>
    public float startLength = 10;

    /// <summary>
    /// 路障距上一个路障的最小距离  
    /// </summary>
    public float minLength = 10;

    /// <summary>
    /// 路障距上一个路障的最大距离  
    /// </summary>
    public float maxLength = 20;

    /// <summary>
    /// 与路面相贴合的路线上的脚本组件  
    /// </summary>
    private waypoints wayPoints;

    void Awake()
    {
    
    
        wayPoints = GameObject.Find("waypoints").GetComponent<waypoints>(); 
    }

    // Use this for initialization  
    void Start()
    {
    
    
        //创建路障
        GenerateObstacle(); 
    }

    /// <summary>
    /// 创建路障
    /// </summary>
    void GenerateObstacle()
    {
    
    
        //当前道路在场景中的起始Z坐标  
        float startZ = transform.position.z - 300;

        //当前道路在场景中的结束Z坐标  
        float endZ = transform.position.z;
        
        //将要产生路障的Z坐标
        float z = startZ + startLength;
        
        while (true)
        {
    
    
            //每隔多少米的距离产生一个路障  
            z += Random.Range(minLength, maxLength);

            //如果将要产生路障的位置超出了这条道路则退出路障产生循环,否则产生路障 
            if (z > endZ)                            
            {
    
    
                break;
            }
            else
            {
    
    
                //方法计算路障位置坐标
                Vector3 position = GetWayPos(z);
                //方法计算路障旋转坐标
                Vector3 rotation = GetWayRotate(z);
                //产生一个从路障数组里取路障的随机序数  
                int obsIndex = Random.Range(0, obstacles.Length);
                //实例化路障 
                Instantiate(obstacles[obsIndex], position, Quaternion.Euler(rotation.x, rotation.y, rotation.z)); 
            }
        }
    }

    /// <summary>
    /// 获取转折点的集合索引值
    /// </summary>
    /// <param name="z"></param>
    /// <returns></returns>
    int GetPointIndex(float z)
    {
    
    
        //在道路上设置的转折点的集合  
        Transform[] points = wayPoints.points;
        //转折点在集合中的序数号  
        int index = 0;

        for (int i = 0; i < points.Length - 1; i++)
        {
    
    
            //根据要插入路障的Z值在集合中寻找在哪两个点之间,找到后记下序数号  
            if (z >= points[i].position.z && z <= points[i + 1].position.z)
            {
    
    
                index = i;
                break;
            }
        }
        return index;
    }

    Vector3 GetWayPos(float z)
    {
    
    
        int index = GetPointIndex(z);
        //使用Lerp函数计算出插入路障处的空间坐标值  
        return Vector3.Lerp(wayPoints.points[index + 1].position, wayPoints.points[index].position, (z - wayPoints.points[index + 1].position.z) / (wayPoints.points[index].position.z - wayPoints.points[index + 1].position.z));
    }

    Vector3 GetWayRotate(float z)
    {
    
    
        int index = GetPointIndex(z);
        return Vector3.Lerp(wayPoints.points[index + 1].eulerAngles, wayPoints.points[index].eulerAngles, (z - wayPoints.points[index + 1].position.z) / (wayPoints.points[index].position.z - wayPoints.points[index + 1].position.z));
    }
    }

Das Ergebnis des Erstellungsabschlusses lautet wie folgt:
Fügen Sie hier eine Bildbeschreibung ein

Zusammenfassen

In diesem Artikel wird hauptsächlich die Verwendung von Mathf.Lerp() erläutert. Wenn Sie nichts verstehen, können Sie meinen vorherigen Artikel lesen.

Supongo que te gusta

Origin blog.csdn.net/qq_42194657/article/details/135438295
Recomendado
Clasificación