유니티 엔진/Fortress Craft
[Fortess Craft] Path Finding
라구넹
2025. 2. 5. 20:47
맵이 간단해서 굳이 벨만 포드 등의 길찾기 알고리즘을 쓸 필요가 없음
이렇게 생긴 맵이고, 유닛은 가운데에 있는 지역을 움직임
가운데애 X 형태의 다리를 건너도록 패스 파인딩을 하면 됨
=> 중간에 지점을 하나 넣어주기
정확히 문제가 되는 상황은 무엇이냐?
위 이미지처럼 다리 위에서 타겟 세팅을 바꾸는 경우임
특정한 지역 (A, B, C, D) 위에선 바뀌어도 상관이 없음
어차피 바로 연결되어 갈 수 있기 때문
하지만 다리 위에서는 일직선 상으로 갈 수가 없음
⇒ middlePoint를 두고, 현재 유닛 위치를 기준으로 가장 가까운 지역으로 가서
그곳에서 목표지점으로 다시 이동하게 만들면 됨
두번째 문제: 가운데 교차하는 다리에서는 어떻게 움직일 것이냐?
교차 지점의 다리에서 middlePoint 지정을 잘못하면 오히려 꼬일 수도 있고,
그냥 가운데 교차 지점으로 이동하고 목표 지점으로 이동하는게 빠름
⇒ middlePoint를 가운데 교차 지점 (name: center)으로 설정하면 됨
구현
public void Initializing()
{
if (initialized)
{
if( TargetString != Spawner.Target ) // 타겟 변경됐는데 다리 위
{
if( nowGround == "Bridge" )
{
float minDist = GetDistanceXYSquared(grounds[0]);
int idx = 0;
for (int i = 1; i < 4; ++i)
{
float tempDist = GetDistanceXYSquared(grounds[i]);
if (tempDist < minDist)
{
minDist = tempDist;
idx = i;
}
}
middlePoint = grounds[idx];
}
else if( nowGround == "CrossBridge" )
{
middlePoint = Spawner.Center;
}
}
// RPC Properties
TargetString = Spawner.Target;
AttackEnabled = Spawner.AttackEnabled;
Damage = Spawner.Damage;
Defense = Spawner.Defense;
}
TargetGround = "Ground_" + TargetString;
TargetUnit = "Unit_" + TargetString;
initialized = true;
}
Initializing 함수에서 TargetString을 변경하기 전에 변경점이 있는지 우선 체크
만약 변경점이 있는데(타겟이 변경됨) 유닛이 다리 위라면 middlePoint 설정을 해주어야 함
일반 다리 위라면 middlePoint를 위해 거리를 재고,
교차하는 다리 위라면 middlePoint를 center로 설정
센터는 이거
private void MoveToTarget()
{
Transform targetGround;
if( middlePoint == null )
{
if (TargetGround.CompareTo("Ground_A") == 0)
{
targetGround = grounds[0];
}
else if (TargetGround.CompareTo("Ground_B") == 0)
{
targetGround = grounds[1];
}
else if (TargetGround.CompareTo("Ground_C") == 0)
{
targetGround = grounds[2];
}
else
{
targetGround = grounds[3];
}
if (TargetGround.CompareTo(nowGround) == 0)
{
_rb.Rigidbody.velocity = Vector2.zero;
return;
}
}
else
{
targetGround = middlePoint;
}
if( Mathf.Sqrt( GetDistanceXYSquared(targetGround) ) < 0.3f )
{
if( middlePoint == null )
{
_rb.Rigidbody.velocity = Vector2.zero;
return;
}
else
{
middlePoint = null;
return;
}
}
Vector3 movDir = targetGround.position - transform.position;
Vector3 movDirNormalized = movDir.normalized;
_rb.Rigidbody.velocity = movDirNormalized * testSpeed;
if (movDir.x > 0)
{
transform.localScale = new Vector3(-1.0f, transform.localScale.y, transform.localScale.z);
}
else
{
transform.localScale = new Vector3(1.0f, transform.localScale.y, transform.localScale.z);
}
}
움직임 구현 부분에서는 middlePoint가 비어있지 않으면 타겟을 middlePoint로 하게 만듦