Unity - Cách di chuyển một con tàu thực tế đến một điểm trong trò chơi từ trên xuống 2D


14

Tôi đang cố gắng di chuyển một chiếc thuyền buồm đến điểm mà tôi đã nhấp bằng chuột. chuyển động này phải thực tế (oar ở phía sau nơi con tàu di chuyển xung quanh) vì vậy nếu nhấp chuột trái và ở phía trước con tàu, sau đó tàu sẽ di chuyển đến đó với một đường cong để có vòng quay đúng

Tôi rất vui nếu ai đó có thể giúp tôi về vấn đề này cảm ơn chuyển động tàu


1
Như hình ảnh của bạn dường như mô tả những cánh buồm: Có nên tính đến gió? Một số thao tác là không thể làm với gió sai hoặc thiếu nó.
Không ai

Quan trọng hơn, phong trào tàu thuyền thực tế đòi hỏi phải tính đến gió; bỏ qua nó sẽ gần giống như bỏ qua trọng lực khi thực hiện nhảy. Bạn không nhất thiết cần một mô hình gió đặc biệt chi tiết, nhưng bạn cần lưu ý rằng tàu của bạn đang bị gió đẩy xung quanh (và nước chống lại keel và bánh lái của chúng). Cụ thể, tàu không thể đi ngược gió; thay vào đó họ sẽ cần phải đánh bại họ.
Ilmari Karonen

Thông thường, một "điểm goto" có thể được chia thành pha quay và pha chuyển động về phía trước. Thực hiện cùng một aproach nhưng áp đặt cho xoay một chuyển động về phía trước. Ví dụ mỗi x rad quay di chuyển về phía trước thuyền mét y
DNK drone.vs.drones

Câu trả lời:


7

Xem trang này

Thêm lượt thực tế

Bước tiếp theo là thêm các đường cong cong thực tế cho các đơn vị của chúng tôi để chúng không xuất hiện thay đổi hướng đột ngột mỗi khi chúng cần rẽ. Một giải pháp đơn giản liên quan đến việc sử dụng một spline để làm mịn các góc đột ngột thành các lượt. Trong khi điều này giải quyết một số mối quan tâm thẩm mỹ, nó vẫn dẫn đến chuyển động vật lý rất không thực tế cho hầu hết các đơn vị. Ví dụ, nó có thể thay đổi một góc đột ngột của một chiếc xe tăng thành một đường cong chặt chẽ, nhưng khúc cua cong vẫn sẽ chặt hơn nhiều so với chiếc xe tăng thực sự có thể thực hiện.

Để có giải pháp tốt hơn, điều đầu tiên chúng ta cần biết là bán kính quay vòng cho đơn vị của chúng tôi. Bán kính quay vòng là một khái niệm khá đơn giản: nếu bạn đang ở trong một bãi đậu xe lớn trong xe của mình và xoay bánh xe sang trái theo hướng nó sẽ đi và tiến tới lái xe trong một vòng tròn, bán kính của vòng tròn đó là vòng quay của bạn bán kính. Bán kính quay vòng của một chiếc Beetle của Volkswagen sẽ nhỏ hơn đáng kể so với một chiếc SUV lớn, và bán kính quay vòng của một người sẽ thấp hơn đáng kể so với một con gấu lớn, gỗ.

Giả sử bạn đang ở một điểm nào đó (điểm gốc) và chỉ theo một hướng nhất định, và bạn cần đến một điểm khác (đích), như minh họa trong Hình 5. Con đường ngắn nhất được tìm thấy bằng cách rẽ trái theo bạn có thể, đi theo vòng tròn cho đến khi bạn được chỉ thẳng vào đích, rồi tiếp tục tiến về phía trước, hoặc bằng cách rẽ phải và làm điều tương tự. Hình 5: Xác định đường dẫn ngắn nhất từ ​​điểm gốc đến đích.

Trong Hình 5, con đường ngắn nhất rõ ràng là đường màu xanh lá cây ở phía dưới. Đường dẫn này hóa ra khá đơn giản để tính toán do một số mối quan hệ hình học, được minh họa trong Hình 6.

