모바일이 다른 것을 둘러싸 기 위해 어떤 종류의 조향 동작 또는 로직을 사용할 수 있습니까?


10

내 게임에서 경로 찾기를 사용하여 폭도를 다른 플레이어에게 이끌고 있습니다. 이것은 플레이어의 꼭대기에 오게하기 위해 작동하지만 목적지보다 약간 전에 멈추기를 원합니다 (따라서 두 번째 노드를 선택하는 것이 좋습니다).

그러나, 여러 몹이 모바일을 추구 할 때 때때로 "서로 쌓이게"됩니다. 이것을 피하는 가장 좋은 방법은 무엇입니까? 나는 폭도들을 불투명하게 취급하고 싶지 않고 (왜냐하면 당신이 걸을 수 없기 때문에) 폭도들이 어떤 구조적 감각을 갖기를 원합니다.

예:

각 뱀이 저를 안내하고 "Setsuna"를 둘러싸고 있다고 상상해보십시오. 두 뱀이 어떻게 나를 갈래로 선택했는지 주목하십시오. 이것은 엄격한 요구 사항이 아닙니다. 약간 상쇄되는 것도 괜찮습니다. 그러나 그들은 Setuna를 둘러싼 다.

여기에 이미지 설명을 입력하십시오


1
스태킹은 목적지 또는 운송 중에 만 문제가됩니까? 후자를 추측하고 있습니다.
스파르타 도넛

후자는 @SpartanDonut
Vaughan

@KromStern 사진을 추가했는데 도움이 되길 바랍니다.
Vaughan Hilts

답변:


15

쿨롱의 법칙에 따라 서로 대항 할 수 있도록 약에 "정전기 전하"를 부여하십시오 .

폭도 동등한 강도가 서로 멀리 밀어한다고 가정 간략화를 위해, 그 크기와 군중의 각 쌍 사이에 힘을인가하기에 충분해야한다 some_constant / distance^2, some_constant구성 반발 강도 및 distance그들을 분리 거리이다.

그런 다음 거리의 제곱에 따라 반발 강도가 떨어집니다.

Code of Nature는 (실시간 데모와 함께) 훌륭한 예가 있습니다 . 다음과 같이 보입니다 :

결합 된 후속 행동과 분리 된 행동

모든 요소를 ​​서로 비교하는 것은 2 차 시간 ( O(n^2)) 연산입니다. 실제로 에이전트 가 많은 경우 Barnes-Hut 근사법을 사용하여 힘 계산을 최적화 할 수 있습니다. Barnes-Hut approximation 은 log-linear ( O(n log n)) 로 내려가 지만 quadtree 가 필요합니다 .


훌륭한 연결, Anko. 매우 감사! 나는이 사이트 전체를 다시 읽어보아야 할 것이다.
Vaughan Hilts

스타 크래프트 (1 이상)는 비행 유닛과 비슷한 것을한다. 그러나 그것은 그들이 움직이지 않을 때, 즉 그들이 움직일 때 서로 뭉치 게합니다 (완벽히 서로를 장애물로 무시합니다). 그러나 그들이 멈 추면 그들은 모두 보이는 것처럼 퍼지기 시작합니다. 그것들을 포함하는 일정한 지역 (아마도 사각형 / 원형)의 지역 중심. 이것은 대답의 예처럼보기에는 좋지 않지만 CPU 리소스를 덜 사용하고 코딩하기도 더 쉬울 것입니다.
Shivan Dragon

@ShivanDragon SC2는 동일한 행동을 나타내며 모두 군중으로 목적지로 수렴 한 다음 현실적이고 친밀감이있는 외모를 위해 공간을 확보합니다 (따라서 부품이 잘리지 않음).
Kroltan

2
어떤 종류의 반발력은 좋은 생각이 될 수 있지만 세부 사항은 까다 롭습니다. 나는 우주 테마 RTS에서 이것들을 실험했고 물리학을 너무 세밀하게 따르지 않고 모델링하는 것이 좋습니다. 몇 가지 관찰 사항 : 1) 이것은 물리 시뮬레이션이 아니기 때문에 단거리에서만 힘을 가할 것입니다. 2) 이것은 유한 체가 겹치는 것을 막을 수 없습니다. 3) 단단한 전위는 입자가 높은 속도로 굴절되는 등의 수치 오류를 쉽게 유발합니다. 4) 중간에 상당한 수의 입자와 압력이 생기면 상황이 추악 해지는 경향이 있습니다.
코드 InChaos

1

내 접근 방식은 @Anko와 비슷하지만 인공 지능 게임의 Millington and Funge의 작업을 기반으로합니다 .

이는 분리 동작의 모습이지만 업데이트 속도에서 에이전트 속도로이 속도를 계산해야한다는 점을 고려해야합니다.

public Vector3 GetSeparationVel (float threshold, float decayCoefficient)
{
    threshold = threshold * threshold;
    Vector3 separationVelocity = Vector3.Zero;
    for (int i = 0; i < enemies.Length; i++) {
        if (enemies[i] == this) {
            continue;
        }
        Vector3 direction = this.position - enemies[i].position;
        float distance = direction.LengthSquared();
        float strenght = 0.0f;
        if (distance < (threshold)) {
            strenght = Math.Min(decayCoefficient / distance, this.maxAccel);
            direction.Normalize();
            separationVelocity += strenght * direction;
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.