Unity知識三:兩種方式實現切水果的刀痕

Unity作爲遊戲開發平臺之一,還是有很多實用的小技巧的,今天來學習一下怎樣用兩種方式來顯示切水果遊戲中的刀痕:
1.正常顯示下的刀痕:
什麼叫正常顯示下的呢?我們所接觸過的切水果遊戲一般都是2D遊戲,那我們知道,2D遊戲可以用Unity直接來做,還可以使用NGUI、UGUI或者其他方法通過UI來實現。
所以我們第一種方法就是不借助UI來做。
首先來看看我們刀痕的素材:(需要的同學可以右鍵另存。^_^)
這裏寫圖片描述
打開Unity:
這裏寫圖片描述
新建一個空遊戲體,命名爲“BackGround”,然後在組件面板中添加組件GUI Texture:(創建出來的物體不要忘記reset一下哦~)
這裏寫圖片描述
找到Texture屬性,點擊後面的圓圈,爲它選擇一個背景圖片:
這裏寫圖片描述
背景素材:
這裏寫圖片描述
添加好背景圖片之後,我們看Scenes面板和Game面板,發現了兩個問題:
這裏寫圖片描述
1.在Scenes面板中,添加上去的圖片看不到;
2.Game面板中圖片的位置有點不對。

Scenes中看不到的情況,由於我也是小白,搞不懂原理,但是我猜是因爲GUITexture是UI的一部分,所以在Scenes面板中有時候顯示效果不好,至於怎麼設置去讓它顯示出來,我暫時還不知道,我現在是以Game面板上的顯示情況做參考的。

Game面板下顯示不對,我們把它Transform下的Position設置爲(0.5,0.5,0):
這裏寫圖片描述
這樣就可以了。

接下來我們再新建一個空遊戲體,將其命名爲Knife,併爲其添加LineRenderer組件:
這裏寫圖片描述 這裏寫圖片描述

我們在上面右圖中可以找到Materials屬性,下面有Size和Element 0.
因爲Materials是一個Materials類型的數組,Size是數組的長度,Element是數組元素的值,此時Size爲1,那麼它就只有一個元素,索引值爲0,Element 0因此而來。

我們剛剛創建的遊戲體是用來顯示刀痕的,那麼我們就要把上面我們的刀片素材給它。
大家會發現,直接把圖片拖給Element 0不成功,因爲Element 0是Material類型的,而圖片還不是材質,它現在只是一張圖片,對應的材質還沒有生成。
我們直接把圖片拖給Knife遊戲體,Unity會自動爲這張圖片創建一個材質Material,並把這個材質賦給Element 0;
這裏寫圖片描述
大家可以在Scenes面板中看到它。

接下來,我們找到Line Renderer下的position屬性,發現它也是一個數組,這個數組是幹什麼用的呢?他就是用來畫出Line Renderer的關鍵屬性。

實際上Line Renderer是這樣的:你給我幾個座標,我把相應的材質在幾個座標之間渲染出來。現在:Element 0爲(0,0,0)Element 1爲(0,0,1),那就是說,把圖片在座標(0,0,0)和(0,0,1)之間顯示出來,因爲兩點確定一條直線嘛~對不對?

既然我們瞭解了Line Renderer的原理,那麼我們就知道了,我想用鼠標畫出一條線,我只要獲取到鼠標左鍵按下時的座標和鼠標左鍵擡起時的座標,然後把它們分別給Element 0和Element 1,那這條線不就是畫出來了嗎?

那我們就開始寫腳本咯:

using UnityEngine;
using System.Collections;

public class tes : MonoBehaviour {

    Vector3 pos1;     //定義起點座標
    Vector3 pos2;     //定義終點座標

    LineRenderer myLinRenderer;     //定義一個LineRenderer對象

    // Use this for initialization
    void Start () {
        myLinRenderer = GetComponent<LineRenderer>();     //給LineRenderer對象初始化
    }

    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(0))      //當鼠標左鍵按下的時候
        {
            pos1 = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y,1));     //將起點座標記錄下來
        }

        if (Input.GetMouseButtonUp(0)) 
        {
            pos2 = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y,1));     //將終點座標記錄下來
            myLinRenderer.SetPosition(0,pos1);
            myLinRenderer.SetPosition(1,pos2);     //分別將起始座標和終點座標付給相應的變量
        }
    }
}

寫好之後我們先來想一下,LinRenderer是給它設置座標它就開始渲染了,那上面我們寫好的腳本也就是說:當我鼠標鬆開的時候,這條線才能畫出來,而當鼠標一直按下的時候,這條線我們是看不到的。

我們把這個腳本給我們創建的遊戲體Knife,運行後:
這裏寫圖片描述

我們可以看到,在Scenes面板中確實有一條類似刀痕的東西,但是有兩個問題:
顏色和我們的好像不太一樣,那是因爲在這裏:
這裏寫圖片描述
有Parameters屬性,這裏可以設置刀片的起始寬度和終點寬度,起始顏色到終點顏色的過渡,默認是白色的。

