https://github.com/h8man/TurboTrack2D
GitHub - h8man/TurboTrack2D: Prototype of 2D arcade style racing game
Prototype of 2D arcade style racing game. Contribute to h8man/TurboTrack2D development by creating an account on GitHub.
github.com
열심히 뜯어봐서 이제 대충 알겠는 pseudo 3d. 다들 같이 봐보자.
참고로 여기 프로젝트에서 도로의 스프라이트는 존재하지 않는다. 오로지 메터리얼로 그려주고 있기 때문. 따라서 이 스크립트를 이용한다면 도로의 스프라이트를 따로 줄 수 없다. 지금으로서는 메테리얼의 색깔만 바꿔 줄 수 있다. 이 부분은 수정해 볼 수 있으면 수정해 볼 예정이다.
이 프로젝트에선 크게 HqRenderer, TrackObject, Line 스크립트를 보면 된다.
1. Line.cs에서는 도로의 각 세그먼트에 대한 데이터를 저장하는 구조체이다. 이미지에서 볼 수 있는 속성들을 포함하는 곳이기에 이 구조체를 통해 TrackObject에서 배열로 관리가 된다.
using UnityEngine;
public struct Line
{
public float x, y, z, w;//3d center of line
public float X, Y, W; //screen coord
public float curve, spriteX, clip, scale;
public Sprite sprite;
public bool flipX;
//장애물 충돌처리 때문에 추가
public bool isObstacle; // 장애물 여부 체크
public void project(int camX, int camY, int camZ, int screenWidth2, int screenHeight2, float cameraDepth)
{
scale = cameraDepth / (z - camZ);
X = scale * (x - camX) * screenWidth2;
Y = scale * (y - camY) * screenHeight2;
W = scale * w * screenWidth2;
}
}
아. 참고로 나의 경우 장애물을 그려주기 위해 위에서 처럼 코드에 bool변수인 isObstacle을 추가해 주었다.
주요 속성으로 spriteX, frequency, segments, sprite 정도는 알아둬야 된다.
- spriteX는 스프라이트의 x축 위치를 말한다. 이 값으로 화면에 보여주고 싶은 오브젝트의 위치를 정한다.
- frequency는 스프라이트가 반복되는 간격을 말한다. 같은 간격으로 왼쪽, 오른쪽에 물체를 추가해주고 싶다면 같은 값을 입력하면 되고, 만약 다르게 나타내고 싶다면 다른 값을 입력해 주면 어긋나게 오브젝트들이 나온다.
- segments의 경우 시작과 끝지점이다.(x, y값) 이걸로 물체를 어디서부터 어디까지 나오게 하고 싶은지 정하면 된다.
- sprite는 해당 라인에 표시될 스프라이트로 그려주고 싶은 오브젝트의 스프라이트를 넣어주면 된다.
이제 유니티에 가서 Tracks폴더에 있는 New Track을 켜주고 추가로 그려주고 싶은 애들을 Modifier에 추가해 주자.
아까도 말했듯이 나는 장애물을 추가해주고 싶었기 때문에 왼쪽 장애물과 오른쪽 장애물을 추가해 주었다.
2. TrackObject.cs를 봐보자.
여기는 도로 트랙의 전체적인 구성과 속성을 관리하는 ScriptableObject다.
여기서는 트랙을 생성해 주는 Construct() 함수를 봐야 된다. 방금 유니티의 Inspector에서 설정된 TrackModifier들(leftObstacle, RightObstacle)의 속성들이 Construct() 함수를 통해 실제 트랙에 적용되어 화면에 표시되는 것이다.
참고로, 만약 트랙의 길이를 더 길게 하고 싶다면 TrackObject.cs에서 Length 값을 증가시켜 주면 된다.
using HQ;
using UnityEngine;
[CreateAssetMenu( fileName = "New Track", menuName = "HQ/Track")]
public class TrackObject: ScriptableObject
{
public int Length;
public Line[] lines { get; protected set; }
[HideInInspector]
public TrackModifier[] Modifier;
public float roadWidth;
public int segmentLength;
public float trackHeight;
private void OnEnable()
{
Construct();
}
protected virtual void Construct()
{
Length = 1600;
lines = new Line[Length];
for (int i = 0; i < Length; i++)
{
ref Line line = ref lines[i];
line.z = i * segmentLength;
line.w = roadWidth;
foreach (var m in Modifier)
{
if (!m.disabled && m.Segments.InRange(i) && i % m.frequency == 0)
{
line.curve += m.curve;
line.spriteX = m.spriteX;
line.y += Mathf.Sin(i * m.h) * trackHeight;
line.sprite = m.sprite ?? line.sprite;
line.flipX = m.flipX;
//장애물이면 체크
line.isObstacle = m.label.Contains("Obstacle");
}
}
}
}
}
나는 장애물과 플레이어의 충돌처리를 위해 여기서 장애물일 때 1. 에서 추가로 넣어줬던 bool값을 변경해 줬다.
3. 자, 이제 마지막 HqRenderer.cs를 봐보자.
여기서 추가해줘야 할 변수는 1개이다. spriteRenderer로 이전에 만들어 뒀던 스프라이트들을 그려줄 변수를 만들어 주자. 나의 경우 원래 오브젝트들을 그려주고 있던 scale과 장애물 scale의 비율이 달랐기에 장애물 스케일을 관리해 줄 ObstacleScale 변수도 추가해 줬다. scale 문제가 없다면 굳이 추가해 줄 필요가 없다.
변수를 만들어 줬다면 Awake() 함수로 가서 기존 코드와 같은 방식으로 새 스프라이트를 생성해 주자.
아, 이렇게 해주기 전에 유니티에서 ProjectedScene에 빈 오브젝트를 하나 추가해 주고 Sprite Renderer를 컴포넌트로 추가해 주자. sprite는 비워두고 다시 코드로 와서 이렇게 코드를 써주면 유니티로 넘어갔을 때 runtimeObstacle이라는 스프라이트가 연결된 걸 확인할 수 있다. 물론 이 스프라이트에는 아직 아무것도 그려져있지 않는 빈 스프라이트다.
이제 다시 코드로 와서 수정해 주자. drawSprite() 함수에서 매개변수로 Line을 받아오는 걸 보면 여기서 아까 추가해 준 scale을 변경해 주자. 장애물일 경우엔 내가 넣어준 ObstacleScale을 사용해 주고 장애물이 아닐 경우 원래 있던 SpriteScale을 사용해 주자.
그리고 새롭게 DrawObstacle() 함수를 하나 만들어주자. 여기서 장애물을 그려줄 것이다. DrawObjects() 함수와 거의 똑같이 만들어 주면 된다.
처음엔 DrawObjects() 함수에 같이 그려줬다가 충돌처리 오브젝트들을 따로 관리해 주기 위해 변경해 줬다.
만약 또 다른 오브젝트들을 그려줄 때, 충돌처리가 필요 없다면 DrawObject() 함수에서 처리할 것이고, 충돌처리가 필요한 오브젝트라면 DrawObstacle() 함수에서 처리해 줄 것이다.
하나만 기억하면 된다. Track에 추가 해준 Modifier에 label 이름을 충돌 처리 하고 싶은 오브젝트들에만 + "Obstacle" 해주자. 절대 충돌처리가 필요 없는 애들의 이름에는 Obstacle을 써주면 안 된다. 그 이유는 내가 작업한 코드를 보면 이름에 "Obstacle" 이 있는지 없는지만을 확인해서 나눠주기 때문이다.
이제 거의 다 왔다. CheckObstacleCollision() 함수를 만들어 주자. 여기서 충돌 처리를 확인할 것이다. 처음엔 위치값으로 만도 체크를 해봤는데 섬세하게 안 돼서 AABB충돌체크로 충돌 감지를 해봤다.
만약에 충돌이 된다면 OnCollision() 함수를 실행시켜 주고 이 OnCollision() 함수에서 충돌했을 때 해주고 싶은 작업을 해주면 된다.
마지막으로 Update() 함수에서 DrawObstacle() 함수와 CheckObstacleCollision() 함수를 추가해 주면 모든 게 끝이 난다.
화면에 보이는 것처럼 잘 나온다. 굿굿!
아까도 이야기했듯이 다른 오브젝트들도 넣어주고 싶다면 화면처럼 추가해 주면 끝난다.
'유니티' 카테고리의 다른 글
유니티 복권 긁기 기록용 스크립트. 수정중 - 박스 콜라이더 스크립트 (0) | 2024.12.18 |
---|---|
유니티 ) 긁는 복권 게임을 만들어 보자.(scratch game) (2) | 2024.12.13 |
유니티 ) 내 방식대로 만드는 pseudo 3d game 2. (2) | 2024.12.03 |
유니티 ) 내 방식대로 만드는 pseudo 3d game 1. (0) | 2024.11.26 |
유니티에 광고를 넣어보자.(Google AdMob 사용) (4) | 2024.11.09 |