Unity-船を2Dトップダウンゲームのポイントに現実的に移動する方法


14

帆船をマウスでクリックした場所に移動しようとしています。この動きは現実的である必要があります(船が動き回る後ろにあります)。したがって、マウスのクリックが左で船の前にある場合、船は右回転するために曲がりくねった経路でそこに移動する必要があります

誰かがこの問題で私を助けてくれたら嬉しいです 船の動き


1
あなたのイメージは帆を描いているように見えます:風を考慮に入れるべきですか?いくつかの機動は、間違った風やその不足に対処することは不可能です。
誰も

その他のポイントに、リアルな帆船の動きが本当に必要とし、アカウントに風を取ります。それを無視することは、ジャンプを実装するときに重力を無視することにほとんど似ています。特に詳細な風のモデルは必ずしも必要ではありませんが、船は帆の風(およびキールとラダーに対する水)に押し付けられていることに留意する必要があります。特に、船は風上に直接航行することはできません。代わりに彼ら彼らの方法を打つ必要があります。
イルマリカロネン

通常、「後点」は回転フェーズと前進フェーズに分割できます。同じアプローチを取りますが、回転に前方への動きを課します。例えば、回転のそれぞれのX RADは、Yメートル前方に船を移動
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の位置がわかったので、Pから目的地までの距離を計算できます。これは図にhとして示されています。

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

この時点で、目的地がサークル内にないことも確認します。サークル内にない場合、到達できないためです。

if (h < r)
    return false

これで、直角三角形の他の2つの辺、つまり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つのポイント間を移動するために必要な曲線状のパスを計算したら、リスト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
この答えは、船の物理学を実際に調べていません。また、基本的に別のWebサイトへのリンクであり、別のWebサイトからの長い抜粋であるという問題もあります(合法性については不明です)。
誰も

前回の質問に対する解決策である既存のリソースを提供したとき、ターゲットサイトが停止した場合にリンクのコンテンツを含めるように求められました。現在、コンテンツを含めないように求められています。心を決めてください。
Draco18sはSEを信頼しなくなりました

3
@ Draco18s:あなたがすべきことは、リンクされた資料の重要なポイントをあなた自身の言葉で要約することです。(または、より良いのは、あなた自身の経験に基づいて質問に答え、サポート資料として、またはさらに読むためにリンクのみを使用することです。)特に短い引用は、特に避けることができない状況では大丈夫です(例:誰かの正確な引用彼らが本当に何かを言ったことを示すための言葉)、しかし、記事のかなりの部分を引用することは、本当にフェアユースを超えています
イルマリカロネン

ポイントが円内にある場合は、少し外に出て戻ってくることができます。
user253751

(追伸。meta.SEのこれら 2つの質問も参照してください。)
イルマリカロネン

7

簡単な解決策として、すでにコメントで述べたように、このアプローチを試すことができます:

目標の方向に船を向けるフェーズを考えてください。このフェーズでは、一口に回転を適用するだけでなく、前進も適用します。船がすでに目標に直面している場合は、最大前進速度を適用できます。私は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があります。
イルマリカロネン

ご回答どうもありがとうございました!!!:)あなたは私のヒーローです!
DavidT

@DavidTその後、問題を十分に解決できた場合、回答を承認済みとしてマークすることを検討してください。:)
MAnd

-2

Unity Navメッシュシステムでは、navエージェントの値を少し試してみれば、おそらく必要なことを実行できます。

ナビゲーションメッシュは非常に簡単に使用できます。そして、トップダウン設定でのみ使用可能(または少なくともx / z移動のみで使用可能)

ナビゲーションメッシュのセットアップに関するUnityマニュアルページ

基本的に、任意のシェイプメッシュを使用してナビゲーションエリアをベイク処理し、ナビゲーションエージェントをオブジェクトに追加して、ナビゲーションメッシュの周囲のパスを見つけさせることができます。


Draco18sの回答もその点で欠けていると思います。ただし、あなたの答えは本当の答えではなく、単なるコメントではありません。
誰も

2
これは良い提案ですが、良い答えになるためには、実装に関するサポートと情報が必要です。これが適切な答えになるように、ナビゲーションメッシュの設定に関する情報を追加してください。上記のコメンターが言っていることだと思います:)
sirdank
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.