U3D DotH教程2

<a target=_blank href="http://weibo.com/DoubleIris">微博@捲毛的呈秀波</a>

上回我們已經建立了遊戲中的基本要素,這回我們要建立一個交互界面。

作爲一個塔防遊戲,他的互動要素有以下

  1. 點擊按鈕
  2. 在空地放置炮臺

簡言之就是操作界面的建立。

UI界面

我們來想一下UI界面的要素

  1. 按下按鈕之後可以創建炮臺
  2. 能在怪物的移動軌道之外建立炮臺

僞代碼可以寫成

if(buttonpressed == TRUE)
  Tower.Render.enabled = true;
if(Tower.Render.enabled == true){
  if(mousecontact.Object != path&&!=tower){
  createTower(Pos(mouse.position));
  Tower.Rander.enabled = false;
}
}

前期工作

要完成這兩個功能,我們需要了解幾個函數

Object.Instantiate()

這個函數是不是很眼熟,沒錯,這就是上一篇中我們用來複制Monster 的克隆函數,具體細則參照上一篇。


這個函數用來獲取鼠標按鍵的返回消息,參數分別對應左右中鍵。



這個函數用於生成GUI界面的按鈕,返回按鈕是否被按下。一共有六個重載,挑選自己所需要的使用就好


用來返回射線是否觸碰到物體

 不太懂沒關係,接下來我們將會實際使用到。

首先將我們上次在場景中創建的Tower隱藏或者移除

邏輯1

於Project-》Script下新建一個腳本,名爲createtower 。

首先我們要繪製GUI按鈕,在MonoBehavior中添加如下代碼

void OnGUI()
{
  if(GUI.Button(new Rect(0,0,64,64),"點擊這裏”))
  Debug.Log("click");
}
將它掛載到Main Camera上
點擊播放,可以看見下圖

左上角出現了按鈕,並且點擊之後consle會輸出信息“click”



這裏就要了解OnGUI這個過程了,他是專門用來繪製GUI可見對象的一個函數。我們使用GUI。Button生成的按鈕在這裏會被調用。具體說明請戳我

而在這裏我們需要做的事情是,按下按鈕後,進入可以放置炮臺的狀態。所以我們要新建一個bool 類型的變量用來管理狀態。

bool isCreate = false;//默認關閉
然後修改我們的OnGUI

void OnGUI()
    {
        if(GUI.Button(new Rect(0,0,64,64),"點擊這裏"))
            isCreate = true;
        if (isCreate == true)
        {
            GUI.Button(new Rect(Input.mousePosition.x - 32, Screen.height - Input.mousePosition.y - 32, 64, 64), "這裏是模型");
            Debug.Log("Click");
        }
    }
在這裏我們又生成了一個實時跟隨鼠標的GUIButton,用來告訴玩家當前處於可以創建炮臺的狀況= =因爲我沒模型所以用了String來代替。

檢查一下效果


邏輯2

現在我們擁有了可以操作的按鈕但是還是不能生成炮臺。

生成炮臺需要兩個判斷

  1. 是否處於可以創建炮臺的模式下
  2. 鼠標點擊的地方是不是path

第一個判斷我們已經使用bool變量來存儲了,現在要解決第二個判斷。這個就要用到之前出現的兩個函數Raycast和GetMBDown。

聲明兩個變量,Ray,和RayHit用於Raycast的調用

public Ray distance;

public RaycastHit hit;

還要聲明一個gameObject類,用來掛載Tower

然後在Update中添加下列代碼

void Update () 
    {
        distance = camera.ScreenPointToRay(Input.mousePosition);//獲取從攝像機的投影平面向鼠標位置發射的射線
        if (isCreate == true)//前提需要能夠創建炮臺
        {
            if (Physics.Raycast(distance, out hit))//如果射線觸碰到了物體
            {
                if (hit.collider.tag != "path")//前提2不是怪物的路徑
                
                {   
                    if (Input.GetMouseButtonDown(0) && hit.collider.name != "Tower")//按下左鍵切鼠標觸碰到的碰撞體不是塔               
                    {
                        Object.Instantiate(mTower, hit.collider.transform.position, Quaternion.identity);
                        isCreate = false;//把炮臺複製過來,並且關閉可以創建的狀態
                    }
                }
            }
        }
    }
然後運行一下

如果你和我的設置一樣會發下有兩個個問題

  1. 創建的炮塔都重複在中間,並且一個疊加在另一個上面
  2. 炮臺下沉在地面之下

第二個問題很簡單,因爲我們的圓柱本來就要上升0.5個單位,所以在Instantiate (的transform後面加Vec(0,0.5,0))就能夠讓炮臺準確的在地面上浮現了。


第一個問題好像完全不符合情理,我們已經在代碼中做了判定,卻依舊能夠在炮塔身上建立炮臺?

這個問題我們需要深究一下。

重新看我們的代碼:

if (Input.GetMouseButtonDown(0) && hit.collider.name != "Tower")             
          
我們可以看見我們所做的判斷是判定射線觸碰到的物體名字是否爲Tower,但是實際觀察一下我們的組件欄

他的名字是Tower(Clone)!!!  你是不是完全沒有在意!


再看另一行代碼

 Object.Instantiate(mTower, hit.collider.transform.position, Quaternion.identity);
這行代碼將我們的炮臺複製到的地方是射線觸碰到物體的位置(中心),這不符合常理,因爲地面是一個物體,我們不可能將所有炮臺都建立在地面中心。

關於這一點我們有兩種解決方案:

  1. 在地圖上建立一個個炮架,這樣炮臺就會建立在炮架上。
  2. 把炮臺的複製位置換成射線觸碰的點。

在這裏,加入選用第一種方案的話,勢必就要再給炮架添加一個判斷腳本,太繁瑣所以我們直接將hit.collider.transform.position改變成hit.point.position.

最後我們的代碼長成這個樣子

void Update () 
    {
        distance = camera.ScreenPointToRay(Input.mousePosition);
        if (isCreate == true)
        {
            if (Physics.Raycast(distance, out hit))
            {
                if (hit.collider.tag != "path")
                {
                    {   //getMouseDown(x) :x=0,left button;1,right button;2,middle button)
                        if (Input.GetMouseButtonDown(0) && hit.collider.name != "Tower(Clone)")
                        {
                            Object.Instantiate(mTower, hit.point + new Vector3(0f, 0.5f, 0f), Quaternion.identity);
                            isCreate = false;
                            Debug.Log(hit.point );
                            Debug.Log(hit.collider.name);
                        }
                    }
                }
            }
        }
    }


然後你就能看見下圖


耶,我們的塔防遊戲又完善了一步。



ps,筆者雜談

最近由於各種瑣碎的事情,導致上週的教程完全沒有更新,今天突然有一個讀者諮詢我教程,感覺自己的努力也是有回報的。

於是登陸了CSDN,看見還給我的博客頒發了持之以恆的徽章。頓時覺得只要你們能從筆者的簡陋教程中獲取一些知識,筆者再辛苦也是值得的。


我是妖哲,明天見~

發佈了40 篇原創文章 · 獲贊 6 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章