Ruya Games

Unity에서 사용 가능한 C# BezierCurves 일반화 함수 본문

Unity

Unity에서 사용 가능한 C# BezierCurves 일반화 함수

SadEvil 2023. 11. 30. 15:56

사용되는 변수들

public GameObject torpedo;
public List<Transform> transformList;
private List<Vector3> vectorsList;
public float speed;

torpedo : 곡선을 따라 움직일 오브젝트

transformList : 베지어 곡선의 point 오브젝트들

vectorsList : point 오브젝트들의 transform.position 값들

speed : 오브젝트의 속도

 


베지어 커브 계산 함수

	private static Vector3 Bezier(List<Vector3> points, float value) {
		List<Vector3> step1 = points.ToList();
		int pastTemp = 0;
		for(int i = 1; i < points.Count; i++) {
			var temp = step1.Count;
			for(int j = pastTemp; j < temp-1; j++) {
				step1.Add(Vector3.Lerp(step1[j], step1[j+1], value));
			}
			pastTemp = temp;
		}
		return step1.Last();
	}

 


베지어 커브 함수를 사용하는 코루틴 함수(Update로도 대체 가능)

IEnumerator Func() {
    var value = 0.0f; //0 : 시작점   1 : 도착지점
    while(value < 1.0f) {
        torpedo.transform.position = Bezier(vectorsList, value);
        value += Time.deltaTime*speed;
        yield return new WaitForSeconds(Time.deltaTime);
    }
}

 


전체 코드

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

public class BezierTest : MonoBehaviour {
	public GameObject torpedo;
	public List<Transform> transformList;
	private List<Vector3> vectorsList;
	public float speed; //speed를 조절하면 진행속도가 빨라짐.
	
	private void Start() {
		vectorsList = new List<Vector3>();
		foreach (var objTransform in transformList) {
			vectorsList.Add(objTransform.position);
		}
		StartCoroutine(Func());
	}

	private static Vector3 Bezier(List<Vector3> points, float value) {
		List<Vector3> step1 = points.ToList();
		int pastTemp = 0;
		for(int i = 1; i < points.Count; i++) {
			var temp = step1.Count;
			for(int j = pastTemp; j < temp-1; j++) {
				step1.Add(Vector3.Lerp(step1[j], step1[j+1], value));
			}
			pastTemp = temp;
		}
		return step1.Last();
	}
	
	IEnumerator Func() {
		var value = 0.0f; //0 : 시작점   1 : 도착지점
		while(value < 1.0f) {
			torpedo.transform.position = Bezier(vectorsList, value);
			value += Time.deltaTime*speed;
			yield return new WaitForSeconds(Time.deltaTime);
		}
	}
}

하나의 게임오브젝트당 하나의 Func()함수를 사용해야 하기 때문에, torpedo 오브젝트에 이 클래스를 넣고 사용하는게 가장 편합니다.

 


에디터에서의 적용

 


동작 영상