2.5d 어드벤쳐 게임은 제 취미를 위해 만드는 것고 전문적으로 만드는 것이 아닙니다.
그래서 아래의 내용 중 간혹 틀린내용이나 실무적이지 않은 내용도 포함될 수도 있습니다.
현재 2.5d 어드벤처 게임을 만드는 중입니다. 게임을 제대로 만들기 전 타일맵, 플레이어 행동, 애니메이션, 아이템, 대화 등을 먼저 구현하고 진행할 생각입니다.
위쪽 사진과 같이 만들었는데, 오늘은 벽 뒤에 갔을 때 플레이어가 안 보이는 것을 구현했습니다.
현재 저는 3차원 스프라이트에 2차원 타일맵을 이용하고 있어서, 원래라면 플레이어 y좌표를 이용하면 되는 것을 따로 스크립트를 작성해서 구현해야 했습니다. (아니면 방법이 있는데 제가 찾지 못한 것일 수도 있습니다.) ( 2차원+3차원 구조로 해도 되는 건지 잘 모르겠지만, 안 될 이유도 찾지 못해서 이렇게 계속 계발해보려고요.)
카메라는 \(z = -100\)에 위치해 있고 플레이어는 \(z = -20\)에 위치해 있기 때문에, 가리는 효과를 주기 위해서는 타일맵이 \(-100<z<-20\) 사이로 이동해야 합니다. 그래서 플레이어의 발의 y좌표가 타일맵의 y좌표보다 크다면 타일맵의 z값을 -50하는 식으로 만들었습니다. 이때 그림에서 볼 수 있듯이 원하는 결과는 세로로 쌓여 있는 벽돌이 모두 플레이어를 가릴 수 있게 해야 했기 때문에, \((x+y+z)/4\)를 이용해서 3개의 타일이 마치 한 점에 있는 것으로 간주하여 계산했습니다.(현재 z 값은 음수이므로 더해주는 것입니다.)
아래 사진처럼 벽이 z방향으로 -50만큼 이동해서 플레이어를 가린 것을 확인할 수 있습니다.
* 오늘 알게 된 공식 : 타일맵 \(y\)좌표 \( = (x+y-|z|)/4\)
|소스코드|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using System;
public class CoverableTileBehavior : MonoBehaviour
{
Player player;
Transform playerTr;
Tilemap coverableTilemap;
GridLayout gridLayout;
public TileBase tilebase;
// <tile y pos(world),tile position(tile)>
private List<Tuple<float, Vector3Int>> tilePosition;
// 음수로 적용됨. 실제로 -50을 기준으로 작동함.
public int threshold = 50;
// Start is called before the first frame update
void Start()
{
tilePosition = new List<Tuple<float, Vector3Int>>();
player = GameObject.Find("Player").GetComponent<Player>();
playerTr = player.transform;
coverableTilemap = GameObject.Find("Coverable Tilemap").GetComponent<Tilemap>();
gridLayout = coverableTilemap.layoutGrid;
for (int x = coverableTilemap.cellBounds.min.x; x < coverableTilemap.cellBounds.max.x; x++)
{
for (int y = coverableTilemap.cellBounds.min.y; y < coverableTilemap.cellBounds.max.y; y++)
{
for (int z = coverableTilemap.cellBounds.min.z; z < coverableTilemap.cellBounds.max.z; z++)
{
var tile = coverableTilemap.GetTile(new Vector3Int(x, y, z)); ;
if (tile != null)
{
tilePosition.Add(new Tuple<float, Vector3Int>((float)(x + y + z) / 4, new Vector3Int(x, y, z)));
}
}
}
}
}
// requires optimization
private void LateUpdate()
{
float playerHPostion = playerTr.position.y;
for (int i = 0; i < tilePosition.Count; i++)
{
Tuple<float, Vector3Int> entry = tilePosition[i];
Vector3 tileworldpos = gridLayout.CellToWorld(entry.Item2);
if (entry.Item1 > playerHPostion && tileworldpos.z <= -threshold)
{
coverableTilemap.SetTile(entry.Item2 + new Vector3Int(0, 0, threshold), coverableTilemap.GetTile(entry.Item2));
coverableTilemap.SetTile(entry.Item2, null);
tilePosition[i] = new Tuple<float, Vector3Int>(entry.Item1, new Vector3Int(0, 0, threshold) + entry.Item2);
}
else if (entry.Item1 < playerHPostion && tileworldpos.z > -threshold)
{
coverableTilemap.SetTile(entry.Item2 + new Vector3Int(0, 0, -threshold), coverableTilemap.GetTile(entry.Item2));
coverableTilemap.SetTile(entry.Item2, null);
tilePosition[i] = new Tuple<float, Vector3Int>(entry.Item1, new Vector3Int(0, 0, -threshold) + entry.Item2);
}
}
}
}
조금 코드를 최적화하지 않아서 나중에 성능이 안 좋으면 고칠 예정입니다.
'개발 > [C#] Unity' 카테고리의 다른 글
[Unity] RPG 대화 구현 (csv 이용) (0) | 2022.09.07 |
---|---|
[Unity] 2.5d 어드벤쳐 게임 #개발일지 2022/09/06 (0) | 2022.09.06 |