├── .gitignore ├── Assets ├── Bezier.asset ├── Bezier.asset.meta ├── Packages.meta └── Packages │ ├── BezierTools.meta │ └── BezierTools │ ├── ArrayUtil.cs │ ├── ArrayUtil.cs.meta │ ├── Bezier.cs │ ├── Bezier.cs.meta │ ├── BezierBase.cs │ ├── BezierBase.cs.meta │ ├── Editor.meta │ ├── Editor │ ├── BezierEditor.cs │ ├── BezierEditor.cs.meta │ ├── ScriptableObjUtil.cs │ └── ScriptableObjUtil.cs.meta │ ├── Samples.meta │ └── Samples │ ├── BezierLoopSample.asset │ ├── BezierLoopSample.asset.meta │ ├── BezierSample.asset │ └── BezierSample.asset.meta ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset └── UnityConnectSettings.asset ├── README.md ├── ReadMeData ├── ss001.png ├── ss002.png ├── ss003.png └── ss004.png └── UnityBezierTools.unitypackage /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | 8 | # Autogenerated VS/MD solution and project files 9 | ExportedObj/ 10 | *.csproj 11 | *.unityproj 12 | *.sln 13 | *.suo 14 | *.tmp 15 | *.user 16 | *.userprefs 17 | *.pidb 18 | *.booproj 19 | *.svd 20 | 21 | 22 | # Unity3D generated meta files 23 | *.pidb.meta 24 | 25 | # Unity3D Generated File On Crash Reports 26 | sysinfo.txt 27 | 28 | # Builds 29 | *.apk 30 | #*.unitypackage 31 | -------------------------------------------------------------------------------- /Assets/Bezier.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/Assets/Bezier.asset -------------------------------------------------------------------------------- /Assets/Bezier.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3fae58d08e78c1b44a9e02d7d6cf2e44 3 | timeCreated: 1491210929 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Packages.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 531995943f73aae41b7e9ff6cf4d4ff5 3 | folderAsset: yes 4 | timeCreated: 1491210213 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/BezierTools.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8360fad2d4c0a304db0220f02dc2797d 3 | folderAsset: yes 4 | timeCreated: 1484116583 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/ArrayUtil.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | namespace BezierTools { 5 | 6 | public static class ArrayUtil { 7 | public static void Insert(ref T[] list, T newone, int at) { 8 | var expanded = new T[list.Length + 1]; 9 | System.Array.Copy(list, expanded, at); 10 | System.Array.Copy(list, at, expanded, at + 1, list.Length - at); 11 | expanded[at] = newone; 12 | list = expanded; 13 | } 14 | 15 | public static void Insert(ref T[] list, T[] newList, int at) 16 | { 17 | var expanded = new T[list.Length + newList.Length]; 18 | System.Array.Copy(list, expanded, at); 19 | System.Array.Copy(list, at, expanded, at + newList.Length, list.Length - at); 20 | for (int i = 0; i < newList.Length; i++) 21 | { 22 | expanded[at + i] = newList[i]; 23 | } 24 | list = expanded; 25 | } 26 | 27 | public static T Remove(ref T[] list, int at) { 28 | var oldone = list[at]; 29 | System.Array.Copy(list, at + 1, list, at, list.Length - (at + 1)); 30 | System.Array.Resize(ref list, list.Length - 1); 31 | return oldone; 32 | } 33 | 34 | public static void Remove(ref T[] list, int start, int end) 35 | { 36 | //Debug.Log("Before: Length " + list.Length + " start " + start + " end " + end); 37 | if(list.Length > (end + 1)) 38 | { 39 | System.Array.Copy(list, end + 1, list, start, list.Length - (end + 1)); 40 | } 41 | System.Array.Resize(ref list, list.Length - (end - start + 1)); 42 | //Debug.Log("After: Length " + list.Length + " start " + start + " end " + end); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/ArrayUtil.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6e0167a9d3e61d9409ff0bb6bd3dee43 3 | timeCreated: 1430389007 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Bezier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | 6 | namespace BezierTools 7 | { 8 | public class Bezier : ScriptableObject 9 | { 10 | [SerializeField] 11 | public BezierData data; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Bezier.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d2461683d20cc254fbcff442da3bbd19 3 | timeCreated: 1484116593 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/BezierBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | #if UNITY_EDITOR 4 | using UnityEditor; 5 | #endif 6 | 7 | namespace BezierTools 8 | { 9 | [System.Serializable] 10 | public class BezierData 11 | { 12 | #region define 13 | private const int stepsPerCurve = 20; 14 | #endregion 15 | 16 | #region public 17 | public ControlPoint[] cps; 18 | [SerializeField] 19 | public BezierControlPointMode[] modes; 20 | 21 | /// 22 | /// ベジェ曲線の長さ 23 | /// 24 | public float bezierLength = 1; 25 | public Vector3 bezierBoundingSize = Vector3.zero; 26 | public Vector3 bezierBoundingCenter = Vector3.zero; 27 | 28 | public float[] bezierCurvesLength; // ベジェ曲線単位の長さ 29 | public float[] normalizeBezierPoints; // 長さを正規化したベジェ曲線の位置 30 | public float[,] preCalcLinearLength; // 距離均等に移動するための距離の微分の事前計算配列 31 | #endregion 32 | 33 | [SerializeField] 34 | private bool loop = false; 35 | 36 | #region public property 37 | public bool Loop 38 | { 39 | get 40 | { 41 | return loop; 42 | } 43 | set 44 | { 45 | loop = value; 46 | if (value) 47 | { 48 | Debug.Log("LOOP!"); 49 | modes[modes.Length - 1] = modes[0]; 50 | SetControlPoint(0, cps[0].position); 51 | } 52 | } 53 | } 54 | 55 | /// 56 | /// ベジェ曲線の座標の数 57 | /// 58 | public int Length 59 | { 60 | get 61 | { 62 | return (cps.Length - 1) / 3; 63 | } 64 | } 65 | #endregion 66 | 67 | #region public method 68 | public int GetIndex(int i) 69 | { 70 | while (i < 0) 71 | i += cps.Length; 72 | return Mathf.Min(i, cps.Length - 1); 73 | } 74 | 75 | public Vector3 GetCP(int i) 76 | { 77 | return cps[GetIndex(i)].position; 78 | } 79 | 80 | /// 81 | /// インデックスから正規化されたパス全体の長さの中での位置(T)を返す 82 | /// 83 | /// 84 | /// 85 | public float GetT(int index) 86 | { 87 | index = Mathf.Min(index, cps.Length - 1); 88 | 89 | return (float)index / (cps.Length - 1); 90 | } 91 | 92 | /// 93 | /// コントロールポイントのインデックスとその中の時間(T)を取得(コントロールポイント数で等間隔) 94 | /// 95 | /// 96 | /// 97 | /// 98 | public void CalcIndex(float inT, out int outIdx, out float outT) 99 | { 100 | if (inT >= 1f) 101 | { 102 | outT = 1f; 103 | outIdx = cps.Length - 4; 104 | } 105 | else 106 | { 107 | outT = Mathf.Clamp01(inT) * Length; 108 | outIdx = (int)outT; 109 | outT -= outIdx; 110 | outIdx *= 3; 111 | } 112 | } 113 | 114 | /// 115 | /// コントロールポイントのインデックスとその中の時間(T)を取得(ベジェ曲線の長さの割合、移動速度が変わらない) 116 | /// 117 | /// 118 | /// 119 | /// 120 | public void CalcIndexNormalize(float inT, out int outIdx, out float outT) 121 | { 122 | if (inT >= 1f) 123 | { 124 | outT = 1f; 125 | outIdx = cps.Length - 4; 126 | } 127 | else 128 | { 129 | outT = inT; 130 | int i; 131 | float oldPoint = 0; 132 | float preOutT = 0; 133 | 134 | //int i; 135 | //CalcIndex(inT, out i, out preOutT); 136 | 137 | for (i = 0; i < normalizeBezierPoints.Length; i++) 138 | { 139 | if (normalizeBezierPoints[i] >= inT) 140 | { 141 | preOutT = (inT - oldPoint) / (normalizeBezierPoints[i] - oldPoint); 142 | //preOutT = inT / normalizeBezierPoints[i]; 143 | //Debug.Log("[" + i + "]" + normalizeBezierPoints[i] + " : outT " + outT + " inT " + inT); 144 | //Debug.Log("KKKK[" + i + "]" + normalizeBezierPoints[i] + " oldPoint " + oldPoint + " inT " + inT + " preOutT " + preOutT); 145 | break; 146 | } 147 | //Debug.Log("LLLL[" + i + "]" + normalizeBezierPoints[i] + " oldPoint " + oldPoint + " inT " + inT); 148 | oldPoint = normalizeBezierPoints[i]; 149 | } 150 | 151 | //outT = Mathf.Clamp01(inT) * Length; 152 | outIdx = i * 3; 153 | //outT -= outIdx; 154 | //outIdx *= 3; 155 | //outT = CalcLinearLength(i, preOutT); 156 | //outT = CalcLinearLength(outIdx, preOutT); // 逐次計算 157 | //outT = preOutT; 158 | outT = GetPreCalcLinearLength(i, preOutT); // 事前計算(未完成) 159 | //Debug.Log("RRRR[" + i + "]" + normalizeBezierPoints[i] + " preOutT " + preOutT + " oldPoint " + oldPoint + " outT " + outT + " inT " + inT + " outIdx " + outIdx + " i " + i); 160 | } 161 | } 162 | 163 | static float[] linearLength = { 0, 0, 0, 0, 164 | 0, 0, 0, 0, 165 | 0, 0, 0, 0, 166 | 0, 0, 0, 0, 167 | 0, 0, 0, 0 }; 168 | 169 | float CalcLinearLength(int index, float t, int divN = 16) 170 | { 171 | float ni = 1f / divN; 172 | float tt = 0; 173 | 174 | //float[,] ll = new float[Length, divN + 1]; 175 | //ll = new float[Length, divN + 1]; 176 | 177 | Vector3 p1 = BezierCurve(0, GetCP(index), GetCP(index + 1), GetCP(index + 2), GetCP(index + 3)); 178 | 179 | linearLength[0] = 0; 180 | 181 | // パスを分割して距離を保存する 182 | for (int i = 1; i <= divN; i++) 183 | { 184 | tt += ni; 185 | Vector3 p2 = BezierCurve(tt, GetCP(index), GetCP(index + 1), GetCP(index + 2), GetCP(index + 3)); 186 | linearLength[i] = linearLength[i - 1] + Vector3.Distance(p1, p2); 187 | //Debug.Log("[" + i + "] index " + index + " linearLength " + linearLength[i]); 188 | p1 = p2; 189 | } 190 | 191 | // linearLengthを0~1の範囲に正規化する 192 | float xx = 1f / linearLength[divN]; 193 | for (int i = 1; i <= divN; i++) 194 | { 195 | linearLength[i] *= xx; 196 | } 197 | 198 | // tを距離として該当するlinearLength区画を探す 199 | int ii; 200 | for (ii = 0; ii < divN; ii++) 201 | { 202 | if ((t >= linearLength[ii]) && (t <= linearLength[ii + 1])) 203 | break; 204 | } 205 | 206 | if (ii >= divN) 207 | return t; 208 | 209 | // 線形補間 210 | xx = (linearLength[ii + 1] - linearLength[ii]); 211 | if (xx <= float.Epsilon) xx = float.Epsilon; 212 | xx = (t - linearLength[ii]) / xx; 213 | 214 | return (ii * (1f - xx) + (ii + 1) * xx) * ni; 215 | } 216 | 217 | float GetPreCalcLinearLength(int index, float t, int divN=16) 218 | { 219 | if(preCalcLinearLength == null) 220 | { 221 | PreCalcLinearLength(ref preCalcLinearLength); 222 | } 223 | float ni = 1f / divN; 224 | 225 | int ii; 226 | for(ii = 0; ii < divN; ii++) 227 | { 228 | //Debug.Log("index " + index + " ii " + ii); 229 | if ((t >= preCalcLinearLength[index, ii]) && (t <= preCalcLinearLength[index, ii + 1])) 230 | break; 231 | } 232 | 233 | //Debug.Log("index " + index + " ii " + ii); 234 | 235 | if (ii >= divN) 236 | return t; 237 | 238 | float xx = (preCalcLinearLength[index, ii + 1] - preCalcLinearLength[index, ii]); 239 | if (xx <= float.Epsilon) xx = float.Epsilon; 240 | xx = (t - preCalcLinearLength[index, ii]) / xx; 241 | 242 | return (ii * (1f - xx) + (ii + 1) * xx) * ni; 243 | } 244 | 245 | //float[,] PreCalcLinearLength(int divN = 16) 246 | void PreCalcLinearLength(ref float[,] ll, int divN = 16) 247 | { 248 | //Debug.Log("PreCalcLinearLength"); 249 | 250 | float ni = 1f / divN; 251 | 252 | //float[,] ll = new float[Length, divN+1]; 253 | ll = new float[Length, divN + 1]; 254 | 255 | for (int i = 0; i < Length; i++) 256 | { 257 | float tt = 0; 258 | 259 | int idx = i * 3; 260 | Vector3 p1 = BezierCurve(0, GetCP(idx), GetCP(idx + 1), GetCP(idx + 2), GetCP(idx + 3)); 261 | 262 | ll[i, 0] = 0; 263 | 264 | for (int j = 1; j <= divN; j++) 265 | { 266 | tt += ni; 267 | Vector3 p2 = BezierCurve(tt, GetCP(idx), GetCP(idx + 1), GetCP(idx + 2), GetCP(idx + 3)); 268 | ll[i, j] = ll[i, j - 1] + Vector3.Distance(p1, p2); 269 | p1 = p2; 270 | //Debug.Log("[" + i + "," + j + "] index " + idx + " linearLength " + ll[i, j]); 271 | } 272 | 273 | float xx = 1f / ll[i, divN]; 274 | for (int j = 1; j <= divN; j++) 275 | { 276 | ll[i, j] *= xx; 277 | } 278 | } 279 | } 280 | 281 | public Vector3 Position(float t) 282 | { 283 | int i; 284 | CalcIndex(t, out i, out t); 285 | return BezierCurve(t, GetCP(i), GetCP(i + 1), GetCP(i + 2), GetCP(i + 3)); 286 | } 287 | 288 | /// 289 | /// 移動速度が変わらない座標 290 | /// 291 | /// 292 | /// 293 | public Vector3 PositionNormalizeT(float t) 294 | { 295 | int i; 296 | CalcIndexNormalize(t, out i, out t); 297 | return BezierCurve(t, GetCP(i), GetCP(i + 1), GetCP(i + 2), GetCP(i + 3)); 298 | } 299 | 300 | public Vector3 Velocity(float t) 301 | { 302 | int i; 303 | CalcIndex(t, out i, out t); 304 | return GetFirstDerivative(t, GetCP(i), GetCP(i + 1), GetCP(i + 2), GetCP(i + 3)); 305 | } 306 | 307 | /// 308 | /// 移動速度が変わらないベロシティ 309 | /// 310 | /// 311 | /// 312 | public Vector3 VelocityNormalizeT(float t) 313 | { 314 | int i; 315 | CalcIndexNormalize(t, out i, out t); 316 | return GetFirstDerivative(t, GetCP(i), GetCP(i + 1), GetCP(i + 2), GetCP(i + 3)); 317 | } 318 | 319 | public Vector3 Direction(float t) 320 | { 321 | return Velocity(t).normalized; 322 | } 323 | 324 | public void AddCurve() 325 | { 326 | Vector3 point = cps[cps.Length - 1].position; 327 | Array.Resize(ref cps, cps.Length + 3); 328 | point.x += 1f; 329 | cps[cps.Length - 3] = new ControlPoint(); 330 | cps[cps.Length - 3].position = point; 331 | point.x += 1f; 332 | cps[cps.Length - 2] = new ControlPoint(); 333 | cps[cps.Length - 2].position = point; 334 | point.x += 1f; 335 | cps[cps.Length - 1] = new ControlPoint(); 336 | cps[cps.Length - 1].position = point; 337 | 338 | Array.Resize(ref modes, modes.Length + 1); 339 | modes[modes.Length - 1] = modes[modes.Length - 2]; 340 | EnforceMode(cps.Length - 4); 341 | 342 | if (loop) 343 | { 344 | cps[cps.Length - 1].position = cps[0].position; 345 | modes[modes.Length - 1] = modes[0]; 346 | EnforceMode(0); 347 | } 348 | } 349 | 350 | public void Reset(float x=0, float y=0, float z=0) 351 | { 352 | cps = new ControlPoint[4]; 353 | Vector3 point = new Vector3(x, y, z); 354 | for (int i = 0; i < 4; i++) 355 | { 356 | cps[i] = new ControlPoint(); 357 | cps[i].position = point; 358 | point.x += 1f; 359 | } 360 | 361 | modes = new BezierControlPointMode[] 362 | { 363 | BezierControlPointMode.Free, 364 | BezierControlPointMode.Free 365 | }; 366 | 367 | CalcBezierLength(); 368 | } 369 | 370 | public BezierControlPointMode GetControlPointMode(int index) 371 | { 372 | return modes[(index + 1) / 3]; 373 | } 374 | 375 | public void SetControlPoint(int index, Vector3 point) 376 | { 377 | if (index % 3 == 0) 378 | { 379 | Vector3 delta = point - cps[index].position; 380 | if (loop) 381 | { 382 | if (index == 0) 383 | { 384 | cps[1].position += delta; 385 | cps[cps.Length - 2].position += delta; 386 | cps[cps.Length - 1].position = point; 387 | } 388 | else if (index == cps.Length - 1) 389 | { 390 | cps[0].position = point; 391 | cps[1].position += delta; 392 | cps[index - 1].position += delta; 393 | } 394 | else 395 | { 396 | cps[index - 1].position += delta; 397 | cps[index + 1].position += delta; 398 | } 399 | } 400 | else 401 | { 402 | if (index > 0) 403 | { 404 | cps[index - 1].position += delta; 405 | } 406 | if (index + 1 < cps.Length) 407 | { 408 | cps[index + 1].position += delta; 409 | } 410 | } 411 | } 412 | cps[index].position = point; 413 | EnforceMode(index); 414 | } 415 | 416 | public void SetControlPointMode(int index, BezierControlPointMode mode) 417 | { 418 | int modeIndex = (index + 1) / 3; 419 | modes[modeIndex] = mode; 420 | if (loop) 421 | { 422 | if (modeIndex == 0) 423 | { 424 | modes[modes.Length - 1] = mode; 425 | } 426 | else if (modeIndex == modes.Length - 1) 427 | { 428 | modes[0] = mode; 429 | } 430 | } 431 | EnforceMode(index); 432 | 433 | } 434 | 435 | public static Vector3 GetFirstDerivative(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) 436 | { 437 | t = Mathf.Clamp01(t); 438 | float onMinusT = 1f - t; 439 | 440 | return 3f * onMinusT * onMinusT * (p1 - p0) + 6f * onMinusT * t * (p2 - p1) + 3f * t * t * (p3 - p2); 441 | } 442 | 443 | public BezierData Copy() 444 | { 445 | BezierData b = new BezierData(); 446 | b.cps = new ControlPoint[cps.Length]; 447 | for (int i = 0; i < this.cps.Length; i++) 448 | { 449 | b.cps[i] = new ControlPoint(); 450 | b.cps[i].position.x = cps[i].position.x; 451 | b.cps[i].position.y = cps[i].position.y; 452 | b.cps[i].position.z = cps[i].position.z; 453 | } 454 | b.modes = new BezierControlPointMode[this.modes.Length]; 455 | for (int i = 0; i < this.modes.Length; i++) 456 | { 457 | b.modes[i] = this.modes[i]; 458 | } 459 | b.loop = loop; 460 | return b; 461 | } 462 | 463 | public void SetOffset(Vector3 offset) 464 | { 465 | for(int i = 0; i < cps.Length; i++) 466 | { 467 | cps[i].position += offset; 468 | } 469 | } 470 | 471 | public void SetOffsetScale(Vector3 offset) 472 | { 473 | for (int i = 0; i < cps.Length; i++) 474 | { 475 | cps[i].position.x *= offset.x; 476 | cps[i].position.y *= offset.y; 477 | cps[i].position.z *= offset.z; 478 | } 479 | } 480 | 481 | public Vector3 GetSize() 482 | { 483 | Vector3 min = Vector3.one * 1000000f; 484 | Vector3 max = Vector3.one * -1000000f; 485 | for(int i = 0; i < Length; i += 3) 486 | { 487 | if (min.x > cps[i].position.x) min.x = cps[i].position.x; 488 | if (min.y > cps[i].position.y) min.y = cps[i].position.y; 489 | if (min.z > cps[i].position.z) min.z = cps[i].position.z; 490 | 491 | if (max.x < cps[i].position.x) max.x = cps[i].position.x; 492 | if (max.y < cps[i].position.y) max.y = cps[i].position.y; 493 | if (max.z < cps[i].position.z) max.z = cps[i].position.z; 494 | } 495 | 496 | return new Vector3(Mathf.Abs(max.x - min.x), Mathf.Abs(max.y - min.y), Mathf.Abs(max.z - min.z)); 497 | } 498 | 499 | /// 500 | /// ベジェデータを末尾に付け足す 501 | /// 502 | public void AddBezierData(BezierData data) 503 | { 504 | //Vector3 point = cps[cps.Length - 1].position; 505 | int oldLast = cps.Length - 1; 506 | int oldModeIndex = modes.Length - 1; 507 | int mergeOffset = 2; 508 | int dataLength = data.cps.Length; 509 | 510 | // 末端の制御点を保持 511 | Vector3 oldLastControlPos = cps[oldLast - 1].position; 512 | 513 | Array.Resize(ref cps, cps.Length + dataLength + mergeOffset); // 結合用パスの制御点2つ追加 514 | Array.Resize(ref modes, modes.Length + mergeOffset + data.modes.Length); 515 | 516 | // データコピー 517 | for (int i = 0; i < dataLength; i++) 518 | { 519 | int idx = oldLast + mergeOffset + i + 1; 520 | //Debug.Log("[" + i + "] cps[" + (idx) + "] data.cps["+i+"].position " + data.cps[i].position); 521 | cps[idx] = new ControlPoint(); 522 | cps[idx].position = data.cps[i].position; 523 | } 524 | for(int i = 0; i < data.modes.Length; i++) 525 | { 526 | modes[oldModeIndex + mergeOffset + i] = data.modes[i]; 527 | } 528 | 529 | cps[oldLast + 1] = new ControlPoint(); 530 | cps[oldLast + 2] = new ControlPoint(); 531 | 532 | SetControlPointMode(oldLast + 1, BezierControlPointMode.Aligned); 533 | SetControlPointMode(oldLast + 2, BezierControlPointMode.Aligned); 534 | 535 | // 間の制御点の座標を前後の制御点からの流れに沿わせる 536 | Vector3 p1 = cps[oldLast].position + (cps[oldLast].position - cps[oldLast - 1].position).normalized * 0.01f; 537 | SetControlPoint(oldLast + 1, p1); 538 | 539 | Vector3 p2 = cps[oldLast + 3].position + (cps[oldLast + 3].position - cps[oldLast + 4].position).normalized * 0.01f; 540 | SetControlPoint(oldLast + 2, p2); 541 | 542 | // 結合前の末端の制御点を復元 543 | SetControlPoint(oldLast - 1, oldLastControlPos); 544 | 545 | } 546 | 547 | /// 548 | /// 選択インデックスの後ろに挿入 549 | /// 550 | /// 551 | public void InsertNextPoint(int index) 552 | { 553 | if(index == (cps.Length - 1)) 554 | { 555 | // 末端に追加 556 | AddCurve(); 557 | } 558 | else 559 | { 560 | // 次に追加 561 | // 中間座標取得 562 | float d = 1f / (float)(cps.Length - 1); 563 | float t1 = (float)index * d; 564 | float t2 = (float)(index + 3) * d; 565 | float tt = t1 + (t2 - t1) * 0.5f; 566 | Vector3 middlePoint = Position(tt); 567 | Vector3 middleVelocity = Velocity(tt) * 0.01f; 568 | ControlPoint[] newCps = new ControlPoint[3]; 569 | 570 | newCps[0] = new ControlPoint(); 571 | newCps[0].position = middlePoint - middleVelocity; 572 | newCps[1] = new ControlPoint(); 573 | newCps[1].position = middlePoint; 574 | newCps[2] = new ControlPoint(); 575 | newCps[2].position = middlePoint + middleVelocity; 576 | BezierTools.ArrayUtil.Insert(ref cps, newCps, index + 2); 577 | 578 | int modeIndex = (index + 1) / 3; 579 | BezierTools.ArrayUtil.Insert(ref modes, BezierControlPointMode.Free, modeIndex + 1); 580 | } 581 | 582 | if (loop) 583 | { 584 | cps[cps.Length - 1].position = cps[0].position; 585 | modes[modes.Length - 1] = modes[0]; 586 | EnforceMode(0); 587 | } 588 | } 589 | 590 | /// 591 | /// 選択インデックスを削除 592 | /// 593 | /// 594 | public void RemovePoint(int index) 595 | { 596 | if (index == 0) 597 | { 598 | BezierTools.ArrayUtil.Remove(ref cps, 0, 2); 599 | } 600 | else if (index == (Length - 1)) 601 | { 602 | BezierTools.ArrayUtil.Remove(ref cps, index - 2, index); 603 | } 604 | else 605 | { 606 | BezierTools.ArrayUtil.Remove(ref cps, index - 1, index + 1); 607 | } 608 | 609 | int modeIndex = (index + 1) / 3; 610 | BezierTools.ArrayUtil.Remove(ref modes, modeIndex); 611 | 612 | if (Loop) 613 | { 614 | Loop = true; 615 | } 616 | } 617 | 618 | /// 619 | /// 長さを計算 620 | /// 621 | public float CalcBezierLength() 622 | { 623 | float len = 0; 624 | float lenSum = 0; 625 | Vector3 old = Position(0); 626 | Vector3 point; 627 | 628 | bezierCurvesLength = new float[Length]; 629 | normalizeBezierPoints = new float[Length]; 630 | //preCalcLinearLength = new float[Length, stepsPerCurve]; 631 | for (int i = 0; i < bezierCurvesLength.Length; i++) 632 | { 633 | float startT = GetT(i * 3); 634 | float endT = GetT((i + 1) * 3); 635 | float diffT = (endT - startT) / stepsPerCurve; 636 | len = 0; 637 | for (int j = 0; j <= stepsPerCurve; j++) 638 | { 639 | point = Position(startT + diffT * j); 640 | len += Vector3.Distance(old, point); 641 | old = point; 642 | } 643 | bezierCurvesLength[i] = len; 644 | lenSum += len; 645 | normalizeBezierPoints[i] = lenSum; 646 | } 647 | 648 | bezierLength = lenSum; 649 | 650 | for(int i = 0; i < normalizeBezierPoints.Length; i++) 651 | { 652 | normalizeBezierPoints[i] /= bezierLength; 653 | //Debug.Log("normalizeBezierPoints[" + i + "] " + normalizeBezierPoints[i]); 654 | } 655 | 656 | //preCalcLinearLength = PreCalcLinearLength(); 657 | PreCalcLinearLength(ref preCalcLinearLength); 658 | 659 | //int steps = stepsPerCurve * Length; 660 | //for (int i = 1; i <= steps; i++) 661 | //{ 662 | // point = Position((float)i / (float)steps); 663 | // len += Vector3.Distance(old, point); 664 | // old = point; 665 | //} 666 | 667 | return bezierLength; 668 | } 669 | 670 | public void CaleBezierBoundingBox() 671 | { 672 | 673 | // X 674 | float left = float.MaxValue; 675 | float right = float.MinValue; 676 | // Y 677 | float bottom = float.MaxValue; 678 | float top = float.MinValue; 679 | // Z 680 | float back = float.MaxValue; 681 | float forward = float.MinValue; 682 | 683 | int steps = stepsPerCurve * Length; 684 | for (int i = 1; i <= steps; i++) 685 | { 686 | Vector3 pos = Position((float)i / (float)steps); 687 | //Debug.Log("[" + i + "]" + pos); 688 | if (left >= pos.x) left = pos.x; 689 | if (right <= pos.x) right = pos.x; 690 | 691 | if (bottom >= pos.y) bottom = pos.y; 692 | if (top <= pos.y) top = pos.y; 693 | 694 | if (back >= pos.z) back = pos.z; 695 | if (forward <= pos.z) forward = pos.z; 696 | } 697 | 698 | //for (int i = 1; i < cps.Length; i += 3) 699 | //{ 700 | // Vector3 pos = cps[i].position; 701 | // Debug.Log("[" + i + "]" + pos); 702 | // if (left >= pos.x) left = pos.x; 703 | // if (right <= pos.x) right = pos.x; 704 | 705 | // if (bottom >= pos.y) bottom = pos.y; 706 | // if (top <= pos.y) top = pos.y; 707 | 708 | // if (back >= pos.z) back = pos.z; 709 | // if (forward <= pos.z) forward = pos.z; 710 | //} 711 | 712 | bezierBoundingSize.x = (right - left); 713 | bezierBoundingSize.y = (top - bottom); 714 | bezierBoundingSize.z = (forward - back); 715 | 716 | bezierBoundingCenter.x = left + bezierBoundingSize.x * 0.5f; 717 | bezierBoundingCenter.y = bottom + bezierBoundingSize.y * 0.5f; 718 | bezierBoundingCenter.z = back + bezierBoundingSize.z * 0.5f; 719 | Debug.Log("left " + left + " right " + right + " top " + top + " bottom " + bottom + " forward " + forward + " back " + back); 720 | Debug.Log("size " + bezierBoundingSize + " center " + bezierBoundingCenter); 721 | 722 | //bezierBoundingSize = GetSize(); 723 | //Debug.Log("size " + bezierBoundingSize + " center " + bezierBoundingCenter); 724 | } 725 | #endregion 726 | 727 | #region private method 728 | private void EnforceMode(int index) 729 | { 730 | int modeIndex = (index + 1) / 3; 731 | BezierControlPointMode mode = modes[modeIndex]; 732 | if (mode == BezierControlPointMode.Free || !loop && (modeIndex == 0 || modeIndex == modes.Length - 1)) 733 | { 734 | return; 735 | } 736 | 737 | int middleIndex = modeIndex * 3; 738 | int fixedIndex, enforcedIndex; 739 | if (index <= middleIndex) 740 | { 741 | fixedIndex = middleIndex - 1; 742 | if (fixedIndex < 0) 743 | { 744 | fixedIndex = cps.Length - 2; 745 | } 746 | enforcedIndex = middleIndex + 1; 747 | if (enforcedIndex >= cps.Length) 748 | { 749 | enforcedIndex = 1; 750 | } 751 | } 752 | else 753 | { 754 | fixedIndex = middleIndex + 1; 755 | if (fixedIndex >= cps.Length) 756 | { 757 | fixedIndex = 1; 758 | } 759 | enforcedIndex = middleIndex - 1; 760 | if (enforcedIndex < 0) 761 | { 762 | enforcedIndex = cps.Length - 2; 763 | } 764 | } 765 | 766 | Vector3 middle = cps[middleIndex].position; 767 | Vector3 enforcedTangent = middle - cps[fixedIndex].position; 768 | if (mode == BezierControlPointMode.Aligned) 769 | { 770 | enforcedTangent = enforcedTangent.normalized * Vector3.Distance(middle, cps[enforcedIndex].position); 771 | } 772 | cps[enforcedIndex].position = middle + enforcedTangent; 773 | } 774 | 775 | Vector3 calcVec3; 776 | private Vector3 BezierCurve(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) 777 | { 778 | t = Mathf.Clamp01(t); 779 | //float onMinusT = 1f - t; 780 | double tt = (double)t; 781 | double onMinusT = 1d - tt; 782 | double p0x = p0.x; 783 | double p0y = p0.y; 784 | double p0z = p0.z; 785 | 786 | double p1x = p1.x; 787 | double p1y = p1.y; 788 | double p1z = p1.z; 789 | 790 | double p2x = p2.x; 791 | double p2y = p2.y; 792 | double p2z = p2.z; 793 | 794 | double p3x = p3.x; 795 | double p3y = p3.y; 796 | double p3z = p3.z; 797 | 798 | double mt3 = onMinusT * onMinusT * onMinusT; 799 | double mt2 = onMinusT * onMinusT; 800 | 801 | double tt2 = tt * tt; 802 | double tt3 = tt * tt * tt; 803 | 804 | double bx = mt3 * p0x + 3d * mt2 * tt * p1x + 3d * onMinusT * tt2 * p2x + tt3 * p3x; 805 | double by = mt3 * p0y + 3d * mt2 * tt * p1y + 3d * onMinusT * tt2 * p2y + tt3 * p3y; 806 | double bz = mt3 * p0z + 3d * mt2 * tt * p1z + 3d * onMinusT * tt2 * p2z + tt3 * p3z; 807 | 808 | calcVec3.x = (float)bx; 809 | calcVec3.y = (float)by; 810 | calcVec3.z = (float)bz; 811 | 812 | return calcVec3; 813 | //return new Vector3((float)bx, (float)by, (float)bz); 814 | //return onMinusT * onMinusT * onMinusT * p0 + 3f * onMinusT * onMinusT * t * p1 + 3f * onMinusT * t * t * p2 + t * t * t * p3; 815 | } 816 | #endregion 817 | 818 | #if UNITY_EDITOR 819 | #region inspecterGUI 820 | public bool DrawInspectorGUI(int selectedIndex, ref bool isDrawDirection) 821 | { 822 | bool isChange = false; 823 | 824 | if (cps != null) 825 | { 826 | EditorGUILayout.LabelField("Bezier Length: " + bezierLength); 827 | 828 | EditorGUI.BeginChangeCheck(); 829 | bool loop = EditorGUILayout.Toggle("Loop", Loop); 830 | if (EditorGUI.EndChangeCheck()) 831 | { 832 | Loop = loop; 833 | isChange = true; 834 | } 835 | 836 | EditorGUI.BeginChangeCheck(); 837 | isDrawDirection = EditorGUILayout.Toggle("DrawDirection", isDrawDirection); 838 | if (EditorGUI.EndChangeCheck()) 839 | { 840 | isChange = true; 841 | } 842 | 843 | if ((selectedIndex >= 0) && (selectedIndex < cps.Length)) 844 | { 845 | isChange |= DrawSelectedPointInspector(selectedIndex); 846 | } 847 | EditorGUILayout.BeginHorizontal(); 848 | if ((selectedIndex >= 0) && (selectedIndex < cps.Length) && ((selectedIndex % 3) == 0)) 849 | { 850 | if (GUILayout.Button("Add Point")) 851 | { 852 | Debug.Log("selectedIndex " + selectedIndex); 853 | //AddCurve(); 854 | InsertNextPoint(selectedIndex); 855 | isChange = true; 856 | } 857 | 858 | if (cps.Length > 4) 859 | { 860 | if (GUILayout.Button("Remove Point")) 861 | { 862 | Debug.Log("selectedIndex " + selectedIndex); 863 | RemovePoint(selectedIndex); 864 | isChange = true; 865 | } 866 | } 867 | } 868 | if (GUILayout.Button("Reset")) 869 | { 870 | Reset(); 871 | isChange = true; 872 | } 873 | EditorGUILayout.EndHorizontal(); 874 | 875 | if (bezierCurvesLength != null) 876 | { 877 | EditorGUILayout.BeginVertical(); 878 | GUILayout.Label("Bezier Curves Length"); 879 | for (int i = 0; i < bezierCurvesLength.Length; i++) 880 | { 881 | GUILayout.Label("[" + i + "] " + bezierCurvesLength[i] + " : " + normalizeBezierPoints[i]); 882 | } 883 | 884 | EditorGUILayout.EndVertical(); 885 | } 886 | } 887 | 888 | // 変更があったら長さを再計算 889 | if (isChange) 890 | { 891 | CalcBezierLength(); 892 | } 893 | return isChange; 894 | } 895 | 896 | private bool DrawSelectedPointInspector(int selectedIndex) 897 | { 898 | bool isChange = false; 899 | 900 | GUILayout.Label("Selected Point"); 901 | EditorGUI.BeginChangeCheck(); 902 | Vector3 point = EditorGUILayout.Vector3Field("Position", cps[selectedIndex].position); 903 | if (EditorGUI.EndChangeCheck()) 904 | { 905 | isChange = true; 906 | SetControlPoint(selectedIndex, point); 907 | } 908 | EditorGUI.BeginChangeCheck(); 909 | BezierControlPointMode mode = (BezierControlPointMode)EditorGUILayout.EnumPopup("Mode", GetControlPointMode(selectedIndex)); 910 | if (EditorGUI.EndChangeCheck()) 911 | { 912 | SetControlPointMode(selectedIndex, mode); 913 | isChange = true; 914 | } 915 | 916 | // 変更があったら長さを再計算 917 | if (isChange) 918 | { 919 | CalcBezierLength(); 920 | } 921 | return isChange; 922 | } 923 | #endregion 924 | 925 | #region sceneGUI 926 | private const float handleSize = 0.04f; 927 | private const float pickSize = 0.06f; 928 | private const float directionScale = 0.5f; 929 | 930 | private static Color[] modeColors = { 931 | Color.green, 932 | Color.yellow, 933 | Color.cyan 934 | }; 935 | 936 | private Vector3 ShowPoint(int index, ref int selectedIndex, ref bool isChange) 937 | { 938 | Vector3 point = cps[index].position; 939 | var rot = Quaternion.identity; 940 | float size = HandleUtility.GetHandleSize(point); 941 | if ((index % 3) == 0) 942 | { 943 | size *= 2f; 944 | } 945 | Handles.Label(point, "[" + index + "]"); 946 | Handles.color = modeColors[(int)GetControlPointMode(index)]; 947 | if (Handles.Button(point, rot, size * handleSize, size * pickSize, Handles.DotCap)) 948 | { 949 | selectedIndex = index; 950 | isChange |= true; 951 | } 952 | 953 | 954 | if (selectedIndex == index) 955 | { 956 | EditorGUI.BeginChangeCheck(); 957 | point = Handles.DoPositionHandle(point, rot); 958 | if (EditorGUI.EndChangeCheck()) 959 | { 960 | SetControlPoint(index, point); 961 | isChange |= true; 962 | } 963 | } 964 | return point; 965 | } 966 | 967 | private void ShowDirections() 968 | { 969 | Handles.color = Color.green; 970 | Vector3 point = Position(0f); 971 | Handles.DrawLine(point, point + Direction(0f) * directionScale); 972 | int steps = stepsPerCurve * Length; 973 | for (int i = 1; i <= steps; i++) 974 | { 975 | point = Position(i / (float)steps); 976 | Handles.DrawLine(point, point + Direction(i / (float)steps) * directionScale); 977 | } 978 | } 979 | 980 | public bool DrawSceneGUI(ref int selectedIndex, ref bool isShowDirection) 981 | { 982 | bool isChange = false; 983 | 984 | if (cps != null && cps.Length > 3) 985 | { 986 | Vector3 p0 = ShowPoint(0, ref selectedIndex, ref isChange); 987 | float colStep = 1f / cps.Length; 988 | for (int i = 1; i < cps.Length; i += 3) 989 | { 990 | Vector3 p1 = ShowPoint(i, ref selectedIndex, ref isChange); 991 | Vector3 p2 = ShowPoint(i + 1, ref selectedIndex, ref isChange); 992 | Vector3 p3 = ShowPoint(i + 2, ref selectedIndex, ref isChange); 993 | 994 | Handles.color = Color.gray; 995 | Handles.DrawLine(p0, p1); 996 | Handles.DrawLine(p2, p3); 997 | //Gizmos.color = Color.HSVToRGB(i, 1f, 1f); 998 | //Handles.DrawBezier(p0, p3, p1, p2, Color.white, null, 2f); 999 | Handles.DrawBezier(p0, p3, p1, p2, Color.HSVToRGB((float)i * colStep, 1f, 1f), null, 2f); 1000 | p0 = p3; 1001 | } 1002 | 1003 | if(isShowDirection) ShowDirections(); 1004 | } 1005 | 1006 | // 変更があったら長さを再計算 1007 | if (isChange) 1008 | { 1009 | CalcBezierLength(); 1010 | } 1011 | 1012 | return isChange; 1013 | } 1014 | #endregion 1015 | #endif 1016 | 1017 | [System.Serializable] 1018 | public class ControlPoint 1019 | { 1020 | public Vector3 position; 1021 | } 1022 | 1023 | } 1024 | 1025 | public enum BezierControlPointMode 1026 | { 1027 | Free, 1028 | Aligned, 1029 | Mirrored 1030 | } 1031 | } -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/BezierBase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 71f4291b6ceef80489fae13db5effe6a 3 | timeCreated: 1484131280 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ebb162bf043ac864aba6c6052510109f 3 | folderAsset: yes 4 | timeCreated: 1484119810 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Editor/BezierEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using UnityEditor; 6 | 7 | namespace BezierTools 8 | { 9 | [CustomEditor(typeof(Bezier))] 10 | public class BezierEditor : Editor 11 | { 12 | #region define 13 | private const float handleSize = 0.04f; 14 | private const float pickSize = 0.06f; 15 | private const int stepsPerCurve = 20; 16 | private const float directionScale = 0.5f; 17 | #endregion 18 | 19 | private Bezier bezier; 20 | private int selectedIndex = -1; 21 | 22 | private bool isDrawDirection = false; 23 | 24 | #region publicmethod 25 | public override void OnInspectorGUI() 26 | { 27 | bezier = (Bezier)target; 28 | if (bezier.data == null) 29 | { 30 | bezier.data = new BezierData(); 31 | } 32 | if (bezier.data.cps == null) 33 | { 34 | bezier.data.Reset(); 35 | } 36 | 37 | if (bezier.data.DrawInspectorGUI(selectedIndex, ref isDrawDirection)) 38 | { 39 | EditorUtility.SetDirty(bezier); 40 | } 41 | } 42 | #endregion 43 | 44 | #region privatemthod 45 | private void OnSceneGUI() 46 | { 47 | bezier = (Bezier)target; 48 | if (bezier.data == null) 49 | { 50 | bezier.data = new BezierData(); 51 | } 52 | 53 | if(bezier.data.DrawSceneGUI(ref selectedIndex, ref isDrawDirection)) 54 | { 55 | EditorUtility.SetDirty(bezier); 56 | } 57 | } 58 | 59 | private void OnEnable() 60 | { 61 | SceneView.onSceneGUIDelegate += DrawSceneGUI; 62 | } 63 | private void OnDisable() 64 | { 65 | SceneView.onSceneGUIDelegate -= DrawSceneGUI; 66 | } 67 | 68 | private void DrawSceneGUI(SceneView sceneView) 69 | { 70 | OnSceneGUI(); 71 | } 72 | #endregion 73 | 74 | [MenuItem("Assets/Create/Bezier")] 75 | public static void CreateSpline() { ScriptableObjUtil.CreateAsset(); } 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Editor/BezierEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 825a1f95dfe4c4346a98014028468e9c 3 | timeCreated: 1484119841 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Editor/ScriptableObjUtil.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | using System.IO; 5 | 6 | namespace BezierTools 7 | { 8 | public static class ScriptableObjUtil { 9 | 10 | public static void CreateAsset() where T : ScriptableObject { 11 | var path = AssetDatabase.GetAssetPath(Selection.activeObject); 12 | if (path == "") 13 | path = "Assets"; 14 | else if (!Directory.Exists(path)) { 15 | var lastSlash = path.LastIndexOf("/"); 16 | if (lastSlash >= 0) 17 | path = path.Substring(0, lastSlash); 18 | } 19 | path = AssetDatabase.GenerateUniqueAssetPath(path + "/" + typeof(T).Name + ".asset"); 20 | 21 | var asset = ScriptableObject.CreateInstance(); 22 | AssetDatabase.CreateAsset(asset, path); 23 | AssetDatabase.SaveAssets(); 24 | AssetDatabase.Refresh(); 25 | EditorUtility.FocusProjectWindow(); 26 | Selection.activeObject = asset; 27 | } 28 | 29 | public static void CreateAssetNonGeneric(System.Type T) { 30 | var ti = typeof(ScriptableObjUtil); 31 | var mi = ti.GetMethod("CreateAsset"); 32 | mi = mi.MakeGenericMethod(T); 33 | mi.Invoke(null, null); 34 | } 35 | 36 | [MenuItem("Assets/Create/ScriptableObject")] 37 | static void CreateScriptableObject() { 38 | var selected = Selection.activeObject as MonoScript; 39 | if (selected == null || !AssetDatabase.Contains(selected)) { 40 | Debug.Log("Select ScriptableObject in Assets"); 41 | return; 42 | } 43 | 44 | var type = selected.GetClass(); 45 | if (!type.IsSubclassOf(typeof(ScriptableObject))) { 46 | Debug.Log("Not a Subclass of ScriptableObject"); 47 | return; 48 | } 49 | 50 | ScriptableObjUtil.CreateAssetNonGeneric(type); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Editor/ScriptableObjUtil.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e2337f67e05b6c94c8e111677daf994d 3 | timeCreated: 1430388886 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Samples.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7f2825dc785af4f47bede84a42141597 3 | folderAsset: yes 4 | timeCreated: 1484121916 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Samples/BezierLoopSample.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/Assets/Packages/BezierTools/Samples/BezierLoopSample.asset -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Samples/BezierLoopSample.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d8b256bb110e20e4d8344bfdb1f8dde9 3 | timeCreated: 1484131913 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Samples/BezierSample.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/Assets/Packages/BezierTools/Samples/BezierSample.asset -------------------------------------------------------------------------------- /Assets/Packages/BezierTools/Samples/BezierSample.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4cc69f79158877d41a7fa5c613ccd415 3 | timeCreated: 1484131826 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 5.5.2f1 2 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UnityBezierTools 2 | 3 | ![UnityBezierTools](ReadMeData/ss001.png) 4 | 5 | 3D Bezier Curve Library for Unity3d. 6 | Loop on/off support. 7 | 8 | ## Usage 9 | 10 | import [UnityBezierTools.unitypackage](UnityBezierTools.unitypackage) to your unity project. 11 | 12 | ### How to create Bezier scriptable object 13 | 14 | 1. [Menu]->[Assets]->[Create]->[Bezier] 15 | 2. Select to large control point. it move position by D&D. 16 | ![Select large control point](ReadMeData/ss002.png) 17 | In inspector window, 18 | - click [Add Point] Button, add to control point. 19 | - click [Remove Point] Button, remove selected large control point. 20 | - click [Reset] Button, reset selected bezier object. 21 | 22 | ![UnityBezierTools](ReadMeData/ss003.png) 23 | 24 | 3. Select to small control point. it move position by D&D. 25 | In inspector window, 26 | - click [Reset] Button, reset selected bezier object. 27 | 28 | ![UnityBezierTools](ReadMeData/ss004.png) 29 | 30 | 4. Other inspector window settings, 31 | - [Mode] pull-down menu, change connect mode in control point. 32 | - [Loop] toggle, connect the first and last points on enable. 33 | - [DrawDirection] toggle, Draw curve direction line on enable . 34 | -------------------------------------------------------------------------------- /ReadMeData/ss001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ReadMeData/ss001.png -------------------------------------------------------------------------------- /ReadMeData/ss002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ReadMeData/ss002.png -------------------------------------------------------------------------------- /ReadMeData/ss003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ReadMeData/ss003.png -------------------------------------------------------------------------------- /ReadMeData/ss004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/ReadMeData/ss004.png -------------------------------------------------------------------------------- /UnityBezierTools.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaiware007/UnityBezierTools/8ee08c29af2d20b8cece9e59b34eed9e3773509e/UnityBezierTools.unitypackage --------------------------------------------------------------------------------