亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何 使 rts 相機 在 Unity 中 縮放 時 平滑

如何 使 rts 相機 在 Unity 中 縮放 時 平滑

C#
呼如林 2022-11-21 20:46:13
現在 我 正 試圖 使 rts 相機 縮放 與 平移 時 , 接近 地面 。我 現在 的 問題 是 , 我 使用 鼠標 滾輪 縮放 , 它 使 縮放 感覺 像 它 的 滯后 。它 看 起來 像 是 跳躍 了 一些 Y 值 和 瞬間 移動 , 而 不是 平滑 地 移動 到 所 需 的 位置 。此外 , 我 還 想 知道 如何 使 相機 停止 在 最 小 Y 值 , 因為 現在 發生 的 是 , 它 停止 在 22 左右 , 而 不是 20 , 這 是 我 的 最 小 Y 值 的 相機 移動 。我 試 著 在 我 的 numpad 上 用 + 和 - 縮放 , 它 按照 我 想 要 的 方式 工作 ( 平穩 地 放大 和 縮小 而 不 跳 過 ) , 但 并 不 是 所有 的 玩家 都 有 numpad , 我 覺得 用 鼠標 滾輪 縮放 更 合適 。{private const int levelArea = 100;private const int scrollArea = 25;private const int scrollSpeed = 25;private const int dragSpeed = 70;private const int zoomSpeed = 50;// Maximum/minimum zoom distance from the groundpublic int zoomMin = 20;public int zoomMax = 120;private const int panSpeed = 40;// Minimal/maximal angles for cameraprivate const int panAngleMin = 30;private const int panAngleMax = 90;void Update(){    // Init camera translation for this frame.    var translation = Vector3.zero;    // Zoom in or out    var zoomDelta = Input.GetAxis("Mouse ScrollWheel") * zoomSpeed * Time.deltaTime;    if (zoomDelta != 0)    {        translation -= Vector3.up * zoomSpeed * zoomDelta;    }    // Start panning camera if zooming in close to the ground or if just zooming out.    var pan = transform.eulerAngles.x - zoomDelta * panSpeed;    pan = Mathf.Clamp(pan, panAngleMin, panAngleMax);    // When to start panning up the camera    if (zoomDelta < 0 || transform.position.y < (zoomMax -20))    {        transform.eulerAngles = new Vector3(pan, 0, 0);    }我希望從相機現在所在的位置到滾動進/出后所需的位置有一個平滑的過渡。我還想知道如何使相機停止在最小/最大變焦距離,而不是停止接近它。謝謝你的幫助。攝像機移動的視頻:https://youtu.be/Lt3atJEaOjA
查看完整描述

2 回答

?
HUH函數

TA貢獻1836條經驗 獲得超4個贊

好 的 , 我 現在 要 做 三 件 事 。First and foremost, I'm going to recommend that if you're working with advanced camera behavior, you probably want to at least consider using Cinemachine.我 想 親自 給 你 講解 一下 , 但 鑒于 我 缺乏 親身 經歷 , 我 可能 會 給 你 帶來 傷害 。有 很多 很 好 的 教程 在 那里 。youtube 和 谷歌 應該 提供 。


我要做的第二件事是用我能管理的最直接的方式解決你的問題,然后,我們再看看是否能想出一個更好的方法來解決你的問題。


所以,這里的關鍵是Unity的滾輪輸入是非常二進制的。當你檢查一個滾輪軸時,結果直接基于自上次幀更新以來你的滾輪經歷了多少次“點擊”,但你真正想要的是一些有一點給予的東西。默認情況下,Unity實際上可以對大多數軸輸入執行此操作:您可能會注意到,如果您在默認Unity項目中使用WASD,則會有一種“滯后”現象,您的手指會離開按鍵,但仍會從輸入.獲取軸()對于幾個幀。這與重力輸入設置中的值,以及輸入.GetAxisRaw()函數實際上是用來完全規避這一點的。不管出于什么原因,滾輪軸似乎不受軸重力的影響,所以我們本質上必須自己實現類似的東西。


// Add this property to your class definition (so it persists between updates):

private float wheelAxis = 0;


// Delete this line:

var zoomDelta = Input.GetAxis("Mouse ScrollWheel") * zoomSpeed * Time.deltaTime;


// And put these three new lines in its place:

wheelAxis += Input.GetAxis("Mouse ScrollWheel");

wheelAxis = Mathf.MoveTowards(wheelTotal, 0f, Time.deltaTime);

var zoomDelta = Mathf.Clamp(wheelAxis, -0.05f, 0.05f) * zoomSpeed * Time.deltaTime;

好的,我們在這里做一些事情。每次更新時,我們都會將當前滾輪值添加到輪軸。接下來,我們將電流Time.deltatime“重力”通過數學函數移動到()得雙曲余切值.最后,我們稱之為“老”縮放增量經過簡單修改代碼:我們約束輪軸與Mathf.Clamp以嘗試和調節變焦可以發生得多快。


您 可以 通過 幾 種 方式 修改 此 代碼 。If you multiply the Time.deltaTime parameter you can affect how long your input will "persist" for. If you mess with the Mathf.Clamp() values, you'll get faster or slower zooming.總 而言 之 , 如果 您 只 想 在 對 代碼 進行 最 小 更改 的 情況 下 實現 平滑 縮放 , 這 可能 是 最 好 的 選擇 。


這樣 啊 !


現在 我們 已經 完成 了 這些 , 讓 我們 來 討論 一下 您 的 代碼 , 以及 您 是 如何 處理 問題 的 , 看看 我們 是否 能 找到 一 個 稍微 干凈 一些 的 解決 方案 。


讓一臺好的相機工作起來是非常重要的。你的代碼看起來像我看到的很多試圖解決復雜問題的代碼:看起來您添加了一些功能,然后對其進行了測試,發現了一些崩潰的邊緣情況,然后修補了這些情況,然后嘗試在舊代碼上實現新功能,但它以各種其他方式中斷,等等,我們在這一點上得到的有點混亂。


你的代碼最大的問題是攝像頭位置攝像頭自轉緊密地聯系在一起。當與字符工作時,這通常是好的,但當與相機工作時,你想要打破這一點。想想攝像頭是以及相機是什么查看作為非常獨立的事情來記錄。


因此 , 這里 有 一 個 工作 的 相機 腳本 , 你 應該 能夠 插入 和 運行 :


using UnityEngine;


public class RTSCamera : MonoBehaviour

{

    public float zoomSpeed = 100f;

    public float zoomTime = 0.1f;


    public float maxHeight = 100f;

    public float minHeight = 20f;


    public float focusHeight = 10f;

    public float focusDistance = 20f;


    public int panBorder = 25;

    public float dragPanSpeed = 25f;

    public float edgePanSpeed = 25f;

    public float keyPanSpeed = 25f;


    private float zoomVelocity = 0f;

    private float targetHeight;


    void Start()

    {

        // Start zoomed out

        targetHeight = maxHeight;

    }


    void Update()

    {

        var newPosition = transform.position;


        // First, calculate the height we want the camera to be at

        targetHeight += Input.GetAxis("Mouse ScrollWheel") * zoomSpeed * -1f;

        targetHeight = Mathf.Clamp(targetHeight, minHeight, maxHeight);


        // Then, interpolate smoothly towards that height

        newPosition.y = Mathf.SmoothDamp(transform.position.y, targetHeight, ref zoomVelocity, zoomTime);


        // Always pan the camera using the keys

        var pan = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")) * keyPanSpeed * Time.deltaTime;


        // Optionally pan the camera by either dragging with middle mouse or when the cursor touches the screen border

        if (Input.GetMouseButton(2)) {

            pan -= new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")) * dragPanSpeed * Time.deltaTime;

        } else {

            var border = Vector2.zero;

            if (Input.mousePosition.x < panBorder) border.x -= 1f;

            if (Input.mousePosition.x >= Screen.width - panBorder) border.x += 1f;

            if (Input.mousePosition.y < panBorder) border.y -= 1f;

            if (Input.mousePosition.y > Screen.height - panBorder) border.y += 1f;

            pan += border * edgePanSpeed * Time.deltaTime;

        }


        newPosition.x += pan.x;

        newPosition.z += pan.y;


        var focusPosition = new Vector3(newPosition.x, focusHeight, newPosition.z + focusDistance);


        transform.position = newPosition;

        transform.LookAt(focusPosition);

    }

}

雖然我鼓勵你在自己的時間里去經歷它,但我不打算拖你走過它的每一寸,相反,我只會把主要的癥結過一遍。


The key idea here is that rather than controlling the camera's height and orientation directly, we just let the scrollwheel dictate where want the camera's height to be, and then we use Mathf.SmoothDamp() to move the camera smoothly into that position over several frames.( Unity 有 很多 像 這樣 有用 的 功能 。Consider Mathf.MoveTowards() for an alternative interpolation method.)在 最 后 , 我們 并 沒有 直接 調整 攝像 機 的 旋轉 值 , 而是 在 我們 面前 靠近 地面 的 地方 選擇 一 個 點 , 然后 直接 將 攝像 機 對準 那個 點 。


通過保持攝像機的位置和方向完全獨立,以及分離出攝像機高度的“動畫”,我們避免了很多麻煩,并消除了許多混亂交織的錯誤的可能性。


希望 能 幫 上 忙 。


查看完整回答
反對 回復 2022-11-21
?
慕萊塢森

TA貢獻1810條經驗 獲得超4個贊

Cinemachine是相當不錯的,但我建議人們在使用Cinemachine之前自己學習相當多的東西,這樣你就能更好地了解后臺發生了什么。


查看完整回答
反對 回復 2022-11-21
  • 2 回答
  • 0 關注
  • 208 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號