로그라이크 게임 제작 05

로그라이크 게임 제작 05

Summary 무한 맵 구현을 위한 C# 코드와 알고리즘을 설명하며, 플레이어의 위치에 따라 맵 프리팹을 재배치하는 방법을 다룹니다. 플레이어와 프리팹 간의 거리 차이를 계산하여 특정 조건을 만족할 때 프리팹을 이동시키는 로직이 포함되어 있습니다.


참고 코드

 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
//Reposition.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Reposition : MonoBehaviour
{
    //트리거가 체크된 콜라이더를 벗어났을때
    //이를 위해 플레이어에 Area를 만들었다 (충돌여부를 확인하기 위해)
    void OnTriggerExit(Collider collision)
    {
        //이 콜라이더의 주인
        //만약 Area태그가 아닌다면 코드를 실행하지 않겠다 라는 뜻
        if(!collision.CompareTag("Area"))
        {
            Debug.Log("Area태그 아님");
            return;
        }
        //거리를 구하기 위해 플레이어 위치와 타일맵 위치를 미리 저장
        
        //플레이어 위치
        //플레이어 포지션을 가져오기위해 게임매니저에 저장해둔 플레이어에서 위치값을 가져오는 과정
        Vector3 playerPos = GameManager.instance.player.transform.position;
        
        //타일맵 위치
        //현재 이 스크립트가 들어있는 타일맵의 위치값
        Vector3 myPos = transform.position; 
        
        //x축과 z축 각각의 거리를 구하는 코드
        //Mathf 는 수학 라이브러리.. 절대값을 구하기 위해 Abs를 불러옴
        float diffX = Mathf.Abs(playerPos.x - myPos.x);
        float diffZ = Mathf.Abs(playerPos.z - myPos.z);


        //플레이어의 이동 방향을 저장하기 위한 변수
        //플레이어에서 미리 만들어뒀던 inputVec을 불러온다
        Vector3 playerDir = GameManager.instance.player.inputVec;
        //Player에서 노멀라이즈를 했기때문에 1값이 안나오니 0보다 클때(좌우 이동할때) 값을 받아온다 
        float dirX = playerDir.x < 0 ? -1 : 1;
        float dirZ = playerDir.z < 0 ? -1 : 1;

        //나중에 적이 추가되었을때 적들도 재배치를 요구하기때문에 여기서 필터를 만들어준다
        switch (transform.tag)
        {
            case "Ground":
                if (diffX > diffZ)
                {
                    //Translate : 지정된 값 만큼 현재 위치에서 이동한다
                    //Translate(이동방향,플레이어방향,Area의크기,)
                    //40을 곱해준 이유는 Tilemap을 4개 복사해서 쓸거기 때문에 타일맵의 총 합을 구하면 40이된다
                    transform.Translate(Vector3.right * dirX * 40);
                }
                else if (diffX < diffZ)
                {
                    transform.Translate(Vector3.right * dirX * -40);
                }
                break;
            case "Enemy":
                break;
        }
    }
}

알고리즘

  1. 맵 프리팹은 총 0.1,2,3,4 즉 5개 시작은 2
  2. 0 = ( -40 , 0 )
  3. 1 = ( -20 , 0 )
  4. 2는 ( 0 , 0 )
  5. 3 = ( +20 , 0 )
  6. 4 = ( +40 , 0 )
  7. 현재 플레이어와 abs(60) 이상 차이날 경우 격차가 벌어진 프리팹을 플레이어의 이동 방향 + 100 만큼 이동시킴
  8. 플레이어가 이동방향으로 20 이상 이동헀을경우 가장 먼 프리팹에 abs(100) 을 더함
  9. 플레이어의 방향 x축 + ( (1 or -1) * abs(100)) | | | | Player | | | | | | 0 | 1 | 2 | 3 | 4 | | | | -40 , 0 | -20 , 0 | 0 , 0 | 20 , 0 | 40 , 0 | |

| | Move | | | Player | | +100 | | | 0 | 1 | 2 | 3 | 4 | 0 | | | -40 , 0 | -20 , 0 | 0 , 0 | 20 , 0 | 40 , 0 | 60,0 |

  1. (해당 알고리즘 다)플레이어의 위치를 기준으로 가장 멀리있는 (플레이어 위치 - 프리팹의 위치) 가
  2. 양수일 경우 (플레이어 방향은 +1)
  3. 음수일 경우 (플레이어 방향은 -1)

프리팹이 플레이어와 60 이상 거리가 차이나면 그 프리팹은 이동방향(1 , -1) * 100 을 함

구현 코드

 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
//Reposition.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Reposition : MonoBehaviour
{

    public Transform groundSize;

    void Update() 
    {
        moveMap();
    }
    //트리거가 체크된 콜라이더를 벗어났을때
    //이를 위해 플레이어에 Area를 만들었다 (충돌여부를 확인하기 위해)
    void moveMap()
    {
        //프리팹의 크기를 자동으로 계산
        Vector3 mapSize = groundSize.transform.localScale;

        // ... 거리를 구하기 위해 플레이어 위치와 타일맵 위치를 미리 저장
        
        //플레이어 위치
        //플레이어 포지션을 가져오기위해 게임매니저에 저장해둔 플레이어에서 위치값을 가져오는 과정
        Vector3 playerPos = GameManager.instance.player.transform.position;
        
        //타일맵 위치
        //현재 이 스크립트가 들어있는 타일맵의 위치값
        Vector3 tilePos = transform.position; 

        //x축과 z축 각각의 거리를 구하는 코드
        //Mathf 는 수학 라이브러리.. 절대값을 구하기 위해 Abs를 불러옴
        float diffX = Mathf.Abs(playerPos.x - tilePos.x);

        //플레이어의 이동 방향을 저장하기 위한 변수
        //플레이어에서 미리 만들어뒀던 inputVec을 불러온다
        Vector3 playerDir = GameManager.instance.player.inputVec;
        //Player에서 노멀라이즈를 했기때문에 1값이 안나오니 0보다 클때(좌우 이동할때) 값을 받아온다 
        float dirX = playerDir.x < 0 ? -1 : 1;

        //일정거리 이동했을때 플레이어에서 가장 먼 프리팹을 플레이어 방향으로 이동
        if (diffX >= (mapSize.x * 3))
            transform.Translate(Vector3.right * dirX * (mapSize.x * 5));
    }
}
  1. groundSize를 전역변수로 설정하여 이 코드를 가지고있는 객체의 mapsize에따라 코드가 작동하도록 변수로 설정했음
  2. 기존 콜라이더 방식에서 update 함수방식으로 변경함

💬 댓글

GitHub 계정으로 로그인하여 댓글을 남겨보세요. GitHub 로그인

🔧 댓글 시스템 설정이 필요합니다

GitHub Discussions 기반 댓글 시스템을 활성화하려면:

  1. Giscus 설정 페이지에서 설정 생성
  2. GISCUS_SETUP_GUIDE.md 파일의 안내를 따라 설정 완료
  3. Repository의 Discussions 기능 활성화

Repository 관리자만 설정할 수 있습니다. 설정이 완료되면 모든 방문자가 댓글을 남길 수 있습니다.