■サンプル

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

public class BSpline
{
    public enum KnotType
    {
        Uniform,
        OpenUniform,
    }

    private List<Vector3> m_ctrlPt;
    private List<float> m_knot;
    private KnotType m_knotType;
    private int m_degree;

    /// <summary>
    /// B-Splineを生成する
    /// </summary>
    /// <param name="ctrlPt">制御点</param>
    /// <param name="degree">次数</param>
	/// <param name="knotType">Knotの種類(Uniform or OpenUniform</param>
    public BSpline(Vector3[] ctrlPt, int degree, KnotType knotType)
    {
        m_ctrlPt = new List<Vector3>();
        m_ctrlPt.AddRange(ctrlPt);

        switch (knotType)
        {
            case KnotType.Uniform:
                m_knot = createUniformKnotVector(ctrlPt.Count(), degree);
                break;

            case KnotType.OpenUniform:
                m_knot = createOpenUniformKnotVector(ctrlPt.Count(), degree);
                break;

            default:
                Debug.Assert(false);
                throw new ArgumentException();
        }

        m_knotType = knotType;
        m_degree = degree;
    }

    /// <summary>
    /// B-Splineを生成する
    /// </summary>
    /// <param name="resolution">生成するの数</param>
    /// <returns></returns>
    public List<Vector3> evaluate(int resolution)
    {
        List<Vector3> result = new List<Vector3>();

        if (m_degree == 1 || resolution < m_ctrlPt.Count || m_ctrlPt.Count < 2)
        {
            result.AddRange(m_ctrlPt);
        }
        else
        {
            float minKnot = m_knot[m_degree];
            float maxKnot = m_knot[m_knot.Count - m_degree - 1];

            float t = minKnot;
            float step = (maxKnot - minKnot) / (resolution - 1.0f);

            while (true)
            {
                result.Add(calc(t));
                if (t == maxKnot)
                    break;

                t += step;
                if (t > maxKnot)
                    t = maxKnot;
            }

            if (m_knotType == KnotType.OpenUniform)
            {
                result[result.Count - 1] = m_ctrlPt.Last();
            }
        }

        return result;
    }

    /// <summary>
    /// t点の位置を求める
    /// </summary>
    /// <param name="t"></param>
    /// <returns></returns>
    private Vector3 calc(float t)
    {
        Vector3 pt = new Vector3();

        int count = m_ctrlPt.Count;
        for (int i = 0; i < count; i++)
        {
            float w = deboor(i, m_degree, t);
            if (w > 0.0f)
                pt += m_ctrlPt[i] * w;
        }
        return pt;
    }

    // de boor cox
    private float deboor(int i, int degree, float t)
    {
        if (degree == 0)
        {
            return (m_knot[i] <= t && t < m_knot[i + 1]) ? 1 : 0;
        }

        float w1 = 0.0f, w2 = 0.0f;
        if (m_knot[i + degree] - m_knot[i] != 0)
            w1 = ((t - m_knot[i]) / (m_knot[i + degree] - m_knot[i]));

        if (m_knot[i + degree + 1] - m_knot[i + 1] != 0)
            w2 = ((m_knot[i + degree + 1] - t) / (m_knot[i + degree + 1] - m_knot[i + 1]));

        if (w1 != 0)
            w1 *= deboor(i, degree - 1, t);

        if (w2 != 0)
            w2 *= deboor(i + 1, degree - 1, t);

        return w1 + w2;
    }

    /// <summary>
    /// 一様ノットベクトルの作成
    /// </summary>
    /// <param name="controlPointCount"></param>
    /// <param name="degree"></param>
    /// <returns></returns>
    private List<float> createUniformKnotVector(int controlPointCount, int degree)
    {
        List<float> knot = new List<float>();
        int knotCount = controlPointCount + degree + 1;

        float t = 0;
        for (int i = 0; i < knotCount; i++)
        {
            knot.Add((1.0f / (knotCount - 1)) * i);
        }
        return knot;
    }

    /// <summary>
    /// 開一様ノットベクトルの作成
    /// </summary>
    /// <param name="controlPoint"></param>
    /// <param name="degree"></param>
    /// <returns></returns>
    private List<float> createOpenUniformKnotVector(int controlPointCount, int degree)
    {
        List<float> knot = new List<float>();
        int knotCount = controlPointCount + degree + 1;
        float step = knotCount - ((degree + 1) * 2);
        step = 1.0f / (step + 1.0f);

        for (int i = 0; i < knotCount; i++)
        {
            // 最初のn+1のノットは0
            if (i < degree + 1)
                knot.Add(0);
            // 最後のn+1のノットは1
            else if (i >= knotCount - (degree + 1))
                knot.Add(1);
            // それ以外は補完する
            else
                knot.Add(step * (i - degree));
        }

        return knot;
    }
}

■補足

 次数が固定なら予め漸化式を計算しておいた方が良い。