0

私は 3D ゲームに取り組んでおり、キャラクターの動きを正しく設定しようとしています。インタラクションはシンプルで、画面上に 1 つのモデルがあり、ユーザーが画面上のポイントをクリックすると、モデルが回転してクリックされたポイントに面します (現在、モデルは目で小さなゴーストになっているため、目はクリックされた場所に向きます)ポイント)、ポイントに面すると、モデルはそこに移動します。

私は自分で書いたいくつかのコードでこれを機能させましたが、アニメーションはスムーズではなく、モデルはしばしば目的地をオーバーシュート/アンダーシュートし、その後所定の位置に前後に移動しました. 以前は 2D アニメーションで Universal Tween エンジンを使用したことがありましたが、試してみることにしました。それはぎくしゃくした問題を解決し、回転と変換の両方が単独でうまく機能しますが、それらを連続して一緒に機能させることはできません。

モデルを回転させるコードのみを有効にすると、問題なく動作します (まあ、ほとんど問題なく、特定の角度で時計回りまたは反時計回りの回転を決定すると何かがおかしくなりますが、それは後で別の問題になります): 場所をクリックすると、モデルがその方向を向くように回転し、次のクリックまで新しい回転を保持した後、その場所を向くようになります。翻訳のみを有効にした場合と同じ: スポットをクリックすると、モデルがそこに移動し、もう一度クリックするまで新しい翻訳が保持され、その後、その場所に移動します。

移動と回転の両方を有効にすると、問題が発生します。モデルは、最初にクリックしたポイントに面するように回転し、次に最初の回転に戻してから、クリックしたポイントに移動します。2 回目以降のクリックでは、モデルは最初の平行移動に戻り、次にクリックされたポイント (実際には、再初期化された位置に対するクリックされたポイントの位置) に面するように回転し、クリックされたポイントに移動します。

コードを再配置し、コールバックを使用し、新しい変換と回転をゲーム モデル クラスのメンバーにキャッシュしset()、トゥイーンを開始する前にそれらの値を使用してみましたが、何も機能しませんでした。

my からの関連コードは次のTweenAccessorとおりです。

public class GameModelTweenAccessor implements TweenAccessor<DynamicModel> {    
    public int getValues(DynamicModel target, int tweenType, float[] returnValues) {
        trans = target.model.transform.getTranslation(trans);
        switch (tweenType) {
            ...
            case POSITION_XYZ:
                returnValues[0] = trans.x;
                returnValues[1] = trans.y;
                returnValues[2] = trans.z;
                return 3;
            case ROTATION:
                axisVec = new Vector3();
                angle = target.model.transform.getRotation(new Quaternion()).getAxisAngle(axisVec) * axisVec.nor().y;
                returnValues[0] = angle;
                return 1;
            ...
        }

    }

    public void setValues(DynamicModel target, int tweenType, float[] newValues) {
        trans = target.model.transform.getTranslation(trans);
        switch (tweenType) {
            ...
            case POSITION_XYZ:
                target.model.transform.setToTranslation(newValues[0], newValues[1], newValues[2]);
                break;
            case ROTATION:
                target.model.transform.setToRotation(Vector3.Y, newValues[0]);
                break;
            ...
        }
    }
}

タイムラインとトゥイーンを開始するコードは次のとおりです (このファイルにあります)。

Timeline.createSequence()
    .push(Tween.to(screen.ghost, GameModelTweenAccessor.ROTATION, Math.abs(angle - newRotation) / 200)
        .target(newRotation)
        .ease(TweenEquations.easeNone))
    .push(Tween.to(screen.ghost, GameModelTweenAccessor.POSITION_XYZ, duration).
        target(intersection.x, intersection.y, intersection.z)
        .ease(TweenEquations.easeNone))
    .start(screen.ghostManager);

誰でも私に解決策を教えてもらえますか?

編集: 各トゥイーンの完了によって設定されている変換は、別のトゥイーンが完了すると 0 にリセットされるようです。これらは、getValuesおよびのsetValues関数からのこれらの値のログTweenAccessorです。

Get Rot: 0.0

Get Trans: x: 0.0          y: 0.0          z: 0.0

Get Rot: 0.0

Get Trans: x: 0.0          y: 0.0          z: 0.0

Get Rot: 0.0

Set Rot: 9.598349
Set Rot: 9.814415
Set Rot: 10.052449
...
Set Rot: 39.99417
Set Rot: 43.397423
Set Rot: 46.62333

Get Trans: x: 0.0          y: 0.0          z: 0.0

Set Trans: x: 0.0012489144 y: 0.0          z: 0.001180494
Set Trans: x: 0.024489587  y: 0.0          z: 0.023147952
Set Trans: x: 0.04921494   y: 0.0          z: 0.04651875
...
Set Trans: x: 6.4197707    y: 0.0          z: 6.06807
Set Trans: x: 6.444479     y: 0.0          z: 6.091425
Set Trans: x: 6.453598     y: 0.0          z: 6.1000443

Get Rot: 0.0