另一個嚴重的問題是:在Game面板中根本不顯示這條刀痕,左側的Scenes面板中明明是能顯示的!
我們看運行的時候,BackGround的位置是(0.5,0.5,0),攝像機的位置是(0,1,-10),而且是正交攝像機:
(0,1,-10)
此時刀片的兩個座標的Z都是-9,說明不是腳本的問題:
這裏寫圖片描述
按理來說刀片是完全能顯示的,我們再檢查一下層Layer,即使重新設置了Layer也還是無法顯示。

好像有點懵逼了。。。

經過一系列的檢查,終於找到了癥結所在,從一開始我們就錯了,還記得一開始我們說那個BackGround在Scenes面板中看不到對吧?因爲我們添加的是GUITexture,這裏我們做錯了,不應該添加GUITexture組件,而應該是SpriteRenderer:
這裏寫圖片描述
這下我們在Scenes面板和Game面板下都可以看到了:
這裏寫圖片描述

Game下顯示不對,我們把BackGround的Scale調整爲(2.4,2.4,1):
這裏寫圖片描述

然後我們把BackGround和Knife的Layer都改爲默認,(因爲大家可能發現截圖中他們的Layer是NGUI,那是因爲我在做後面的一種方法的時候沒有改過來。),同時,攝像機的CullingMask保持默認的Everything。
我們再來運行一下:
鼠標按下,並移動一段距離,沒有反應:
這裏寫圖片描述
當鬆開鼠標的時候:
這裏寫圖片描述

啊哈哈哈哈!
終於粗來了!

而且好帥氣的對不對?

沒錯,就是這樣。

之前發現了問題,爲什麼我沒有把之前的內容修改掉,而是在文章中用不少的篇幅來找錯誤呢?那是因爲我覺得我們所犯的每一個錯誤對我們自身而言都十分有意義,當我有一天回頭看看這篇文章的時候,我會對GUITexture和SpriteRenderer有十分深刻的印象,就醬~

言歸正傳:
但是,我們又發現了一個問題:這裏面的刀痕只有一條,那我現在所畫的刀痕不是直線,而是有拐點的呢?它還是隻是顯示一條連接起始點和終點的刀痕,中間的拐點全都沒有表現出來。

既然這樣,那麼我們把中間的拐點也都記錄下來不就好了嗎?

我們這樣來思考:當我鼠標左鍵按下的時候,每隔0.2秒記錄一次鼠標的位置,然後把它加到那個位置座標數組中:
其實這個位置座標更像一個泛型,因爲它有數組的性質,但是又沒有長度限制:
這裏寫圖片描述 這裏寫圖片描述

我們可以這樣,每隔0.2秒,就讓這個泛型的長度加1,然後把座標填進去,只要設置了兩個或兩個以上座標,這條線就能畫得出來:

修改代碼如下:

using UnityEngine;
using System.Collections;

public class tes : MonoBehaviour {

    Vector3 pos1;
    Vector3 pos2;

    LineRenderer myLinRenderer;

    int count=0;    //定義一個變量,用來修改泛型的長度

    float time = 0.2f;  //定義一個時間間隔
    // Use this for initialization
    void Start () {
        myLinRenderer = GetComponent<LineRenderer>();
    }

    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(0)) 
        {
            pos1 = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y,1));
            myLinRenderer.SetVertexCount(1);    //第一次按下鼠標左鍵時,應該有了一個點,所以把節點的數目設置爲1
            myLinRenderer.SetPosition(0, pos1);     //有了一個節點就設置一次座標,而不是單單記錄座標
        }

        if (Input.GetMouseButton(0))    //當鼠標一直按下的時候
        {
            time -= Time.deltaTime;     //時間進行遞減
            if (time <= 0)      //當時間減小到0或0以下時,
            {
                time = 0.2f;        //把時間重置
                count++;        //節點數自增

                Vector3 pos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 1));     //紀錄此時的座標值
                myLinRenderer.SetVertexCount(count);        //每隔0.2秒,就增加一個節點,增加一個點的方法就是SetVertexCount()方法
                count--;        //count還要自減,因爲在設置位置的時候,索引是比節點數小1的
                myLinRenderer.SetPosition(count,pos);       //設置這個增加的節點的位置
                count++;        //最後,因爲增加了一個節點,所以count是要增加1的

            }
        }

        if (Input.GetMouseButtonUp(0))      //當鼠標左鍵擡起的時候,依舊要紀錄最後一個點的座標,最終把count重置爲0
        {
            count++;
            pos2 = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y,1));
            myLinRenderer.SetVertexCount(count);
            count--;
            myLinRenderer.SetPosition(count,pos2);
            count = 0;
        }
    }
}

代碼中加了註釋的地方就是修改的地方,對於count的值得問題,我用的是這種笨方法,需要思考一下才能理清。

保存運行,就得到了:
這裏寫圖片描述

