倉庫:https://gitee.com/mrxiao_com/2d_game_2
回顧我們之前停留的位置
在這段內容中,討論了如何處理游戲中的三維效果,特別是如何處理額外的“Z層”。由于游戲中的藝術資源是位圖而不是3D模型,因此實現三維效果變得非常具有挑戰性。雖然可以通過讓游戲保持在一個平面上并避免涉及上下的元素來簡化問題,但這并不是當前的目標。相反,目標是探索如何在不放棄位圖藝術的情況下,通過各種方法模擬Z深度,以增強游戲的三維感。
接下來,討論了如何處理這些Z層的復雜性,尤其是在程序開發過程中沒有一個完美的解決方案。相比于其他相對容易解決的問題,例如紋理映射,處理Z層涉及更多復雜的決策過程。在這一過程中,目標是逐步探索這些問題,并嘗試找到清晰且有效的渲染設計,使得Z深度感能夠在游戲中得到體現。
在之前的工作中,已經有一個包含兩個Z層的測試世界,并且關閉了地面塊的渲染。接下來的工作是重新啟用這些地面塊的渲染,并開始處理Z切片的概念。在這一過程中,開發者希望通過調整相機的位置并觀察不同層級的元素如何變化,來更好地理解Z層的效果。最終的目標是讓這些Z切片能夠合理地展示,并為游戲中的三維效果提供更清晰的視覺呈現。
解釋 Z 切片的必要性
這段內容討論了在游戲中實現Z層次的具體變化,目標是確保Z層在游戲世界中能夠有一致性和結構性。由于游戲使用的是位圖藝術,而位圖本身不能很好地表達三維信息,因此需要通過“固定的Z切片”來解決這一問題。
首先,提到的核心概念是“Z切片”,這些切片與當前的“chunkz”概念相吻合,目的是將世界分成不同的層次。每個層次都被視為一個獨立的實體,游戲中的所有對象都被歸類到不同的Z切片中,并且不能同時跨越多個Z切片。如果要跨越多個Z層次,則需要在每個層次上都有相應的藝術資源,這樣可以避免在視覺上造成混亂。
在設計中,如果不同層次之間存在視覺斷層,雖然可能導致一定的視覺破裂,但這也是藝術風格的一部分,因此可以接受。如果這種斷層效果影響太大,可能會考慮關閉某些縮放效果,使所有層次之間更為一致,確保藝術資源的頂部和底部對齊。然而,由于游戲并不依賴于高大的結構,基本上可以通過將世界視作一系列獨立的“外殼”來處理這些問題。
通過這樣的設計,游戲中的實體可以在這些Z層之間自由移動而不會造成問題,整體來看,這種方法應該是可行的。
看一下我們的 SimRegion 如何處理實體的解包
目前的工作是檢查如何在游戲中處理實體的解包,特別是關于模擬區域(SimRegion)部分。解包實體的過程大致是這樣的:通過相機查看所有被觸及的區域,遍歷這些區域并將所有的實體提取出來,然后將它們添加到模擬區域中,最后完成解包操作。
在這個過程中,當前的做法是維護一個“Chunkz”概念,它幫助追蹤實體的Z層次,但并沒有實際利用偏移的Z值(Offsetz)。這意味著,雖然相機的Z坐標是被保留的,避免了Z值丟失,但在當前的實現中,相機在不同Z層之間的過渡并不是平滑的,而是以跳躍的方式進行。也就是說,相機在Z層之間移動時,并不會產生流暢的過渡,而是直接從一個層次跳到另一個層次。
最終,目標是使得相機在Z層之間的過渡更加平滑,而不是采用目前的跳躍式過渡。
去掉 ZOffset 并重新啟用 DrawRectangle
在這個過程中,決定移除之前添加的Z偏移量(offset),并回退到之前的設置。Z偏移量的移除是為了簡化代碼并確保功能能夠按預期運行。
在做這些修改之后,運行代碼時發現之前的矩形繪制功能被禁用了,因此需要重新啟用該功能。通過回顧代碼,發現矩形繪制邏輯已經正確更新,只是因為工作時忘記啟用繪制功能,所以沒有顯示出來。啟用之后,矩形繪制功能恢復正常,房間的邊界線再次顯示出來。
此外,雖然目前沒有藝術資源來填充樓梯的區域,但測試時能夠看到角色成功地走上樓梯并進入上層。這表明Z層的邏輯在處理樓層過渡時已經能夠正常工作,盡管在視覺效果上還沒有完全實現。
關閉相機捕捉
在此過程中,決定關閉Z塊的跳躍,使相機的運動更加平滑和連續。通過檢查代碼,發現相機的Z偏移量沒有被使用,因此決定讓偏移量基于相機的位置進行調整。通過這樣修改,相機的Z軸運動變得更加平滑,能夠看到層次之間的過渡效果。
接下來,需要引入一致性的概念,即控制哪些層在不同的Z軸位置上應當顯示或隱藏。特別是當視角處于較低的位置時,地面可能會遮擋視線,使得上層內容無法被看到。因此,需要確保在視角向上移動時,原本遮擋的層會逐漸顯示出來,避免不需要的內容在不合適的時機顯示。
這一步驟的目的是確保視覺上的漸變效果,只有在相機移動到一定高度時,才會讓上一層逐漸顯現,從而實現更加自然和符合預期的畫面過渡。
解釋固定 Z 切片的概念
為了實現目標,首先需要引入“Z切片”的概念。這是為了確保能夠明確知道相對于這些切片的位置。每個切片表示在世界中的不同高度層次,因此需要設計一個能夠處理這些層次查詢的系統。
目標是讓世界結構能夠回答以下問題:給定一個空間中的某個點,返回該點所在的地面層級,以及它上面和下面的層級。通過這種方式,能夠更清楚地知道當前的位置以及所在層級,確保在不同的Z軸層次之間切換時能夠獲得正確的效果。
這意味著不需要在代碼的其他地方到處手動管理每個層次的位置,而是通過集中查詢來獲取有關層次的信息。這樣可以簡化未來可能的修改,使得即便在未來需要為某些特殊區域設計不同的層次處理邏輯時,也能夠在不影響其他部分的情況下處理這些特殊情況。
此外,提供了一個可以靈活處理不同區域特殊需求的查詢機制,讓世界結構可以在必要時做出相應調整,但對其他部分的邏輯不會造成影響。這種結構可以為以后可能的復雜情況留出空間,并使得世界的層次劃分更加清晰、可維護。
移動 GlobalAlpha
在當前的世界結構中,使用了一個全局透明度值(GlobalAlpha),雖然這個值被認為不太理想,但目前會先用它來確保功能正常運行。在確保基礎功能后,計劃將全局透明度值移除,轉而使用渲染目標的方式來處理漸變效果,使得不同層次之間能夠實現更精確的過渡。
每個實體的透明度(alpha)值將根據其在世界中的位置來動態調整,而不再依賴全局透明度。這意味著每個實體可以根據其高度來設定透明度,而不需要通過全局透明度控制整個場景。
然而,當前存在一個問題,即在渲染實體時,無法準確確定敵人的最終位置,因為模擬尚未完成。這暴露了一個潛在的問題,即渲染過程與更新過程之間的耦合性過高。為了解決這個問題,可能需要在更新和渲染之間做出明確的分離,盡管這一點最初并不打算提前處理,但這可能是接下來需要考慮的重要改進。
關于分離實體的更新和渲染
之前討論過一個問題,更新和渲染為什么要合并為一個過程。這樣做的架構設計是為了提高效率,使得某些內容能夠在同一過程內更新和渲染,避免不必要的操作。不過,在一些情況下,更新和渲染可能需要分開處理,尤其是在需要更多靈活性的實體和粒子系統中。
對于實體,考慮到目前的工作方式,可能會將更新和渲染分成不同的階段,這樣可以提供更多的靈活性和控制。而粒子系統等其他內容,可能更適合同時更新和渲染,因為這樣做會更高效。
總的來說,建議在沒有明確需求的情況下,保持更新和渲染一起進行,只有在確定分開能夠帶來效率提升時,才會將其分開。這樣可以避免不必要的操作,比如頻繁地從緩存中拉取和存入數據。但當前的階段可以暫時不考慮這些優化,使用一幀的延遲來處理透明度問題,等以后再做進一步調整。
根據 GroundP 設置 GlobalAlpha
首先,設置了一個全局透明度(GlobalAlpha)值,并且希望根據實體的位置來調整這個透明度值。為了實現這一點,首先需要查看實體的實際位置,并通過一個查詢函數(比如 getGroundPoint
)來確定該實體的地面位置。
然后,根據實體與相機之間的距離,來調整全局透明度值。相機的位置是固定的,通常位于同一空間區域的中心。通過計算實體位置和相機位置之間的差距,便可以得出透明度應該如何變化。
目前,全局透明度值的設定是一個臨時解決方案,只是為了測試而使用,不打算長期保持。在代碼中,使用了 getGroundPoint
函數獲取實體的地面位置,并基于這個位置來調整透明度。但由于全局變量的使用存在一定的風險,因此希望將這種方法替換為更干凈的實現方式。
總的來說,現在的透明度調整機制只是一個臨時手段,用來測試效果,未來會考慮更合適的方式來處理這一問題,避免依賴全局變量,保持代碼的清晰和可維護性。
引入 CameraP
在這里討論了相機位置的處理問題。最初,認為相機的位置應該固定在原點,但考慮到將來可能需要支持相機不在原點的情況,因此決定加入相機位置的處理。目的是確保無論相機位置如何,都能正確渲染實體。
為此,決定引入相機位置的概念,并計算相機相對于當前區域的位移。通過這種方式,在渲染時可以根據相機的位置調整實體的位置,確保它們能夠相對于相機正確顯示。
雖然現在假設相機位于中心,但為了更靈活地處理將來的需求,相機位置會被計算并保存,以便在未來的渲染過程中調整。當前假設相機的初始位置為區域的中心,在實現時可以通過減去相機位置和區域中心點的位置來得出相機相對區域的位置。
這種方法確保了可以在不破壞系統的情況下調整相機位置,并且會自動處理在不同位置的相機。在實際實現時,可能會通過調整相機位置來實現不同的視角需求。
從 CameraRelativeGroundP 設置 GlobalAlpha
首先,想要做的是計算相機相對地面的位置。具體方法是,將地面點的坐標減去相機的位置,這樣就能得到相對位置。接下來,通過計算該位置的 z 值來確定實體的高度,從而得出該實體相對于相機的高低。
為了實現漸變效果,使用某種函數來控制透明度,確保透明度的值在 0 到 1 之間。具體操作是,如果實體的位置在相機下面(即 z 值為負或零),則不進行處理。否則,采用某種方式來控制其透明度,設定一個距離閾值(例如 1.5 米),當實體超過這個距離時,它的透明度將穩定下來,逐漸消失。
看看游戲中的淡入效果
整體上,效果看起來相當不錯。當角色向上移動時,透明度逐漸增加,產生了平滑的淡入效果;而當角色向下移動時,透明度則逐漸減少,產生了淡出效果。通過這種方式,實體的位置變化與透明度的過渡相結合,營造出了良好的視覺效果,表現出隨著位置變化,實體在視覺上的漸變變化。
使其更正式一點
當前的透明度漸變處理方式采用了一種臨時的、即興的方式,因此需要進行規范化,以便能夠基于實際值進行調整。首先,定義漸變的起始FadeStartZ和結束位置FadeEndZ,在z軸上劃分切片,這些切片需要進行漸變處理。目標是明確漸變何時開始,何時結束,確保沒有任何混亂。通過設定漸變的開始和結束位置,可以更加精確地控制每個切片的透明度變化,從而實現更加靈活和清晰的漸變效果。
Blackboard: 指定關卡的可見性
為了實現透明度漸變效果,需要對漸變區域進行參數化處理,確保能夠控制不同層次之間的可見性。具體來說,可以通過設置多個漸變起始和結束位置來定義可見區域與不可見區域之間的過渡。首先,在攝像機與某個特定高度之間的區域內,物體將保持完全可見。然后,隨著高度的增加,物體將開始逐漸消失,直到完全不可見。為了進一步細化控制,可能需要設置不同的漸變參數,以處理上下不同的漸變區域。比如,可以定義上方和下方的漸變起始和結束點,確保在某些特定高度區域物體不會完全消失,而是在視線中逐漸淡出。
此外,由于物體的高度范圍可能不同,需要考慮不同層次的地面之間的漸變效果。為了避免遮擋視線,尤其是在俯視場景時,需要將每一層的漸變值根據其在場景中的實際位置進行調整。因此,每個地面層的漸變范圍可能需要不同的處理方式,從而確保每一層的地面在適當的時候可以逐步顯現或消失,而不會影響玩家的視野。
引入FadeIn淡入位置標記
為了實現漸變效果,需要定義漸變的起始和結束高度,并在這些高度之間進行平滑的透明度變化。首先,可以設定一個“漸變開始”的上方高度和下方高度(例如上方距離1米,下方距離2層樓)。這些值會決定物體開始淡出的時機和位置。上方和下方的漸變將根據設置的起始位置、結束位置以及透明度值來調整。
對于上方的漸變,物體會在從攝像機開始的某個高度處逐漸淡出,直到到達一個特定的高度(例如地面高度或某個層次),并且一旦超過這個高度,物體就完全不可見。對于下方的漸變,物體會在一個較低的高度開始淡出,直到到達另一個不可見的底部區域。
透明度(Alpha)值的計算將根據物體與攝像機的相對高度來決定。如果物體的相對高度大于“漸變上方起始值”,則物體開始在上方漸變消失;如果物體的相對高度小于“漸變下方起始值”,則物體開始在下方漸變消失。根據這些條件,可以動態調整透明度,實現上方和下方的漸變效果。
最終,整個漸變過程會根據具體的游戲世界設置來調整,使物體在不同高度區域內平滑過渡,不會直接消失或突然出現。
引入 Clamp01MapToRange
為了實現透明度漸變,計劃引入一個范圍函數,用于將一個值標準化到0到1之間。這個函數接收三個參數:最小值(min)、最大值(max)和目標值(t)。它的目標是計算出目標值相對于最小值和最大值的位置,并將結果轉化為一個0到1之間的值。
首先,定義一個范圍值,即最大值減去最小值。接著,通過檢查范圍是否大于零,避免除零錯誤。如果范圍大于零,則計算目標值與最小值的差,并將其除以范圍值,從而將目標值規范化為0到1之間。如果范圍為負值,計算方式也能正常工作,只是會反轉計算的方向,這依然是可以接受的。
通過這個函數,可以將相對位置(如相機相對的Z坐標)與漸變起始和結束的Z坐標進行比較,并計算出該值在漸變范圍內的位置。根據計算的結果,可以決定漸變的透明度,從而實現平滑的過渡效果。
游戲中查看并修正淡入方向
接著,發現問題的根源可能是 fade end z
的設置問題。為了避免物體在未達到目標高度時就部分可見,fade end z
必須與地面高度對齊。即如果 fade end z
沒有在地面高度時結束,物體就會部分可見,從而導致問題。
方便調試改一下窗口大小
允許我們上升到另一個層次
目前的世界生成系統只允許樓層之間堆疊兩個房間,但希望能夠擴展到多個樓層,以支持更多復雜的結構。當前的實現存在限制,無法自由選擇上樓或下樓。要實現這一目標,可以修改房間生成邏輯,讓門的方向(向上或向下)可以分別獨立選擇,從而允許房間在不同的高度進行堆疊,避免一開始就局限于兩層。
在嘗試解決這個問題時,遇到一個困境:生成的樓層沒有正確堆疊,導致玩家可以走下樓梯進入一個空的空間。這是因為生成門時沒有正確處理門的方向,默認假設門總是指向正確的位置。為了解決這一問題,需要修改生成邏輯,確保根據門的方向調整相應的高度。如果門是向下的,則需要調整 Z 坐標以便正確生成下層,如果是向上的,則相應調整 Z 坐標以生成上層。
為進一步調試,嘗試優化了墻壁的生成,限制了墻壁的數量,以便減少渲染負擔,同時避免不必要的計算。然而,當前的生成邏輯依然存在問題,例如玩家可以隨意穿越墻壁,這需要進一步改進。
此外,為了測試多層堆疊房間的效果,需要調整生成邏輯,使其更傾向于創建多個上下樓的門,而不是隨機生成。具體來說,可以引入一種方法,使得生成的樓梯不會重疊,從而可以自由地堆疊多個樓層,避免生成邏輯中出現重復的樓梯。最終,目標是創建一個能夠生成多層建筑,并且每層之間有清晰上下通道的世界。
做了什么
在嘗試修改生成邏輯以確保門始終朝下時,意圖是將門的方向固定為向下,從而避免其他情況的出現。然而,這樣的修改帶來了一些意外的后果。現在生成的樓層似乎過多,并且發生了交叉現象,看起來好像超出了預定的閾值,并且可能觸發了某種翻轉錯誤。這個問題需要進一步調試,以了解為什么會有這么多層級,并找出原因。
同時,也對實體的生成產生了疑問。原本只打算在一個有限的區域內生成實體,但現在發現有許多實體出現在不該出現的地方。這個問題需要檢查生成過程中是否存在誤操作,特別是在 Z 坐標的處理上,可能導致了不必要的實體生成。
這是一個 bug
這是一個明顯的錯誤,需要盡快修復。同時,另一個問題是為什么沒有任何實體在逐漸消失。似乎某個環節出現了問題,導致應有的漸隱效果沒有生效。需要進一步排查,找出問題的根源。
調查發生了什么
問題可能出在Z軸范圍的計算上,導致從不應該包括的區域加載了過多的實體。看起來在查詢時,不僅是與實體的Z軸坐標不匹配,而且查詢范圍異常大。這個問題可能是由最大實體半徑導致的,使得查詢范圍過于寬泛,導致不需要的區域也被加載進來。
目前的解決方案是暫時關閉優化,逐步調試代碼,以查看Z軸范圍的實際值。通過這一步可以進一步確認是哪個參數(例如最大速度或最大實體半徑)導致了異常范圍的出現。
將 Z 的 MaxEntityRadius 設置為 0.0f
問題的根源在于由于最大速度的影響,Z軸的查詢范圍過大,因此會加載到不必要的區域。為了解決這個問題,決定暫時不使用實體半徑來限制查詢范圍,這樣可以減少加載的實體數量。接下來需要查看是否可以通過調整安全邊距(safety margin)來進一步減少Z軸上的波動。
目前的思路是,只在Z軸上添加一個較小的邊距,而不是過多地擴展范圍,避免不必要的實體被加載。同時,檢查update safety margin
是否正確生效,以確保在沒有附加額外限制的情況下,Z軸的波動不會過大。接下來的步驟是檢查這些調整是否能夠有效地縮小查詢范圍。
將 Z 的 SimBoundsExpansion 設置為 0.0f,然后設置為 GameState->TypicalFloorHeight
首先,查詢的初始范圍被發現過大,最大值為15,最小值為-15,顯得非常不合理。問題在于Z軸的處理沒有考慮中心對齊,代碼的設計顯得非常隨意,沒有深思熟慮。考慮到這一點,認為在Z軸上不應添加任何額外的擴展,只需使用當前的樓層高度,并通過安全邊距擴展來處理。
為了修正這一點,決定不進行任何Z軸的邊界擴展,只在每一側添加一個單位的安全邊距。這樣處理的目標是確保只包含當前區域,同時避免不必要的擴展。接下來,將嘗試檢查這一調整后的效果,確保沒有遺漏或其他潛在問題,并觀察這種方式是否能更好地控制范圍。
查看這會帶來什么
在修正了Z軸范圍之后,發現問題仍然存在,尤其是在實體漸變淡出的部分。懷疑問題出在ClampMapToRange
的實現,可能是因為編寫時有誤。檢查代碼后發現問題的根源:在處理范圍時,計算最大值和最小值,并進行加減運算后再除以它們,但沒有考慮支持負數范圍。原本的實現假設范圍必須大于零,但實際上,應該支持負數范圍。因此,這個問題的原因就是沒有正確處理負數的情況,導致無法正確判斷值是否大于零。
通過這一發現,能夠確定問題出在對范圍的處理方式上,需要調整代碼以支持負值范圍,從而解決這個問題。
修復 Clamp01MapToRange
經過檢查發現,之前編寫的代碼其實是正確的,只是由于忽略了負數范圍的處理,導致沒有按照預期工作。曾經認為代碼有問題,但實際上是理解上的錯誤。這次的發現確認了之前的代碼是合理的,問題出在對負數范圍的支持不夠,導致了錯誤的行為。
在面對這類問題時,始終保持“總是假設存在bug”的心態是重要的,尤其是在處理復雜的物理計算時。
查看淡入效果并讓 FadeBottom 生效
在進行調試時,發現淡出效果在頂層現在已經正確工作,采用了合適的代碼。之前的代碼本應該有效,但當時未能堅持正確的方法。現在,淡出效果從起始Z位置到結束Z位置,應該如預期般工作。然而,問題依然存在:效果消失了,可能是因為同一區域包含了某些過低的實體。
為了解決這個問題,需要重新審視相機的區域范圍,考慮從相機的位置向下擴展一些,通常可以向下擴展到2或3層樓,向上則查看1層樓。此舉可以避免不必要的區域擴展,尤其是在Z軸方向上的擴展。
接下來調整了相機范圍,但發現沒有正確執行。錯誤在于相機范圍計算時使用的矩形沒有正確設置最小和最大值。因此,需要通過手動設置這些值來確保正確的范圍計算。最終,調整為從相機位置向下擴展3層樓,上面1層樓,這樣可以避免不必要的復雜計算。
然而,問題依舊出現,即淡出效果的方向是錯誤的。通過回顧發現,這又是由于alpha值的設置問題。盡管代碼應該按照從起始位置到結束位置的順序寫,但實際上需要反轉alpha值,以便正確實現淡出效果。
查看所有效果并調整樓梯位置
現在,淡出效果已經能夠按照預期正常工作,可以在兩側進行淡出。然而,堆疊的樓梯相互之間存在碰撞問題,導致玩家無法走下另一側的樓梯。為了解決這個問題,決定采取一種方法,通過錯開樓梯的位置來避免碰撞。
具體做法是判斷樓梯的Z坐標是偶數還是奇數,通過檢查Z值的絕對值是否為偶數來決定樓梯的位置。如果Z值為偶數,則將樓梯放置在一個位置;如果Z值為奇數,則將樓梯放置在另一個位置。這樣做可以有效避免樓梯之間的相互碰撞問題。
走下各個層次并記錄一些待解決的問題
目前,系統已經能夠正常處理淡出效果,并且堆疊的樓梯碰撞問題得到了修復。接下來,觀察到的一個新問題是,某些元素的縮放效果不正確,特別是當物體距離遠時,它們似乎會快速縮放。這是因為沒有正確處理透視效果的問題。
此外,還有另一個未解決的問題,就是當前的“伙伴物體”并沒有被放置在正確的樓層上。這個問題的暴露正是為了后續的調整。雖然這些問題仍然存在,但它們也提供了一個清晰的目標,即要處理透視和地面處理相關的代碼。地面處理還沒有實現,當前的情況是相機的Z軸位置被誤認為是地面位置,因此物體跟隨相機的移動而下落。
整體來說,盡管存在一些問題,這些問題的暴露為后續的工作提供了非常清晰的方向,現在已經進入了能夠徹底解決Z軸相關問題的階段。接下來的重點是處理地面相關的功能,這樣就可以進一步完善引擎的穩定性和性能。
為什么有些樹是倒立的?
樹木出現倒立的原因是因為系統尚未正確處理透視效果。當前所使用的Z軸“調整值”只是通過乘法將物體在屏幕上的X和Y位置放大或縮小,以模擬物體靠近或遠離相機時的大小變化,但這種做法并沒有實際計算透視。因此,這只是一種不準確的方法。
具體來說,當Z值足夠負時(例如低于-0.0015),該表達式會變為負值,導致物體翻轉。因為這種方法是基于乘法,而不是正確的透視計算,物體會被鏡像翻轉。正確的透視計算應該使用除法,而不是乘法。通過除法,物體會隨著遠離相機而變小,但不會發生翻轉。
因此,解決這個問題的方法是引入真正的透視計算,通過除法來確保物體的縮放和顯示更加真實,避免出現翻轉現象。在實施之前,需要先在黑板上詳細講解透視原理,確保每個人理解這種轉換的過程。
頭部和身體實體偏離主角的位置是否應該隨主角一起縮放?
頭部和身體實體應該與主角一起縮放,當前它們的移動與Z軸有關。當實體移動時,它們被錯誤地當作與相機一起移動,而不是固定在正確的地面位置。問題的根本原因是目前系統沒有正確處理地面位置,導致實體隨著相機的位置變化而發生不正確的行為。
具體來說,地面處理的邏輯存在問題,這些實體被錯誤地認為與地面直接關聯,似乎在相機下方移動,就像是地面在它們下面移開一樣。當前的代碼沒有完成,導致無法確定實體為何會這樣移動,但可以確定問題與地面值的處理有關,可能是因為這些實體正在與相機一起移動,而不是固定在正確的地面高度。
為了測試和找出問題的根源,可以嘗試不更新相機的Z值,只讓實體沿著Z軸移動。如果不更新相機Z值,實體會保持在原位不動,表明問題出在地面和相機的關系上。目前系統沒有一個明確的地面處理方式,導致實體位置隨著相機的移動而改變。
解決方法是加強Z軸的處理,確保實體和地面的位置正確關聯,這樣問題就能解決。
什么是 Z-fighting,它在這種游戲中需要擔心嗎?
Z-fighting 是指在3D圖形中,由于兩個物體的表面非常接近,導致它們在渲染時不斷相互干擾,顯示出閃爍或跳動的效果。通常發生在兩個平面或多邊形幾乎在同一個位置時,尤其是在深度緩沖區的精度不足時。雖然Z-fighting是一個常見的問題,但在這種游戲引擎中不需要特別擔心它。
簡而言之,Z-fighting是因為渲染系統無法區分非常接近的兩個表面,導致它們在屏幕上產生視覺上的沖突。盡管這個問題在某些情況下可能出現,但在當前的開發中,暫時不需要特別關注這個問題。
Blackboard: Z-Fighting
Z-fighting 是和深度緩沖區相關的。如果沒有深度緩沖區,通常不會發生 Z-fighting。雖然可以在其他方面出現類似問題,但我這里先專注講解深度緩沖區中的 Z-fighting。
在三維圖形中,如果你沒有處理 Z-fighting,通常會依賴一個叫做深度緩沖區(Depth Buffer)的東西來解決隱藏面移除(Hidden Surface Removal)的問題。這個技術可以用來決定在兩個物體相交的地方,哪個物體應該遮擋另一個物體,從而避免錯誤的渲染。
舉個例子,假設有兩個立方體,一個離相機近,另一個遠一些。當渲染這些立方體時,正確的順序是先繪制遠離相機的立方體,后繪制靠近相機的立方體,這樣重疊的部分就能正確地被覆蓋。
然而在三維圖形中,由于物體的位置、角度的不同,如何判斷哪個物體應該先繪制并不總是那么簡單。如果物體比較復雜,可能需要不斷調整繪制順序。為了簡化處理,通常的做法是逐像素處理:每個像素都有一個深度值,告訴它距離相機的遠近。如果一個新的物體在繪制時,像素的深度值比原來的值小,就會替換原來的像素。
但如果深度計算精度不足,就會出現 Z-fighting。這個問題出現在計算機的浮點數運算中。如果兩個物體非常接近,它們之間的距離差異可能非常小,以至于在浮點數表示中無法精確區分。這種情況下,當物體越來越遠時,精度會丟失,導致這兩個物體的深度值變得無法區分,從而導致 Z-fighting 的現象——物體在重疊區域交替顯示,產生不希望看到的“閃爍”或“鋸齒”效果。
特別是在深度值非常接近時,深度緩沖區的精度可能會不足,導致兩個物體的深度信息丟失,從而產生 Z-fighting。比如,當一個物體的表面比另一個物體的表面更接近相機時,如果浮點精度不足,計算機會將它們的深度值視為相同,從而導致渲染錯誤。
此外,Z-fighting 還可能出現在沒有深度緩沖區的情況下,比如在某些情況下物體的排序會受到浮點數精度的影響。沒有深度緩沖區時,你可能會依賴排序算法來決定物體繪制順序,但如果 Z 值過大或精度不足,可能會出現錯誤的排序,導致 Z-fighting。
總體來說,Z-fighting 的本質是由于浮點數計算精度導致深度值無法區分,最終導致錯誤的圖形顯示。