Unity-2D 하향식 게임에서 배를 현실적으로 한 지점으로 옮기는 방법


14

마우스로 클릭 한 지점으로 범선을 옮기려고합니다. 이 움직임은 현실적이어야한다. (선이 움직이는 뒤쪽에서 노를 젓는 것) 마우스 클릭이 왼쪽에 있고 선박의 앞쪽에서 선박은 올바른 회전을하기 위해 곡선으로 이동해야한다.

누군가 가이 문제에 대해 나를 도울 수 있다면 기쁠 것입니다. 감사합니다. 선박 운동


1
당신의 이미지가 돛을 묘사하는 것처럼 보인다 : 바람이 고려되어야 하는가? 일부 기동은 잘못된 바람이나 그 부족과 관련이 없습니다.
아무도

더 많은 지점으로, 사실적인 항해 선박의 움직임이 정말 필요 계정으로 바람을 복용; 그것을 무시하는 것은 점프를 구현할 때 중력을 무시하는 것과 거의 같습니다. 특별히 상세한 바람 모델이 반드시 필요한 것은 아니지만, 배는 항해 중 바람 (그리고 용골과 방향타에 대한 물)에 의해 밀려 가고 있음을 명심해야합니다. 특히, 배는 바로 바람을 타고 항해 할 수 없습니다. 그들은 대신 그들의 길 을 이길 필요가 있습니다.
Ilmari Karonen

일반적으로 "goto point"는 회전 단계와 전진 이동 단계로 나눌 수 있습니다. 동일한 어프로치를 취하되 회전에 전진 이동을가하십시오. 실시 예 회전의 각각의 X는 Y RAD 미터 전방 보트 이동
DNK가 drone.vs.drones

답변:


7

보기 이 페이지를

현실적인 회전 추가

다음 단계는 우리 유닛에 현실적인 곡선 회전을 추가하여 회전해야 할 때마다 갑자기 방향을 바꾸지 않는 것입니다. 간단한 해결책은 스플라인을 사용하여 갑작스러운 모서리를 회전으로 부드럽게하는 것입니다. 이것은 미학적 관심사 중 일부를 해결하지만 여전히 대부분의 부대에서 물리적으로 매우 비현실적인 움직임을 초래합니다. 예를 들어, 탱크의 급격한 코너링을 타이트한 커브로 변경할 수 있지만 커브 턴은 탱크가 실제로 수행 할 수있는 것보다 훨씬 더 타이트합니다.

더 나은 해결책을 위해, 우리가 알아야 할 첫 번째 것은 우리 장치의 회전 반경입니다. 회전 반경은 매우 간단한 개념입니다. 자동차의 큰 주차장에 있고 바퀴를 왼쪽으로 돌리고 원을 그리며 진행하면 원의 반경은 회전입니다. 반지름. 폭스 바겐 비틀의 회전 반경은 큰 SUV의 회전 반경보다 작을 것이며, 사람의 회전 반경은 큰 벌목 곰의 회전 반경보다 실질적으로 작을 것입니다.

그림 5와 같이 특정 지점 (원점)에 있고 특정 방향으로 향하고 있고 다른 지점 (목적지)에 도달해야한다고 가정 해 보겠습니다. 목적지를 직접 향한 다음 앞으로 나아갈 때까지, 또는 우회전하여 같은 일을하면서 원을 그리며 돌 수 있습니다. 그림 5 : 출발지에서 목적지까지의 최단 경로 결정

그림 5에서 가장 짧은 경로는 분명히 하단의 녹색 선입니다. 이 경로는 그림 6과 같이 일부 기하학적 관계로 인해 계산하기가 매우 간단합니다.

그림 6 : 경로 길이 계산

먼저 우리는 회전 원의 중심 인 점 P의 위치를 ​​계산하고 항상 시작점에서 반경 r을 가리 킵니다. 초기 방향에서 우회전하면 P가 원점에서 (initial_direction-90)의 각도에 있음을 의미합니다.

angleToP = initial_direction - 90
P.x = Origin.x + r * cos(angleToP)
P.y = Origin.y + r * sin(angleToP)

이제 중심점 P의 위치를 ​​알았으므로 다이어그램에서 h로 표시된 P에서 대상까지의 거리를 계산할 수 있습니다.

dx = Destination.x - P.x
dy = Destination.y - P.y
h = sqrt(dx*dx + dy*dy)