Get Trans: x: 6.453598     y: 0.0          z: 6.1000443

Get Rot: 0.0

Get Trans: x: 6.453598     y: 0.0          z: 6.1000443

Get Rot: 0.0

Set Rot: 3.4318955
Set Rot: 6.795984
Set Rot: 10.0074415
...
Set Rot: 156.79567
Set Rot: 159.99591
Set Rot: 162.38742

Get Trans: x: 0.0          y: 0.0          z: 0.0

Set Trans: x: 0.03550978   y: 3.836017E-8  z: 0.021066409
Set Trans: x: 0.15527377   y: 1.6773768E-7 z: 0.092117175
...
Set Trans: x: 6.848614     y: 7.3983565E-6 z: 4.062985
Set Trans: x: 6.961268     y: 7.5200533E-6 z: 4.129818
Set Trans: x: 7.0624847    y: 7.6293945E-6 z: 4.189865

Get Rot: 0.0

Get Trans: x: 7.0624847    y: 7.6293945E-6 z: 4.189865

Get Rot: 0.0

Get Trans: x: 7.0624847    y: 7.6293945E-6 z: 4.189865

Get Rot: 0.0

Set Rot: -3.2620814
Set Rot: -6.8205137
Set Rot: -9.834579
...
Set Rot: -76.57533
Set Rot: -79.91388
Set Rot: -80.610855

Get Trans: x: 0.0          y: 0.0          z: 0.0

Set Trans: x: 0.01940876   y: 0.0          z: 0.033669088
Set Trans: x: 0.04174851   y: 0.0          z: 0.07242267
Set Trans: x: 0.06332677   y: 0.0          z: 0.109855264
...
Set Trans: x: 2.7853239    y: 0.0          z: 4.8318033
Set Trans: x: 2.808029     y: 0.0          z: 4.8711905
Set Trans: x: 2.827034     y: 0.0          z: 4.9041595

getValuesは、トゥイーンの開始前にトゥイーンの各タイプ (移動と回転) に対して 2 回呼び出されています。この時点で、翻訳の値は、最後の翻訳トゥイーンの最後に設定された値のままです。ただし、回転の値は 0 に戻されました (次の一連の回転の呼び出しの結果として推測していますsetValues)。

setValuesその後、ターゲット ローテーションに到達するまでローテーションのために数回呼び出されます。これは(回転のリセットを除いて)期待どおりに機能しています。ただし、呼び出しの後getRotation、変換は 0,0,0 に戻されますが、呼び出しによるものではsetValuesありません (ログはありません)。その後、翻訳は複数のsetValues呼び出しでターゲットにアニメーション化されます。

この後、別のクリックでサイクルが再開されgetValues、回転と移動のために再度 2 回呼び出されます。Translation には、 last の最後の呼び出しで設定された値がありますがsetValuesTimeline回転 (0 に戻る) がトゥイーンを通過するまでのみです。

への 4 つの呼び出しはgetValues何かである可能性があります。にプッシュされたときに順次実行されることになっている場合、私のセットアップで何が原因Timelineで、トゥイーンが始まる前に翻訳の値を取得するのかわかりませんTimelinegetValuesトゥイーンごとに が 2 回呼び出される理由もわかりませんが、トゥイーン エンジンがトゥイーンの過程で 2 回呼び出すことは不可能ではありません。

私が使用しているLibGDXの変換/回転関数は問題なく、モデルに「固執」し、Tweenエンジン以外のバージョンで行ったのと同じものを変換に使用したと確信しています。回転も似ていますが、同じ機能ではありません。

ただし、2 番目の移動中に Y 値が変化することは、調査する必要があります。

4

1 に答える 1

1

したがって、このソリューションは Universal Tween Engine やその実装方法とは何の関係もありませんでした。LibGDX の行列変換関数についての私の理解が不十分でした。を呼び出すとsetToRotation、変換行列がリセットされ、回転が適用されます。これにより、前の移動がゼロになります。setToTranslation同じことを行うため、回転が失われます。

翻訳にはsetTranslation代わりに使用しましたが、回転は失われません。回転に匹敵する関数はないと思います(使用するrotateとあらゆる種類の問題が発生します)。代わりにVector3、モデルの位置が格納された新しい を取得し、 を適用setToRotationしてから、新しいベクトルに変換を設定します。から更新されたコードは次のTweenAccessorとおりです。

public void setValues(DynamicModel target, int tweenType, float[] newValues) {
    trans = target.model.transform.getTranslation(trans);
    switch (tweenType) {
        ...
        case POSITION_XYZ:
            target.model.transform.setTranslation(newValues[0], newValues[1], newValues[2]);
            break;
        case ROTATION:
            // store the position
            Vector3 position = target.model.transform.getTranslation(new Vector3());
            // then set the rotation and reset the translation
            target.model.transform.setToRotation(Vector3.Y, newValues[0]).setTranslation(position);
            break;
        default:
            assert false;
            break;
    }
}
于 2015-01-06T00:09:53.680 に答える