VioletaBabel

66. A*를 응용한 이동 본문

BCA/4. Unity
66. A*를 응용한 이동
Beabletoet 2018. 8. 14. 17:20

유니티 A* 글



현재 위치에서 목적지까지 A* 경로를 만든 후, 목적지에 가까운 그리드부터 하나씩 현 위치까지 선을 긋는다. 그 선 위에 존재하는 그리드들 중 장애물이 있을 경우 검사한 그리드를 출발지에 가까워지게 1칸 움직여 다시 선을 그으며 검사하고, 장애물이 없는 경우에는 그 그리드까지만 직선 운동 후 다시 검사를 시작한다.
이동 시 추가적인 보간은 넣지 않았기에 움직임이 부드럽지 않음. 보간은 알아서 나중에 넣자.




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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//이건 A*를 하는 각 캐릭터가 가지는 파일에 속해야 함. 그리고 전에 올린 A* 유니티 포스팅의 스크립트가 필요.
    public bool knowPath = false;
    public List<GridData> nowPath;
    public Vector3 DepVec;
 
    private void LateUpdate()
    {
        if (knowPath) // 이미 갈 곳을 안다
        {
            if (Vector3.Distance(transform.position, DepVec) > 0.2f)
            {//ㄱㄱ
                Vector3 arrow = (DepVec - transform.position).normalized;
                transform.position += arrow * 0.2f;
            }
            else
            {//도착했으면 다시 길 모르는 상태로 돌린다
                knowPath = false;
            }
        }
        else
        {
            Vector2 nowWayPoint = new Vector2(775);//현재 웨이포인트를 임시로 넣었다.
            if (ThePlayer.gridX != nowWayPoint.x || ThePlayer.gridZ != nowWayPoint.y)
            {//최종 목적지가 지금의 내 위치와 일치하지 않는다
                nowPath = TheAStar.Move(ThePlayer.gridX, ThePlayer.gridZ, 775);//AStar 실행(전 포스팅 관련)
                for (int i = 0; i < nowPath.Count; ++i)
                {
                    bool collectWay = false;
                    bool first = true;
                    Vector3 v = (nowPath[i].transform.position - nowPath[nowPath.Count - 1].transform.position).normalized;
                    RaycastHit[] r = Physics.BoxCastAll(nowPath[nowPath.Count - 1].transform.position, new Vector3(0.001f, 0.001f, 0.001f),
                        v, Quaternion.identity, Vector3.Distance(nowPath[nowPath.Count - 1].transform.position,
                        nowPath[i].transform.position));//박스캐스트로 직선으로 갈 수 있는 곳은 직선 이동 하도록 함
                    DepVec = transform.position;
                    foreach (RaycastHit hit in r)
                    {
                        if (hit.collider.name.Equals("Grid(Clone)"))
                        {
                            transform.DOLookAt(hit.collider.transform.position, 0);
                            GridData._type t = hit.collider.GetComponent<GridData>().type;
                            if (t.Equals(GridData._type.obstacle))
                            {//길 틀림
                                collectWay = false;
                                break;
                            }
                            if (hit.transform.position.Equals(nowPath[i].transform.position))
                            {//길 맞음
                                collectWay = true;
                                DepVec = hit.transform.position;//갈 곳 저장
                                break;
                            }
                        }
                    }
                    if (collectWay)
                    {//길을 안다고 표시
                        knowPath = true;
                        break;
                    }
                    else if (i.Equals(nowPath.Count - 1))
                    {//길을 모르고 검사도 다 함. 대각선 이동 시 사각형 그리드에 걸리는 문제 해결을 위해 길이 남았는데 안가면 한 칸 움직여줌
                        int tempX = 0, tempZ = 0, gridNum = nowPath[0].gridNum;
                        int depGridX = gridNum % MakeGrid.instance.gridMaxX, depGridZ = gridNum / MakeGrid.instance.gridMaxZ;
                        if (depGridX > ThePlayer.gridX)
                        {
                            ++tempX;
                        }
                        else if (depGridX < ThePlayer.gridX)
                        {
                            --tempX;
                        }
                        if (depGridZ > ThePlayer.gridZ)
                        {
                            ++tempZ;
                        }
                        else if (depGridZ < ThePlayer.gridZ)
                        {
                            --tempZ;
                        }
                        if (tempZ != 0 && tempX != 0)
                        {
                            knowPath = true;
                            DepVec = MakeGrid.instance.GridList[(ThePlayer.gridZ + tempZ) * MakeGrid.instance.gridMaxX
                                + (ThePlayer.gridX + tempX)].transform.position;
                            break;
                        }
                        else
                        {//다음 웨이로 갱신을 넣어야 함. 이건 웨이포인트를 정하고 해야하니 보류
 
                        }
                    }
                }
            }
        }
    }
cs


'BCA > 4. Unity' 카테고리의 다른 글

69. Unity 팁 1  (0) 2018.11.21
67. Model View Controller 1 - SendMessage  (0) 2018.11.20
65. A* (유니티)  (0) 2018.08.13
54. Shader  (0) 2018.07.16
47. 네모로직+지뢰찾기  (0) 2018.06.21
Comments