效果已經出來了,然而,LineRenderer在拐彎的地方自己處理不好,有時候就會變成這樣:
這裏寫圖片描述
這是因爲拐彎的時候涉及到了寬度的變化,寬度變化就會出現這種情況。

我們把刀片的Parameters屬性下的Start width和Endwidth的值設置不同,比如一個爲1,一個爲3:
在把第一個腳本掛上來,運行一下:
這裏寫圖片描述
我們會發現,怎麼都不是一條直線了,因爲起始寬度是1,終點寬度是3,1到3不是自然過渡的,所以就好像是在中間突然少了一塊一樣,這是LineRenderer的問題,同理,我們在轉彎的時候遇到的問題與它類似。

不過可以適當調小它們的寬度來使其更自然一些,比如起始和終點寬度都設爲0.3:
這裏寫圖片描述
這樣就稍微好一點,但是解決不了根本問題,要徹底解決需要自己寫腳本來控制。

這裏我們就把第一種方法給講完了,接下來說第二種方法:在NGUI中實現鼠標畫刀痕:
Ctrl+N新建一個Scenes,命名隨意,導入NGUI的包。
找到NGUI->Open->Prefab Toolbar,
這裏寫圖片描述
這裏寫圖片描述
把左上角的背景拖入Hierarchy面板中:
這裏寫圖片描述
找到BG - Stripes,把它刪掉:
這裏寫圖片描述
依次打開:這裏寫圖片描述
這裏寫圖片描述
點擊Create,選擇目錄並命名後,點擊保存,不要關閉這個窗口,在Project面板中找到背景圖片,我們會發現Create按鈕變成了Add/Create,點擊它。這張背景圖片後面出現了Update字樣:
這裏寫圖片描述
現在可以關閉這個窗口了。

選中Hierarchy中的Control - Background,在右側的Inspector面板中找到UISprite,點擊Atlas:
這裏寫圖片描述
彈窗如下窗口:
這裏寫圖片描述
找到你剛纔命名的那個prefab,如果沒有,就點擊下面的Show All,然後點擊對應後面的Select,然後在點擊Sprite:
這裏寫圖片描述
在彈出的面板中選擇背景圖片,並雙擊它。
這裏寫圖片描述
我們發現一片漆黑:這裏寫圖片描述
點擊右面的ColorTint(點擊它右側的黑色區域):
這裏寫圖片描述
彈出如下窗口:
這裏寫圖片描述
用鼠標將方框左下角的白色圓圈移到左上方的白色區域:
這裏寫圖片描述
結果就能正常顯示了:
這裏寫圖片描述

上面都是一些廢話,基本上大家都會操作的。

接下來按照上面相同的方式創建刀片,並把上一個腳本拖給它(做一點點修改):

using UnityEngine;
using System.Collections;

public class tes : MonoBehaviour {

    Vector3 pos1;
    Vector3 pos2;

    LineRenderer myLinRenderer;

    int count=0;   

    float time = 0.2f;  

    public Camera myCamera;     //聲明一個公開的攝像機類型(天哪,什麼類型都有。。。)
    // Use this for initialization
    void Start () {
        myLinRenderer = GetComponent<LineRenderer>();
    }

    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(0)) 
        {
            pos1 = myCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, -1));     //這裏要做修改
            myLinRenderer.SetVertexCount(1);    
            myLinRenderer.SetPosition(0, pos1);     

        }

        if (Input.GetMouseButton(0))    
        {
            time -= Time.deltaTime;    
            if (time <= 0)      
            {
                time = 0.2f;        
                count++;        

                Vector3 pos = myCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, -1));       //這裏要做修改   
                myLinRenderer.SetVertexCount(count);        
                count--;        
                myLinRenderer.SetPosition(count, pos);       
                count++;        

            }
        }

        if (Input.GetMouseButtonUp(0))      
        {
            count++;
            pos2 = myCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, -1));     //這裏要做修改
            myLinRenderer.SetVertexCount(count);
            count--;
            myLinRenderer.SetPosition(count,pos2);
            count = 0;
        }
    }
}

加註釋的地方就是修改的地方,把所有Camera.main.ScreenToWorldPoint全部改爲myCamera.ScreenToWorldPoint(myCamera要看你的具體命名。)
還有後面的Z軸值也要改爲-1.

Ctrl+S保存腳本,回到Unity中,選中刀片,會看到多了一個myCamera:
這裏寫圖片描述

把左側的Camera沿着箭頭拖過去:
這裏寫圖片描述

運行:
這裏寫圖片描述
寬度自己調一下吧,如果不顯示,設置一下Knife的Layer和Camera的Culling Mask就好了。

只需要修改一點點的腳本就能運用在NGUI中了。

嗯,這就是我個人目前實現切水果刀痕的兩種方式,如果大家有什麼好的辦法歡迎交流哦~

同時,文章裏有什麼有誤的地方,歡迎大家批評指正!謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章