이 시점에서 목적지가 원 안에 있지 않은지 확인하고 싶습니다.

if (h < r)
    return false

이제 직각 삼각형의 다른 두 변의 길이, 즉 h와 r을 알고 있기 때문에 세그먼트 d의 길이를 계산할 수 있습니다. 직각 관계에서 각도를 결정할 수도 있습니다.

d = sqrt(h*h - r*r)
theta = arccos(r / h)

마지막으로 원을 떠나 직선에서 시작할 점 Q를 알아 내려면 총 각도 +를 알아야하며 P에서 대상까지의 각도로 쉽게 결정됩니다.

phi = arctan(dy / dx) [offset to the correct quadrant]
Q.x = P.x + r * cos(phi + theta)
Q.y = P.y + r * sin(phi + theta)

위의 계산은 우회전 경로를 나타냅니다. angleToP를 계산하기 위해 initial_direction에 90을 추가하고 나중에 + 대신-를 사용한다는 점을 제외하고 왼쪽 경로는 정확히 같은 방식으로 계산할 수 있습니다. 두 가지를 모두 계산 한 후에는 경로가 더 짧은 것을보고 해당 경로를 사용합니다.

이 알고리즘과 다음 알고리즘을 구현할 때, 우리는 최대 4 개의 서로 다른 "선 세그먼트"를 저장하는 데이터 구조를 사용합니다. 각 세그먼트는 직선 또는 곡선입니다. 여기에 설명 된 곡선 경로에는 두 개의 선분 만 사용됩니다 : 호와 직선. 데이터 구조에는 선분이 호인지 직선인지, 선분의 길이 및 시작 위치를 지정하는 멤버가 포함됩니다. 세그먼트가 직선 인 경우 데이터 구조는 각도를 지정합니다. 호의 경우 원의 중심, 원의 시작 각도 및 호로 덮인 총 라디안을 지정합니다.

두 지점 사이를 이동하는 데 필요한 곡선 경로를 계산하면 목록 2와 같이 특정 시점에 위치와 방향을 쉽게 계산할 수 있습니다.

리스팅 2. 특정 시간에서의 위치 및 방향 계산.

distance = unit_speed * elapsed_time
loop i = 0 to 3:
    if (distance < LineSegment[i].length)
        // Unit is somewhere on this line segment
        if LineSegment[i] is an arc
            //determine current angle on arc (theta) by adding or
            //subtracting (distance / r) to the starting angle
            //depending on whether turning to the left or right
            position.x = LineSegment[i].center.x + r*cos(theta)
            position.y = LineSegment[i].center.y + r*sin(theta)
        //determine current direction (direction) by adding or
        //subtracting 90 to theta, depending on left/right
        else
            position.x = LineSegment[i].start.x 
              + distance * cos(LineSegment[i].line_angle)
            position.y = LineSegment[i].start.y
              + distance * sin(LineSegment[i].line_angle)
        direction = theta
        break out of loop
    else
        distance = distance - LineSegment[i].length

4
이 답변은 실제로 선박의 물리학을 조사하지는 않습니다. 또한 그것이 기본적으로 다른 웹 사이트에 대한 링크이며 긴 발췌 부분이라는 것이 문제가 있음을 알았습니다 (적법성이 확실하지 않습니다).
아무도

요청한 질문에 대한 해결책 인 기존 리소스를 마지막으로 제공했을 때 대상 사이트가 중단 된 경우 링크의 내용을 포함하도록 요청했습니다. 이제 내용을 포함하지 말아야합니다. 당신의 마음을 구성하십시오.
Draco18s

3
@ Draco18s : 해야 할 일은 링크 된 자료의 필수 요점을 자신의 말로 요약하는 것입니다. (또는 더 나은 방법은 자신의 경험을 바탕으로 질문에 대답하고 링크를 지원 자료 또는 추가 자료로 사용하는 것입니다.) 짧은 인용 부호는 일반적으로 피할 수없는 상황에서 일반적으로 좋습니다 (예 : 누군가의 정확한 인용문) 그들이 실제로 무언가를 말했음을 입증하는 단어), 기사의 상당 부분을 인용하는 것은 실제로 공정 사용을 넘어서는 입니다.
Ilmari Karonen

점이 원 안에 있으면 조금 나가서 다시 올 수 있습니다.
user253751

(Ps. meta.SE에 대한 두 가지 질문 도 참조하십시오 )
Ilmari Karonen

