
#20221212 :: 미니보스패턴 메모
#20221213 :: 에이스타(A*) 패스파인딩
#20221214 :: 패스파인딩 개선
#20221215 :: 타겟 패스파인딩 일반화?
#20221212 :: 미니보스패턴 메모
추가할 기믹
마취총 : 에이스타 소녀 멈추기, 레이저 멈추기, 추격자 멈추기
#20221213 :: 에이스타(A*) 패스파인딩
A* 알고리즘 쉬운 개념 설명
개요그래프/트리 탐색 알고리즘. 게임에서 많이 사용되는 최단거리 길찾기 알고리즘이다.다익스트라 확장판. BFS의 가지치기 알고리즘이라 생각하면 된다. 핵심 개념 1. 최소가 되는 지점을 우선
deliorange.tistory.com
문제 상황
- 새롭게 생성하는 오브젝트들은 movepoint.parent = null을 나중에 해야 함. (start에서 할시 오류)
- EnemyController랑 합치고 싶은데 movepoint.parent = null 처리 때문에 고민.
- 적이 움직일때만 턴 지나는 거 계산됨 (아래 내용 때문)
if(isMoving && transform.position == movePoint.position){
Debug.Log("끝");
isMoving = false;
level.playerTurn = true; // 여기에는 코루틴 적용 x
}
적이 움직일 수 없다면(transform.position == movePoint.position 상태라서)
위 코드가 바로 실행되고 level.playerTurn = true 가 돼버림.
if (!level.playerTurn && !isActing){
/* 보스 패턴을 여기에 입력해 주세요~ 0u0 */
//////////////
spikeLaunchCount.text = "" + (FIXED_COUNT - int.Parse(turnCount.text) % FIXED_COUNT);
isActing = true;
/////////////
}
따라서 level.playerTurn 에 걸리므로 턴 지나가는 걸 반영하는 이 부분이 실행 안됨..
해결책
- level.playerTurn = true로 만드는 구문을 변경한다.
- 적이 움직일 수 없는 상태를 만들지 않는다. (항상 움직이도록)
#20221214 :: 패스파인딩 개선
문제상황
패스파인딩 도중에는 이동제한구역(limitArea)의 영향을 받지 않는다.
패스파인딩 스크립트는 내비게이션(start부터 end까지에 대한 모든 경우의 수를 고려하여 최적의 결과를 도출)
역할도 수행하기 때문에 enemy컨트롤러에서 처리하기에는 곤란하다. (내비게이션은 적용이 안되기 때문)
패스파인딩 스크립트 내부에서 처리할 수 있는 방법이 없을까?
요약 : 내비게이션을 결정할 때부터 이동제한구역의 영향을 받았으면 좋겠다.
해결과정
1. PathNode에 이동제한방향 Vector3[] 추가
- 이동제한구역 MovementLimit GameObject
- 이동제한(구역의) 방향 Vector3[]
public int limitValue; // 해당 노드가 제한구역이 아니면 0 으로 초기화
public Vector3[] limitArea;
2. 레벨 시작 시 LevelBase에서 GridBase에 접근하여 이동제한구역 초기화
Collider2D hit;
if (hit = Physics2D.OverlapCircle(new Vector3(x - 1, y - 1, 0f), .2f, whatMovementLimit))
{
levelGrid.SetLimitArea(x, y, hit.GetComponent<MoveLimit>().moveLimitAreas);
}
이 부분에서 처음에는 RayCast를 사용했는데 하필이면 whatStopMovement 랑 겹쳐서 잘 인식이 안 되는 문제가 발생.
RayCastAll 써서 람다식으로 limit 부분만 선별하고 쌩쇼했는데 IndexNullPointerError 이슈 발생.
결국 whatMovementLimit를 추가하는 방향으로 고쳤음.
생각해 보니 그럼 RayCast 쓸 필요가 없어서 걍 Physics2D 씀.
- 레이어마스크 MovementLimit 추가 (태그는 없앨 수도)
public void SetLimitArea(int x, int y, Vector3[] limitAreas){
if (x >= 0 && y >= 0 && x < width && y < height)
{
gridArray[x, y].limitArea = limitAreas;
gridArray[x, y].limitValue = limitAreas.Length;
CreateWorldText(gridArray[x, y].limitValue.ToString(), null, GetWorldPosition(x, y) + new Vector3(cellSize, cellSize) * .5f + new Vector3(.3f, .3f), 40, Color.cyan, TextAnchor.MiddleCenter);
}
}
- CreateWorldText 부분은 이동제한방향의 개수를 시각화 (그리드 셀의 오른쪽 상단)
3. AStarPathFinding의 GetNeighbourList()에서 이동제한구역 처리
- 이웃노드를 결정하는 부분이므로 닫힌 구역으로 바로 들어가는 건 아니다.
- 따라서 해당 위치에서만 이동제한을 하는 것에 적합하다.
if(currentNode.limitValue != 0){ // 이동제한 구역 처리
foreach(var i in currentNode.limitArea){
if(currentNode.x + (int)i.x >= 0 && currentNode.x + (int)i.x < grid.width
&& currentNode.y + (int)i.y >= 0 && currentNode.y + (int)i.y < grid.height){
neighbourList.Add(GetNode(currentNode.x + (int)i.x, currentNode.y + (int)i.y));
}
}
}
- foreach로 이동제한방향을 순회한다. (나중에 이동제한방향의 개수가 많아지는 것에 대해 일반화)
- 현재 노드위치 + 이동제한방향이 그리드를 이탈하지는 않았는지 체크
- 문제없다면 이웃노드리스트에 Add
결과
내비게이션 파트에서도(이동 방향 결정을 포함하여) 이동제한구역이 잘 적용된다.~~ 문제해결!
남은 미션
이동제한구역을 PathNode에 업데이트했으므로 그동안의 플레이어와 enemy의 이동제한구역 처리를 개선할 필요성.
#20221215 :: 타겟 패스파인딩 일반화?
레벨 움짤들
문제 상황
<미러모드 만들던 도중>
플레이어가 아닌 타겟의 postPostion(미래의 위치로 예상)을 어떻게 패스파인딩하면 좋을까?
해결 방법들
- 플레이어의 이동거리를 받아서 타겟의 postPostion을 계산.
- 단, 타겟이 플레이어의 미러모드임.
- 플레이어는 이동가능하나 타겟이 이동불가능한 경우가 있음.
이때는 플레이어의 이동거리를 본뜬 postPosition에서 오류가 발생. 패스파인딩 실패. - 따라서 폐기.
- 타겟에서 미리 계산된 postPostion을 받아와서 패스파인딩.
- 아직 안 해봄 ㅎㅎ.
추가 문제
- 플레이어가 MoveLimit 상태일 때 enemy가 MoveLimit 따라 하는 거 멈춰!!!
- 플레이어 : 사차선 → 대각선 일 때 enemy가 대각선으로 움직임;;
(패스파인딩은 다행히 멀쩡하게 움직임 따라서 enemy 만 항상 사차선으로 움직이도록 수정하면 됨.)
- 플레이어 : 사차선 → 대각선 일 때 enemy가 대각선으로 움직임;;
- enemy와 패스파인딩 충돌문제
- enemy가 피해야 하는 조건에 패스파인딩 객체를 추가?
'개인 프로젝트 > Node Princess' 카테고리의 다른 글
Node Princess :: 개발일지 #9 - 터미널 구현 (4) (0) | 2024.02.16 |
---|---|
Node Princess :: 개발일지 #8 - 터미널 구현 (3) (0) | 2024.02.16 |
Node Princess :: 개발일지 #6 - 캐릭터 컨셉 (0) | 2024.02.16 |
Node Princess :: 개발일지 #5 - 터미널 구현 (2) (1) | 2024.02.16 |
Node Princess :: 개발일지 #4 - 터미널 구현 (1) (1) | 2024.02.15 |
틀린 부분은 언제든지 말씀해주세요!!! 감사합니다!