Hình 6: Tính chiều dài của đường dẫn.

Đầu tiên, chúng tôi tính toán vị trí của điểm P, là tâm của vòng tròn quay của chúng tôi và luôn luôn bán kính r so với điểm bắt đầu. Nếu chúng ta rẽ phải từ hướng ban đầu, điều đó có nghĩa là P nằm ở góc (init_direction - 90) so với điểm gốc, vì vậy:

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

Bây giờ chúng ta đã biết vị trí của điểm trung tâm P, chúng ta có thể tính khoảng cách từ P đến đích, được hiển thị là h trên sơ đồ:

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

Tại thời điểm này, chúng tôi cũng muốn kiểm tra xem đích đến không nằm trong vòng tròn, bởi vì nếu có, chúng tôi không bao giờ có thể đến được:

if (h < r)
    return false

Bây giờ chúng ta có thể tính độ dài của đoạn d, vì chúng ta đã biết độ dài của hai cạnh còn lại của tam giác vuông, cụ thể là h và r. Chúng ta cũng có thể xác định góc từ mối quan hệ tam giác vuông:

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

Cuối cùng, để tìm ra điểm Q tại đó rời khỏi vòng tròn và bắt đầu trên đường thẳng, chúng ta cần biết tổng góc +, và dễ dàng xác định là góc từ P đến đích:

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)

Các tính toán trên đại diện cho con đường rẽ phải. Đường dẫn bên trái có thể được tính theo cùng một cách chính xác, ngoại trừ việc chúng ta thêm 90 vào init_direction để tính angleToP, và sau đó chúng ta sử dụng - thay vì +. Sau khi tính toán cả hai, chúng ta chỉ cần xem đường dẫn nào ngắn hơn và sử dụng đường dẫn đó.

Khi thực hiện thuật toán này và các thuật toán tiếp theo, chúng tôi sử dụng cấu trúc dữ liệu lưu trữ tối đa bốn "phân đoạn dòng", mỗi phân đoạn là thẳng hoặc cong. Đối với các đường cong được mô tả ở đây, chỉ có hai đoạn được sử dụng: một vòng cung theo sau là một đường thẳng. Cấu trúc dữ liệu chứa các thành viên xác định xem phân đoạn là một cung hay một đường thẳng, độ dài của phân đoạn và vị trí bắt đầu của nó. Nếu đoạn là một đường thẳng, cấu trúc dữ liệu cũng chỉ định góc; đối với các cung, nó chỉ định tâm của vòng tròn, góc bắt đầu trên vòng tròn và tổng radian được bao phủ bởi vòng cung.

Khi chúng ta đã tính toán đường cong cần thiết để có được giữa hai điểm, chúng ta có thể dễ dàng tính toán vị trí và hướng của mình tại bất kỳ thời điểm nào được đưa ra theo thời gian, như trong Liệt kê 2.

DANH SÁCH 2. Tính toán vị trí và định hướng tại một thời điểm cụ thể.

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
Câu trả lời này không thực sự nhìn vào vật lý của tàu. Tôi cũng thấy có vấn đề là về cơ bản nó là một liên kết đến và một đoạn trích dài từ một trang web khác (tôi không chắc về tính hợp pháp).
Không ai

Lần cuối cùng tôi cung cấp một tài nguyên hiện có là một giải pháp cho câu hỏi đang được hỏi, tôi đã được yêu cầu đưa nội dung của liên kết vào sự kiện mà trang đích không còn tồn tại. Bây giờ tôi được yêu cầu không bao gồm nội dung. Tạo nên tâm trí của bạn.
Draco18 không còn tin tưởng vào

3
@ Draco18s: Những gì bạn nên làm là tóm tắt những điểm quan trọng của tài liệu được liên kết bằng từ ngữ của riêng bạn. (Hoặc, tốt hơn hết, hãy trả lời câu hỏi dựa trên kinh nghiệm của chính bạn và chỉ sử dụng các liên kết làm tài liệu hỗ trợ hoặc để đọc thêm.) Các trích dẫn ngắn thường ổn, đặc biệt là trong các tình huống không thể tránh được (ví dụ: trích dẫn chính xác của ai đó những từ để chứng minh rằng họ thực sự đã nói điều gì đó), nhưng trích dẫn một phần đáng kể của một bài viết thực sự vượt xa sử dụng hợp lý .
Ilmari Karonen

