Unıty Bezier Curve Generator

Sosyal medyada paylaşın

Eğri çizdirmek hakkında tecrübem olmadığı için uzun süren çabalarım sonucu aşağıda paylaşacağım tool’u yazmaya karar verdim.

Bu tool ile eğri çizdirmek için benim gibi matematiksel hesaplamalar yapmanıza gerek kalmayacak, sadece eğrinin üzerinde olacağı noktaları, çizdirmek istediğiniz eğri tipini ve son olarak noktalar arası mesafeyi parametre olarak vermeniz yeterli olacaktır. Eğer işin temeline inmek isterseniz bu bağlantıdan Bezier Curve formüllerine bakıp kendinize göre implemente edebilirsiniz ki çok zor bir tarafı yok.

Vector3[] pCurveType curveTypefloat pathDistance
Eğrinin üzerinden geçeceği nokta dizisiEğri tipiEğri noktalarının arasındaki mesafe
Linear, Quadratic, CubicNe kadar az verirseniz o kadar fazla nokta ile eğri çizilir.

Öncelikle kodların mantığına değinmek istiyorum. Daha rahat kullanılabilsin diye bir enum oluşturdum ve DrawCurve isimli fonksiyona gerekli parametreler ile erişildikten sonra istenilen enum türüne göre aşağıdaki 3 farklı eğri fonksiyonunu çalıştırıyorum. Aslında enum kullanmadan da 3 ayrı fonksiyona istenilen yerden ayrı ayrı çağrı yapılıp aynı işlem yapılabilirdi ama bu şekilde hem daha rahat bir kullanım sunuyor ve herhangi bir ekleme çıkarma yapılması gerektiği zaman kodun yönetimi daha kolay oluyor. İlgili fonksiyon çalıştığında öncelikle verilen nokta dizisinin eleman sayısına bakıyoruz. Lineer Curve 2, Quadratic Curve 3, Cubic Curve ise 4 noktadan oluşmaktadır. Eğer şart sağlanmazsa exception fırlatıp fonksiyondan çıkıyoruz.

Son olarak bir sayının kuvvetini almak için neden Mathf.Pow() kullanmadın diye soracak olursanız, yaptığım birkaç deneme sonucunda kendi yazdığım kuvvet alma fonksiyonum olan Multipler Mathf.Pow’dan daha hızlı olduğu kanısına vardım ve bu yüzden kendi fonksiyonumu yazıp kullandım. İki fonksiyon arasında ahım şahım bir fark yok, benim testlerim 0.03-0.05 saniye arasında bir farklılık gösteriyordu.

Tool’un kullanımına göz atalım. Benim gibi boş bir listeyi eğri aracından doldurabilir ve o pozisyonlarda obje spawnlatabilirsiniz veya obje spawnlatmaya gerek kalmadan direkt karakterinize o pozisyonları takip et diyebilirsiniz size kalmış.

Eğri Cizdirme Çağrısı:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Fade.BezierCurves;

public class GenerateCurve : MonoBehaviour
{
    public Vector3[] points = new Vector3[] { };
    public List<Vector3> dpoints = new List<Vector3>();
    public GameObject obj;
    private void Start()
    {
        dpoints = Fade.BezierCurves.BezierCurve.DrawCurve(points, BezierCurve.CurveType.Quadratic, .04f);

        for (int i = 0; i < dpoints.Count; i++)
        {
            Instantiate(obj, dpoints[i], Quaternion.identity,transform);
        }
    }
}

Eğri Kodları:

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

namespace Fade.BezierCurves
{
    public static class BezierCurve
    {
        public enum CurveType { Linear, Quadratic, Cubic }
        public static CurveType curveType;
        private static List<Vector3> pList = new List<Vector3>();

        /// <summary>
        ///Creates curves between points you want.
        /// </summary>
        /// <param name="p">The points on the curve</param>
        /// <param name="curveType">Type of curve</param>
        /// <param name="pathDistance">Number of points on curve</param>
        /// <returns>Returns the coordinates of the curve according to your option.</returns>
        public static List<Vector3> DrawCurve(Vector3[] p, CurveType curveType, float pathDistance)
        {
            return curveType switch
            {
                CurveType.Linear => LinearBezierCurve(p, pathDistance),
                CurveType.Quadratic => QuadraticBezierCurve(p, pathDistance),
                CurveType.Cubic => CubicBezierCurve(p, pathDistance),
                _ => null
            };

        }
        #region Curve Generate Functions

        private static List<Vector3> LinearBezierCurve(Vector3[] p, float pathDistance)
        {
            if (p.Length != 2) throw new ArgumentOutOfRangeException();

            pList.Clear();
            for (float t = 0; t < 1; t += pathDistance)
            {
                pList.Add((1 - t) * p[0] + t * p[1]);

            }
            return pList;
        }
        private static List<Vector3> QuadraticBezierCurve(Vector3[] p, float pathDistance)
        {
            if (p.Length != 3) throw new ArgumentOutOfRangeException();

            pList.Clear();
            for (float t = 0; t < 1; t += pathDistance)
            {
                pList.Add(Multipler(1 - t, 2) * p[0] +
                    2 * Multipler(1 - t, 1) * t * p[1] +
                       Multipler(t, 2) * p[2]);
            }
            return pList;
        }

        private static List<Vector3> CubicBezierCurve(Vector3[] p, float pathDistance)
        {
            if (p.Length != 4) throw new ArgumentOutOfRangeException();

            pList.Clear();
            for (float t = 0; t < 1; t += pathDistance)
            {
                pList.Add(Multipler(1 - t, 3) * p[0] +
                    3 * Multipler(1 - t, 2) * t * p[1] +
                      3 * (1 - t) * Multipler(t, 2) * p[2] +
                      Multipler(t, 3) * p[3]);
            }
            return pList;
        }
        #endregion

        #region Power Of Number Function
        private static float Multipler(float a, float b)
        {
            float tmp = a;
            while (b > 1)
            {
                tmp *= a;
                b--;
            }
            return tmp;
        }
        #endregion
    }
}

Github reposu için buraya tıklayın.