VioletaBabel
66. 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(7, 75);//현재 웨이포인트를 임시로 넣었다. if (ThePlayer.gridX != nowWayPoint.x || ThePlayer.gridZ != nowWayPoint.y) {//최종 목적지가 지금의 내 위치와 일치하지 않는다 nowPath = TheAStar.Move(ThePlayer.gridX, ThePlayer.gridZ, 7, 75);//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