다른 사람들은 노트 이미지를 가져다 넣어서 위치만 이동시켜주면 노트 내려오는게 뚝딱 구현완료이지만
나같은 경우는 노트의 크기가 배경에 맞춰서 실시간으로 변해야 하고
무엇보다 노트에 이미지를 쓰지 않고 좌표로 직접 메쉬를 생성하다보니 고민할것이 너무나도 많았다
정말 오랜시간동안 고민하고 방법을 찾고 구조를 갈아엎어서 노트블럭을 생성하고 정상적으로 중심으로 내려오는것 까지 구현에 성공했다.
물론 딱 작동하게만 만들어둔 것이고 이걸로 패턴을 짜고 여러가지 상황을 대비하려면 계속해서 다듬고 갈아엎어야겠지만
일단 작동하는 노트블럭을 구현했다는것에 의의를 뒀다.
Mesh mesh; //메쉬
public PolygonGenerator polygonGenerator; // 첫각도와 배경이 몇각형인지 받아온다
public GameManager gameManager; //게임 속도를 받아온다.
int speed; //게임속도 저장
Vector3[] outPoly; //바깥 다각형의 좌표 저장
Vector3[] inPoly; //안쪽 다각형의 좌표 저장
Vector3[] noteBlock; //사각형 노트블럭의 4개의 좌표 저장
int[] noteBlockIdx; //메쉬에 쓸 노트블럭 렌더링 인덱스
Vector3 up1; //노트블럭 사각형의 오른쪽 위
Vector3 up2; //왼쪽 위
Vector3 down1; //오른쪽 아래
Vector3 down2; //왼쪽 아래
int currentEdge; //어느위치에서 내려올 것인지
float timeLen; // 노트의 길이
int vertex; //호출한 시점에서 배경 다각형의 꼭짓점 수
int changed_vertex; //배경 다각형의 꼭짓점 수가 변하는지 체크
float time; //시간
Note 클래스에서 사용한 변수들이다.
얼기설기 코드를 짜느라 상당히 복잡하지만 일단은 이렇게 구현했다.
public void callNote(int num, float timeLen)
{
currentEdge = num;
this.timeLen = timeLen;
gameObject.SetActive(true);
}
패턴 생성기등에서 노트를 호출할때 이 함수로 호출한다.
어느 각에서 어느정도의 길이로 생성할지 전달해주고 노트블럭을 활성화 시킨다.
void calcPoint()
{
vertex = polygonGenerator.getCurrentPoly();
float firstDegree = polygonGenerator.getfirstDegree();
float radius1 = polygonGenerator.getOutRadius();
float radius2 = polygonGenerator.getInRadius();
float deg = (360 - firstDegree) / (vertex - 1);
for (int i = 0; i <= 1; i++)
{
var rad = Mathf.Deg2Rad * (firstDegree * i);
var x = radius1 * Mathf.Sin(rad);
var y = radius1 * Mathf.Cos(rad);
outPoly[i] = new Vector3(x, y);
x = radius2 * Mathf.Sin(rad);
y = radius2 * Mathf.Cos(rad);
inPoly[i] = new Vector3(x, y);
}
for (int i = 2; i < vertex; i++)
{
var rad = Mathf.Deg2Rad * ((deg * (i - 1)) + firstDegree);
if (i == 1) rad = 0;
var x = radius1 * Mathf.Sin(rad);
var y = radius1 * Mathf.Cos(rad);
outPoly[i] = new Vector3(x, y);
x = radius2 * Mathf.Sin(rad);
y = radius2 * Mathf.Cos(rad);
inPoly[i] = new Vector3(x, y);
}
}
배경 다각형을 직접 계산한다. 처음에는 배경을 생성하는 클래스에서 구해진 배경 좌표들을 그대로 가져오려 했지만
프레임단위로 배경좌표들을 계속 가져와야하기에 차라리 여기서 필요한 좌표들만 새로 구하는게 나을꺼 같았다.
다만 배경 생성 클래스에서 생성한 배경과 동일한 좌표를 구해야 하기 때문에 배경생성 클래스에서 사용하는
다각형의 첫번째 각도만 받아와 계산을 시작하도록 했다.
노트블럭은 바깥쪽 큰 다각형에서 시작하여 안쪽 작은 다각형 사이에서 이동하므로
해당 좌표들을 구해주면 된다.
void calcSquare()
{
up1 = outPoly[currentEdge];
up2 = outPoly[(currentEdge + 1)%vertex];
down1 = inPoly[currentEdge];
down2 = inPoly[(currentEdge + 1)%vertex];
}
생성된 배경 다각형을 바탕으로
노트블럭이 이동할 위치에 해당하는 네개의 좌표를 저장한다.
이 네개의 좌표가 만든 사각형 내에서 노트블럭이 생성되고 내려올것이다.
void init()
{
speed = gameManager.GameSpeed;
changed_vertex = polygonGenerator.getCurrentPoly();
if (vertex > changed_vertex)
{
if (currentEdge == 0)
{
gameObject.SetActive(false);
return;
}
else
{
currentEdge--;
}
}
else if(vertex < changed_vertex)
{
currentEdge++;
}
calcPoint();
calcSquare();
}
Update가 될때마다 필요한 값을 새로 갱신해줘야 한다.
매 프레임마다 복잡한 계산이 들어가는 이유는
예를들면 노트블럭이 내려오는 도중에 배경 다각형이 6각형에서 5각형으로 바뀐다면
노트블럭의 크기가 같이 변해야하기 때문이다.
구현할때 문제점이 있었는데 배경 다각형은 꼭짓점의 갯수가 바뀌면 완전히 바뀌는 순간 미리 만들어놓은 해당 다각형 좌표로 완전히 전환되어 버린다.
하지만 노트블럭은 0,1,2,3,4,5번 레일에서 내려오는 형태이기 때문에 다각형의 꼭짓점이 줄거나 늘면 노트의 위치가 밀려버린다는 문제점이 있었다.
그러므로 변하기전 꼭짓점의 갯수를 따로 저장해주고 프레임마다 현재 꼭짓점의 갯수를 계속 체크하다가
만약 두 숫자가 달라지면 노트블럭의 레일을 밀거나 당겨서 맞춰주어야 한다.
void callDown(float p)
{
noteBlock[1] = Vector3.Lerp(up1, down1, p);
noteBlock[2] = Vector3.Lerp(up2, down2, p);
}
void callUp(float p)
{
noteBlock[0] = Vector3.Lerp(up1, down1, p);
noteBlock[3] = Vector3.Lerp(up2, down2, p);
}
노트블럭을 아래로 내려오게 하는 함수이다.
노트블럭 사각형의 아랫면이 먼저 내려오고 윗면이 내려오는데
아래 두점, 위의 두점이 묶여서 Lerp 함수를 이용해 평행사변형의 빗변을 타고 내려온다.
void Update()
{
init();
time += Time.deltaTime * speed;
if(time<2000f)
{
callDown(time / 2000);
callUp(0.0f);
}
if(time>timeLen)
{
callUp((time - timeLen) / 2000);
callDown(time / 2000);
}
createProceduralMesh();
if((time - timeLen) / 2000>=1.0f)
{
gameObject.SetActive(false);
}
Debug.Log(time + " " + noteBlock[0] + " " + noteBlock[1] + " " + noteBlock[2] + " " + noteBlock[3]);
}
일단 타일의 길이등을 시간을 이용해 구현했는데 개선해야한다.
일단 노트가 정상적으로 맨 위에서 맨 아래로 없어질때까지의 계수를 2000이라고 잡았다.
호출받은 길이가 그보다 길 경우 일정시간동안 노트가 레일을 꽉 채우다가 일정 시간이 지난후 윗면이 내려와야 하기에 이런식으로 구현했다.
그리고 윗면이 바닥까지 내려오면 노트 오브젝트를 끈다.
이 구조를 만들려고 얼마나 오랜시간이 걸렸는지.;;;
방학동안 이 프로젝트를 완성하는게 목표인데 어디까지 할 수 있을지 모르겠다.
일단 현재 문제점은
1. 노트의 길이가 시간으로 구현되어있기에 게임속도가 빨라지면 같은 시간으로 노트를 호출해도 노트자체가 얇아질 수 있다. 게임속도가 어찌됐든 같은 계수로 노트를 호출하면 노트의 속도만 빨라지고 노트의 길이는 같도록 구현해야한다.
2.노트가 내려오는 도중 다각형의 각이 줄어드는 경우는 깔끔하게 구현되었으나 각이 늘어나는 경우는 배경에서 각을 먼저 늘리고 시작하기때문에 노트가 레일의 목표지점으로 먼저 탈출해버린다. 이를 수정해야한다.
해당 문제점을 개선해야 하고 구조 자체를 패턴을 짜기 용이하도록 어느정도 개선이 필요할 것이다.
'Unity 게임개발' 카테고리의 다른 글
기획 - 1. 장르 정하기 (0) | 2023.08.04 |
---|---|
팀프로젝트 진행 - 1 (0) | 2023.08.04 |
3.5 구조 개선 (0) | 2023.05.05 |
3. 다각형간 자연스러운 전환 구현 (0) | 2023.04.02 |
2. 기본적인 배경 구현 (0) | 2023.04.01 |