Nếu điểm nằm trong vòng tròn, bạn có thể ra ngoài một chút và quay lại.
dùng253751

(Ps. Xem thêm những hai câu hỏi trên meta.SE.)
Ilmari Karonen

7

Như một giải pháp đơn giản, như tôi đã nói trong một bình luận, bạn có thể thử cái aproach này:

hãy xem xét một pha mà bạn hướng con tàu theo hướng mục tiêu, trong giai đoạn đó bạn áp dụng một vòng quay cho ngụm nhưng cũng là một chuyển động về phía trước. Khi tàu đã đối mặt với mục tiêu, bạn có thể áp dụng tốc độ hoàn toàn chuyển tiếp. Tôi đã sắp xếp một bài kiểm tra trong love2d, ở đây làm theo phương pháp cập nhật tàu.

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

nhập mô tả hình ảnh ở đây

Hoạt hình ví dụ cho thấy (vòng lặp cuối cùng) một trường hợp con tàu không thể tiếp cận mục tiêu, vì sự kết hợp giữa tốc độ quay và tốc độ chuyển tiếp xác định bán kính quay vòng quá lớn, trong trường hợp này có thể giúp chúng giảm bớt " turnForwordSpeed" hoặc tốt hơn là làm cho nó phụ thuộc vào khoảng cách góc ( a) và khoảng cách mục tiêu.


Đây là một câu trả lời hay, nhưng nó có thể hoặc không đủ thực tế cho OP. Không giống như, ô tô, tàu không thực sự có "bán kính quay vòng": hầu hết các tàu tự vận hành (động cơ / con người) về cơ bản có thể bật xu, trong khi các tàu thuyền phụ thuộc vào gió và thực sự có thể chuyển hướng hiệu quả tiêu cực bán kính khi khai thác, theo nghĩa là rẽ trái vào gió có thể khiến con tàu trôi dạt sang phải. Có gì tàu làm có là quán tính (và kéo): họ không thể bật hoặc di chuyển ngay lập tức, và một lần di chuyển hoặc quay, mất một thời gian và lực lượng để dừng lại. Tuy nhiên, có +1.
Ilmari Karonen

Cảm ơn bạn rất nhiều vì câu trả lời của bạn!!! :) Ngài là người hùng của tôi!
DavidT

@DavidT Sau đó xem xét đánh dấu câu trả lời của anh ấy / cô ấy là câu trả lời được chấp nhận, nếu nó có thể giải quyết vấn đề của bạn một cách thỏa đáng. :)
MA

-2

Hệ thống lưới Unity Nav, nó có thể sẽ làm những gì bạn muốn với một chút chơi xung quanh với các giá trị tác nhân điều hướng.

Nav Lưới khá đơn giản để sử dụng. Và chỉ có thể sử dụng trong thiết lập từ trên xuống (hoặc ít nhất là chỉ có sẵn cho chuyển động x / z)

Hướng dẫn thống nhất Trang về thiết lập lưới điều hướng

Về cơ bản, bạn có thể sử dụng bất kỳ lưới hình dạng nào để nướng một vùng điều hướng và thêm các tác nhân điều hướng vào các đối tượng của bạn và để chúng tìm đường đi của chúng xung quanh lưới điều hướng


Tôi thấy câu trả lời của Draco18 cũng thiếu về vấn đề đó. Tuy nhiên, của bạn không phải là một câu trả lời thực sự và nhiều hơn một nhận xét.
Không ai

2
Đây là một gợi ý tốt, nhưng để trở thành một câu trả lời hay, nó cần hỗ trợ và thông tin về việc thực hiện. Vui lòng thêm một số thông tin liên quan đến việc cấu hình lưới điều hướng để làm cho câu trả lời tốt. Tôi nghĩ đó là những gì các nhà bình luận ở trên đang cố gắng nói :)
sirdank 8/12/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.