Unity3D獨立遊戲開發日記(二):擺放建築物

在沙盒遊戲裏,能自由建造是很重要的特色,好比說風靡全球的《個人世界》,用一個個方塊就能搭建出規模宏大的世界。甚至有偏激的人說,沒有自由建造,就不是一個真正的沙盒遊戲。的確,沙盒遊戲的魅力有很大一部分是能自由構建一個遊戲世界。看着本身一磚一瓦搭建起一個城堡世界會頗有成就感的。程序員

現現在的手遊,大多數就是一個爭鬥和炫耀的世界。不論是傳奇類的狂霸拽酷,仍是連連看,消消樂等好友排名,就是消費國人的虛榮心。其實,遊戲是第九藝術,要上升到藝術的角度。在遊戲裏,玩家須要一種情感的宣泄和寄託以及體驗。數據庫

說了這麼多,仍是回到正題。我是如何在本身編寫的獨立遊戲《中世紀之路》裏實現建築物的擺放呢?函數

在實現這個功能的時候,我首先考慮的不是代碼。而是考慮其餘遊戲是如何實現這樣功能的,有那些能夠借鑑的地方。我首先想到了《魔獸爭霸》裏建築物的擺放,能夠自由的拖放。而後想到了《部落衝突》(簡稱COC)裏的建築放置方式,在COC裏建築是按格子擺放的,在一個平面上。動畫

在個人遊戲《中世紀之路》裏,我既不想讓玩家一磚一瓦的搭建建築,又想讓玩家一下就把建築總體放置到地上了。我以爲像搭積木那樣,既能夠節省玩家時間,又有建造的樂趣。選定了這種方式後,我就要考慮建築模塊的數據儲存方式了:我須要儲存單個模塊的三維空間裏的座標值(x,y,z的值),同時爲了讓模型選擇,我還須要儲存模型的旋轉角度數。spa

而後,我還須要考慮如何用鼠標去執行這個操做。我構想的方案是:點擊揹包裏的物品後,一個模型就動態產生,而後跟隨鼠標在地面移動。而後按"E"鍵就放置到地面上鼠標所指的位置(E鍵放置,是我學《獸人必須死》得來的)。而組件的旋轉呢?我考慮的是讓鼠標滾輪(也就是中鍵)滾動時,就繞着Y軸旋轉。固然若是更近一步,能夠作到繞三個軸都能自由旋轉。具體操做見下圖:3d

建築擺放動畫code

使用鼠標放置篝火orm

經過上面的操做,咱們能夠看到代碼的實現效果很好,完美達到了咱們的需求。不過想通了上面的操做原理後,還須要咱們動腦筋來構思,如何用代碼來實現這些操做功能。這對新手來講可能過難了點,但對於有經驗的開發者就能比較快的找到近似的解決方案,而後加以改進。blog

我首先想到的是我曾經在手機上作過2D積木的搭建功能。把咱們的操做動做拆解開來,無非就是三個步驟:遊戲

1.第一次按下手指或者鼠標,找到初始座標,讓物體動態出如今座標位置上。

2.而後判斷移動狀況,讓物體跟隨鼠標或者手指的移動。

3.最後擡起手指或者鼠標,讓物體固定在最後的座標位置,把座標數據寫入到文本或者數據庫裏。

想清楚了這三個步驟,咱們就內心底了,咱們只要實現了這三步操做代碼,基本上物體擺放功能就能夠實現了。

在我實現第一個步驟的時候,我就遇到了個問題。我以前在寫搭積木遊戲的時候是2D的,座標很好獲取。可是在《中世紀之路》裏,我但是要獲取的是鼠標在地面上的座標點啊。我開始用的是兩行代碼:

Vector3 mousePosition= Input.mousePosition;    //獲取鼠標所在的座標

Vector3 mouseWorldPosition =Camera.main.ScreenToWorldPoint(mousePosition) ; //把鼠標的座標變成3D遊戲世界裏的空間座標

 

我覺得個人思路是沒問題的,結果運行代碼一看。哈哈,建築物徹底不是擺在地面上的啊,是在空中的啊。後來查了相關文檔才知道,這個鼠標位置是鼠標在屏幕這個立體面上的位置(你能夠想象屏幕是一個透明的立體牆,這個牆是樹立在地面上的)。再說得專業點,是從主攝像機爲起點,鼠標所指爲終點的一個射線,與屏幕所在立體面相交的點。對於這個立體面的直觀感受,你們能夠看看在3D空間裏2D UI界面所在的那個面。

因此,上面兩行代碼是不可以解決問題的。不過這麼一分析,我就接觸到了射線的概念。我轉念一想,若是我找到這個射線和地面相交的焦點不就好了嘛!咱們的思路就變成了如下的僞代碼:

1.建立一個從主攝像機爲起點,鼠標所指爲終點的一個射線Ray。

2.找到Ray和地面Terrain的交點position。

3.把物體的座標動態建立於position。

核心代碼以下:

if (Input.GetMouseButton(0))
 {
     Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

       RaycastHit hit;

       if(Physics.Raycast(ray, out hit))
       {

               if(hit.transform.name=="Terrain")
               {
                           position = hit.point;//獲得與地面碰撞點的座標
               } 
        }
}

 

解決這個核心難題後,移動的代碼就很好寫了。只要在手指或者鼠標移動的時候,動態更新物體的座標爲新的position就能夠了。旋轉物體的代碼也能夠寫到一塊兒,動態更新物體的旋轉度就能夠了。這段代碼很容易寫了,我就不貼出來了,新手能夠鍛鍊自我動手能力。老手早就不用看在眼裏了。固然須要提醒的是這段代碼是須要在update函數裏去運行的。

最後的固定物體座標的代碼,也就演變成了把最後的position記錄於文本或者寫入數據庫了。這些代碼都不是有多難寫的。

最後回顧下,咱們整個解決問題的思路:

構思操做步驟和方式->分解操做步驟->用代碼實現分解後的操做步驟->完善和修正代碼

若是你們問我要整個代碼,坦白的說:我以爲"授人於魚,不如授於漁"。你們能獲取正確解決問題的思路就夠了,而後記住核心代碼就能夠了。作程序員到一個「手中無劍,心中有劍」的境界就夠了。固然新手仍是多練練劍,比劃比劃下招式。

 

PS:遊戲DEMO試玩羣:198035671  Unity3d技術交流羣:308185833  鬥魚遊戲開發直播地址:www.douyutv.com/unity3d

相關文章
相關標籤/搜索