본문 바로가기

유니티

유니티 베지에 곡선 만들기

2차 베지에 곡선

시간이 비어서(?) 예전에 읽었던 글(https://blog.coderifleman.com/2016/12/30/bezier-curves/)을 참고하며 유니티로 베지에 커브를 구현해보았습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Bezier : MonoBehaviour
{
    public List<GameObject> p = new List<GameObject>();
    public List<GameObject> m = new List<GameObject>();
    public List<GameObject> b = new List<GameObject>();
 
    public LineRenderer pLine0, pLine1;
    public LineRenderer mLine0;
 
    float t = 0f;
 
    // b0 추적남기기
    List<GameObject> traceObjs = new List<GameObject>();
    public GameObject traceGroup;
    public GameObject trace;
 
    [Header("도달 속도 설정")]
    [Range(0f, 3f)]
    public float speed = 1f;
    [Header("추적 비율")]
    public float traceRate = 0.015f;
 
    void Start()
    {
 
    }
 
    void Update()
    {
        if (t <= 1 / speed)
            t += Time.deltaTime;
 
        pLine0.SetPosition(0, p[0].transform.position);
        pLine0.SetPosition(1, p[1].transform.position);
 
        pLine1.SetPosition(0, p[1].transform.position);
        pLine1.SetPosition(1, p[2].transform.position);
 
        mLine0.SetPosition(0, m[0].transform.position);
        mLine0.SetPosition(1, m[1].transform.position);
    }
 
    GUIStyle style = new GUIStyle();
 
    private void OnGUI()
    {
        style.fontSize = 50;
        GUI.Label(new Rect(2510020060), $"t = {t}", style);
 
        if (GUI.Button(new Rect(25200100100), "재시작"))
        {
            StopAllCoroutines();
 
            t = 0f;
 
            m[0].transform.position = p[0].transform.position;
            m[1].transform.position = p[1].transform.position;
            b[0].transform.position = p[0].transform.position;
 
            StartCoroutine(MoveToTarget(m[0].transform, p[1].transform));
            StartCoroutine(MoveToTarget(m[1].transform, p[2].transform));
            StartCoroutine(MoveToTarget2(b[0].transform, m[0].transform, m[1].transform));
 
            foreach (GameObject obj in traceObjs)
            {
                Destroy(obj);
            }
            traceObjs.Clear();
        }
    }
 
    // 점 P 사이에서 이동하는 점 M을 이동시키기 위해 사용함
    IEnumerator MoveToTarget(Transform self, Transform target)
    {
        Vector3 originPos = self.transform.position;
        Vector3 destPos = target.transform.position - originPos;
        float time = 0f;
 
        while (time <= 1f)
        {
            self.transform.position = originPos + destPos * time;
            time += Time.deltaTime * speed;
            yield return null;
        }
 
        self.transform.position = target.position;
        yield break;
    }
 
    Coroutine co;
 
    // 움직이는 점 M 사이에서 이동하는 점 B을 이동시키기 위해 사용함
    IEnumerator MoveToTarget2(Transform self, Transform target0, Transform target1)
    {
        Vector3 originPos, destPos;
        float time = 0f;
 
        co = StartCoroutine(Trace());
 
        while (time <= 1f)
        {
            originPos = target0.transform.position;
            destPos = target1.transform.position - originPos;
 
            self.transform.position = originPos + destPos * time;
            time += Time.deltaTime * speed;
 
            yield return null;
        }
        StopCoroutine(co);
        self.transform.position = target1.position;
        yield break;
    }
 
    // 점 B가 이동한 경로를 남김
    IEnumerator Trace()
    {
        while (true)
        {
            GameObject obj = Instantiate(trace, traceGroup.transform);
            obj.transform.position = b[0].transform.position;
            traceObjs.Add(obj);
 
            yield return new WaitForSeconds(traceRate);
        }
    }
}
 
cs

일단 구현에만 초점을 맞춘 프로토타입이기 때문에 코드가 조금 지저분.. 합ㄴ디ㅏ.

 

씬 세팅은 이런식으로 되어있고요. 

차후에 2차 베지에 말고도 n차를 자유롭게 다룰 수 있게 만들면 추가로 올리겠습니다.