2022. 8. 16. 23:27ㆍ유니티 unity
참고 주소
https://www.youtube.com/watch?v=pnYccz1Ha34
https://blog.coderifleman.com/2016/12/30/bezier-curves/
https://suhak.tistory.com/1211
베지어 곡선을 이용해서 곡선을 그려보겠습니다.
베지어 곡선이란?
프랑스의 공학자 피에르 베지에(Pierre Bézier)의 이름을 딴 곡선. 영어식으로 베지어 곡선으로 읽기도 한다. 2개 이상의 점으로 정의되는 매개변수 곡선이며, 점 몇개로 곡선을 특정할 수 있는 성질 때문에 CAD, 컴퓨터 그래픽 등 컴퓨터 환경, 특히 벡터 그래픽에서 곡선을 표현하는 데 널리 쓰인다.
베지어 곡선을 글로만 설명을 들으면 헷갈린데 그림으로 보면 엄청 쉽게 이해가 됩니다.
3차 베지어 곡선
3차 베지어 곡선의 공식(점 4개가 주어졌을 때)
n차 베지어 곡선은 점화식으로 정의가 가능합니다.
이제 이걸 유니티로 구현을 해야 하는데 다음처럼 구현을 하면 됩니다.
//점이 4개있는 3차 베지어 공식
public float Bezier(float P0, float P1, float P2, float P3,float t)
{
return Mathf.Pow((1 - t), 3) * P0 + Mathf.Pow((1 - t), 2) * 3 * t * P1 + Mathf.Pow(t, 2) * 3 * (1 - t) * P2 +
Mathf.Pow(t, 3) * P3;
}
유니티 함수 Lerp를 이용하면 좀 더 보기 쉽게 구현이 가능합니다.
public Vector3 Bezier(Vector3 P0, Vector3 P1, Vector3 P2, Vector3 P3, float t)
{
Vector3 M0 = Vector3.Lerp(P0, P1, t);
Vector3 M1 = Vector3.Lerp(P1, P2, t);
Vector3 M2 = Vector3.Lerp(P2, P3, t);
Vector3 B0 = Vector3.Lerp(M0, M1, t);
Vector3 B1 = Vector3.Lerp(M1, M2, t);
return Vector3.Lerp(B0, B1, t);
}
화면으로 표시하기 위해서 4개의 오브젝트를 만들었습니다.
베지어 곡선을 사용할 때는 P1과 P2의 위치만 따로 넣어주면 됩니다.
단순 곡선만 사용하려면 P0기준으로 높이 P3기준으로 높이만 설정하면 됩니다.
이제 베지어 함수를 가지고 라인 렌더를 설정하면 됩니다.
라인 렌더의 Positions을 균등하게 넣어주면 됩니다.
20개 정도가 깔끔하게 나오는 거 같습니다.
public LineRenderer line;//라인렌더
[Min(2)]
public int lineCnt = 20;//라인 수
for (int i = 0; i < lineCnt; i++)
{
float t;
if (i == 0)
{
t = 0;
}
else
{
t = (float)i / (lineCnt - 1);
}
Vector3 bezier = Bezier(P0_GameObject.transform.position, P1_GameObject.transform.position, P2_GameObject.transform.position,
P3_GameObject.transform.position, t);
/*
bezier2 를 써도 됩니다.
Vector3 bezier2;
bezier2.x=Bezier(P0_GameObject.transform.position.x, P1_GameObject.transform.position.x, P2_GameObject.transform.position.x,
P3_GameObject.transform.position.x, t);
bezier2.y=Bezier(P0_GameObject.transform.position.y, P1_GameObject.transform.position.y, P2_GameObject.transform.position.y,
P3_GameObject.transform.position.y, t);
bezier2.z=Bezier(P0_GameObject.transform.position.z, P1_GameObject.transform.position.z, P2_GameObject.transform.position.z,
P3_GameObject.transform.position.z, t);
*/
line.SetPosition(i, bezier); // 라인을 설정합니다
}
라인 수가 3개 일 때
라인 수가 20개 일 때
이걸 활용해서 수류탄 궤적이나 점프 궤적을 그릴 수 있고 포탄의 포물선이동도 구현이 가능합니다.
P1와 P2의 위치를 일정범위로 랜덤 하게 조절한다면 롤의 카이사 Q 스킬처럼 미사일이 나갈 수 있습니다.
코드 보기
using UnityEngine;
public class Curve : MonoBehaviour
{
public LineRenderer line;//라인렌더
[Min(2)]
public int lineCnt = 20;//라인 수
public Vector3 p1Pos=new Vector3(0,5,0); // P0기준으로 p1 더하기
public Vector3 p2Pos=new Vector3(0,5,0);// P3기준으로 p2 더하기
public GameObject P0_GameObject;
public GameObject P1_GameObject;
public GameObject P2_GameObject;
public GameObject P3_GameObject;
void Update()
{
LineDraw();
}
public Vector3 Bezier(Vector3 P0, Vector3 P1, Vector3 P2, Vector3 P3, float t)
{
//gif를 보시면 좀더 이해하기 쉽습니다.
Vector3 M0 = Vector3.Lerp(P0, P1, t);
Vector3 M1 = Vector3.Lerp(P1, P2, t);
Vector3 M2 = Vector3.Lerp(P2, P3, t);
Vector3 B0 = Vector3.Lerp(M0, M1, t);
Vector3 B1 = Vector3.Lerp(M1, M2, t);
return Vector3.Lerp(B0, B1, t);
}
//점이 4개있는 3차 베지어 공식
public float Bezier(float P0, float P1, float P2, float P3,float t)
{
return Mathf.Pow((1 - t), 3) * P0 + Mathf.Pow((1 - t), 2) * 3 * t * P1 + Mathf.Pow(t, 2) * 3 * (1 - t) * P2 +
Mathf.Pow(t, 3) * P3;
}
void LineDraw()
{
line.positionCount = lineCnt;
//라인렌더러 라인수 설정
P1_GameObject.transform.position = P0_GameObject.transform.position + p1Pos;
//보여주기식 P1를 설정한다
P2_GameObject.transform.position = P3_GameObject.transform.position + p2Pos;
//보여주기식 P2를 설정한다
for (int i = 0; i < lineCnt; i++)
{
float t;
if (i == 0)
{
t = 0;
}
else
{
t = (float)i / (lineCnt - 1);
}
Vector3 bezier = Bezier(P0_GameObject.transform.position, P1_GameObject.transform.position, P2_GameObject.transform.position,
P3_GameObject.transform.position, t);
/*
bezier2 를 써도 됩니다.
Vector3 bezier2;
bezier2.x=Bezier(P0_GameObject.transform.position.x, P1_GameObject.transform.position.x, P2_GameObject.transform.position.x,
P3_GameObject.transform.position.x, t);
bezier2.y=Bezier(P0_GameObject.transform.position.y, P1_GameObject.transform.position.y, P2_GameObject.transform.position.y,
P3_GameObject.transform.position.y, t);
bezier2.z=Bezier(P0_GameObject.transform.position.z, P1_GameObject.transform.position.z, P2_GameObject.transform.position.z,
P3_GameObject.transform.position.z, t);
*/
line.SetPosition(i, bezier); // 라인을 설정합니다
}
}
}
'유니티 unity' 카테고리의 다른 글
유니티(Unity) 오브젝트 풀링 (2) | 2022.09.13 |
---|---|
유니티(Unity) Job 시스템 사용법-1 (0) | 2022.08.23 |
유니티(Unity) Quaternion 전부 알기 (0) | 2022.08.15 |
Unity Unitask 사용법 (0) | 2022.08.10 |
unity(유니티) vector 함수 전부 알기 (0) | 2022.08.03 |