7

간단한 해결책으로, 이미 언급 했듯이이 aproach를 시도 할 수 있습니다.

선박을 목표 방향으로 향하게하는 단계를 고려하십시오.이 단계에서는 sip에 회전을 적용하지만 앞으로 이동합니다. 선박이 이미 목표를 향하고있는 경우 전진 속도를 적용 할 수 있습니다. 나는 love2d에서 테스트를 준비했다. 여기서는 선박 업데이트 방법을 따른다.

turnAngSpeed = 0.4 --direction changing speed
ForwordSpeed = 40 -- full forward speed
turnForwordSpeed = ForwordSpeed *0.6 -- forward speed while turning
function ent:update(dt)
            dir = getVec2(self.tx-self.x,self.ty-self.y) -- ship --> target direction (vec2)
            dir = dir.normalize(dir) --normalized                               
            a= dir:angle() - self.forward:angle() --angle between target direction e current forward ship vector
            if (a<0) then
             a=a+math.pi *2 -- some workaround to have all positive values
            end

            if a > 0.05 then -- if angle difference 
                if a < math.pi then
                    --turn right
                    self.forward = vec2.rotate(self.forward,getVec2(0,0),turnAngSpeed * dt)
                else
                    --turn left
                    self.forward = vec2.rotate(self.forward,getVec2(0,0),-turnAngSpeed * dt)
                end             
                --apply turnForwordSpeed
                self.x = self.x+ self.forward.x * turnForwordSpeed * dt
                self.y = self.y+ self.forward.y * turnForwordSpeed * dt
            else 
                --applly ForwordSpeed
                self.x = self.x+ self.forward.x * ForwordSpeed * dt
                self.y = self.y+ self.forward.y * ForwordSpeed * dt
            end
end

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

예제 애니메이션은 선회 속도와 전진 속도의 조합이 선회 반경을 너무 크게 정의하기 때문에 선박이 목표에 도달 할 수없는 경우 (최종 루프)를 보여줍니다.이 경우 " turnForwordSpeed"를 줄이거 나 유용 하게 만들 수 있습니다 각도 거리 ( a) 및 목표 거리 에 따라 다릅니다 .


이것은 좋은 대답이지만 OP에 충분히 현실적이거나 현실적이지 않을 수 있습니다. 예를 들어, 자동차와 달리 선박은 실제로 "선회 반경"을 갖지 않습니다. 대부분의 자체 (엔진 / 인간) 동력 선박은 본질적으로 한푼도 돌릴 수 있지만, 범선은 바람에 의존하고 실제로 부정적인 선회가 가능합니다 바람에 좌회전하면 배가 오른쪽으로 표류 할 수 있다는 점에서, 시침시 반경. 어떤 선박 할 수 있는 관성 (드래그)입니다 : 그들은 켜거나 즉시 이동하고, 이동하거나 회전하면, 정지 시간과 힘을 취할 수 없습니다. 여전히 +1이 있습니다.
Ilmari Karonen

대답 해 주셔서 감사합니다!!! :) 당신은 내 영웅입니다!
DavidT

@DavidT 그런 다음 문제를 만족스럽게 해결할 수 있다면 대답을 승인 된 것으로 표시하십시오. :)
MAnd

-2

Unity Nav 메쉬 시스템은 내비 에이전트 값으로 약간의 장난으로 원하는 것을 할 수 있습니다.

Nav Mesh는 사용이 매우 간단합니다. 하향식 설정에서만 사용 가능 (또는 최소한 x / z 이동에만 사용 가능)

네비게이션 메쉬 설정에 대한 Unity 매뉴얼 페이지

기본적으로 모든 모양 메쉬를 사용하여 탐색 영역을 굽고 탐색 에이전트를 객체에 추가하고 탐색 메쉬 주위의 경로를 찾도록 할 수 있습니다


그 점에서도 Draco18s의 대답이 부족하다는 것을 알았습니다. 그러나 귀하의 답변은 실제 답변이 아니며 더 많은 의견입니다.
아무도

2
이것은 좋은 제안이지만 좋은 답변이 되려면 구현에 대한 지원과 정보가 필요합니다. 이에 대한 답을 얻기 위해 탐색 메쉬 구성에 대한 정보를 추가하십시오. 나는의 위의 덧글이 :) 말을 하려는지 생각
sirdank
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.