1

現在、私は 2 つのカメラを持っています。メイン カメラは銃を通常の状態で表示し、2 つ目のカメラは銃に取り付けられ (銃はメイン カメラの子です)、トグルすると銃のスコープを通して見え、増加します。視野。

理解を深めるためのビジュアルを次に示します。

ここに画像の説明を入力

ここに画像の説明を入力

2 つ目のカメラをオンにして、メインのカメラをオフにすれば、うまく機能しますが、あまり理想的ではありません。シーンごとに 1 つのカメラのみを使用する必要があります。

そこで、カメラの位置を Lerp してスコープを覗き込み、手動で視野を狭めたいと思います。そこで、次のスクリプトを作成しました。

[RequireComponent(typeof(Camera))]
public class Zoom : MonoBehaviour {

    private Transform CameraTransform = null;
    public Transform ZoomedTransform;

    private bool zoomed = false;

    void Start () {
        CameraTransform = Camera.main.transform;
    }

    // Update is called once per frame
    void Update () {
        if (Input.GetKey (KeyCode.LeftShift)) 
        {
            CameraTransform.position = Vector3.Lerp (
                CameraTransform.position, 
                CameraTransform.position + ZoomedTransform.position, 
                5f * Time.deltaTime
            );
            CameraTransform.Rotate(ZoomedTransform.rotation.eulerAngles);
        }
    }
}

これの問題は、それが機能しないことです。ズーム ボタンを押すと、カメラが光の速さでシーンを高速で移動し、何が起こっているのかを正確に把握するのは困難です。

私が間違っていることについて誰かが私に洞察を与えることができますか? 親子関係の関係かと思いますが、静的な値を使ってみてもなかなか正解にたどり着けません。

階層:

ここに画像の説明を入力

4

3 に答える 3

1

Lerp ターゲットは、カメラの現在の位置に相対的であるため、常に移動しています。これはあなたが持っているターゲットです:

CameraTransform.position + ZoomedTransform.position

これは、カメラが移動してこの位置に近づくと、カメラの新しい位置によって目的地が変わることを意味します。そのため、カメラは永遠に動き続けます。

目的地は ですZoomedTransform.positionpositionはワールド座標なので加算不要。(実際にスペース間の変換が必要な場合はTransformPoint、同様の方法をチェックしてください。)

于 2015-10-09T19:43:16.133 に答える
1

ZoomedTransform(この回答は、31eee384の回答で疑われるカメラの絶対位置ではなく、相対的な変換であるという仮定の下で機能します。)

あなたのコードにはいくつかの問題があると思います。理解しやすいように個別に説明しますが、どちらも次の行に関連しています。

CameraTransform.position = Vector3.Lerp (CameraTransform.position, CameraTransform.position + ZoomedTransform.position, 5f * Time.deltaTime);

まず、あなたがどのように使っているか見てみましょうVector3.Lerp()。の 3 番目の引数にはVector3.Lerp()、 を指定しています5f * Time.deltaTime。この値は正確には何に影響しますか? まあ、標準のフレームレートは約 60 FPS なので、Time.deltaTime= ~1/60 です。したがって、5f * Time.deltaTime= 5/60 = ~0.0833 です。

Vector3.Lerp()しかし、3 番目の引数には何が期待されているのでしょうか。ドキュメントによると、その 3 番目の引数は 0 から 1 の間である必要があり、返される値Vector3が最初または 2 番目の引数に近いかどうかを決定しVector3ます。はい、5f * Time.deltaTimeこの範囲内に収まりますが、補間は行われません。これは、0 から 1 (または 1 から 0) に進むのではなく、常に約 0.0833 になるためです。各フレーム、基本的に常に戻ってきますcameraPos + zoomTransform * 0.0833

もう 1 つの注目すべき問題は、すべてのフレームの値を更新する方法ですがCameraTransform.position、その新しい (増加した) 値をVector3.Lerp()次のフレームの引数として使用する方法です。(これは、ループで行うのと少し似ていint i = i + 1;ます。) これが、カメラがマップ上を高速で移動する理由です。Vector3.Lerp()これは、以前に計算した仮説の結果(疑似コード)を使用して、各フレームで何が起こっているかです。

// Frame 1
cameraPosFrame_1 = cameraPosFrame_0 + zoomTransform * 0.0833;
// Frame 2
cameraPosFrame_2 = cameraPosFrame_1 + zoomTransform * 0.0833;
// Frame 3
cameraPosFrame_3 = cameraPosFrame_2 + zoomTransform * 0.0833;
// etc...

すべてのフレームzoomTransform * 0.0833がカメラの位置に追加されます。これは最終的に、非常に速く、絶え間なく値が増加するため、カメラはマップを横切って飛んでいきます.

これらの問題に対処する 1 つの方法は、カメラの最初のローカル位置、ズームの進行状況、およびズームの速度を格納する変数を用意することです。このようにして、カメラの元の位置を失うことはなく、ズームがどこまで進んだか、いつ停止するかを追跡できます。

[RequireComponent(typeof(Camera))]
public class Zoom : MonoBehaviour {

    private Transform CameraTransform = null;
    public Transform ZoomedTransform;
    private Vector3 startLocalPos;
    private float zoomProgress = 0;
    private float zoomLength = 2; // Number of seconds zoom will take

    private bool zoomed = false;

    void Start () {
        CameraTransform = Camera.main.transform;
        startLocalPos = CameraTransform.localPosition;
    }

    // Update is called once per frame
    void Update () {
        if (Input.GetKey (KeyCode.LeftShift)) 
        {
            zoomProgress += Time.deltaTime;

            CameraTransform.localPosition = Vector3.Lerp (startLocalPos, startLocalPos + ZoomedTransform.position, zoomProgress / zoomLength);
            CameraTransform.Rotate(ZoomedTransform.rotation.eulerAngles);
        }
    }
}

お役に立てれば!ご不明な点がございましたら、お知らせください。この答えは少しとりとめのないものなので、重要なポイントを理解するのに問題がないことを願っています.

于 2015-10-09T20:10:35.830 に答える