找回密碼
 注冊帳號

掃一掃,訪問微社區

士郎 我們來用Unity復刻一下《黃金礦工》

13
回復
1940
查看
打印 上一主題 下一主題
[ 復制鏈接 ]
排名
1
昨日變化

8031

主題

8589

帖子

3萬

積分

Rank: 16

UID
1231
好友
186
蠻牛幣
12041
威望
30
注冊時間
2013-7-29
在線時間
4103 小時
最后登錄
2019-8-12

活力之星原創精華達人突出貢獻獎財富之證游戲蠻牛QQ群會員蠻牛妹VIP

馬上注冊,結交更多好友,享用更多功能,讓你輕松玩轉社區。

您需要 登錄 才可以下載或查看,沒有帳號?注冊帳號

x
以前玩過一個摸魚必備游戲《黃金礦工》,開這個坑就可以邊摸魚邊填坑了。



經過上述不超過5分鐘的、大起大落的心理過程后,便有了這期的文章。
雖然黃金礦工比較簡單,但其中細枝末節較多。文章只會講解較為重要的技術點,其余部分歡迎參考后續工程代碼食用。
模擬繩子
黃金礦工游戲中,玩家通過按鍵操作并發射鉤子來挖取金礦,鉤子與絞盤之間有一條繩子進行連接,這條繩子我們使用Unity提供的LineRenderer組件來進行實現。
由于素材的限制,我們使用鉤子的這張圖片做為玩家的本體,并在上面添加LineRenderer組件,然后在Materials選項中選擇默認的精靈圖材質(Sprites-Default),然后將Order in Layer選項修改為1,防止被背景2D物體遮擋。其中,Positions選項是用來設置線段的2點,LineRenderer組件會在游戲運行時自動在2點之間進行連線。而我們也是在代碼中動態修改這2點的值,來實現繩子的效果。大致設定如圖:

LineRenderer設置
接下來,在絞盤的位置新建一個空物體,用于確定線段的起點。然后在代碼中更新Positions選項中點的位置即可。代碼如下:
[AppleScript] 純文本查看 復制代碼
public class Player : MonoBehaviour {
    public Transform startTrans;    //起始點
    LineRenderer lineRenderer;
    void Start() {
        lineRenderer = GetComponent<LineRenderer>();
        lineRenderer.startWidth = 0.1f;//修改線條寬度
    }
    void Update() {
        UpdataLine();
    }
    public void UpdataLine()
    {
        lineRenderer.SetPosition(0, startTrans.position);
        lineRenderer.SetPosition(1, transform.position);//設置線條2點的位置
    }
}

完成后效果如下:
線條效果
旋轉
游戲中,鉤子總是繞著絞盤來進行旋轉。使用RotateAround這個函數就可輕松解決,難點是如何限制鉤子只在下方進行旋轉操作,而不會旋轉到上方。此處,我們使用向量之間的夾角來進行判斷,鉤子是否旋轉出邊界。由于素材的問題,鉤子對應的方向是Up軸的正下方。如下圖:

人物朝向
我們就需要通過Up軸的反方向,與絞盤的Right軸之間的夾角,來進行旋轉的處理。代碼如下:
[AppleScript] 純文本查看 復制代碼
public enum RotaDir
{
    left,
    right,
}//定義旋轉方向枚舉
    public RotaDir nowDir;    //玩家當前的旋轉方向
    public float angleSpeed;  //旋轉速度
    public void PlayRotate()
    {

        float rightAngle = Vector3.Angle(transform.up * -1, Vector3.right);//計算玩家前進方向與Right的夾角


        if (nowDir == RotaDir.left)
        {
            if (rightAngle < 170)
            {   //在可旋轉范圍內按當前方向繼續旋轉
                transform.RotateAround(startTrans.position, Vector3.forward, angleSpeed * Time.deltaTime);
            }
            else
            {
                nowDir = RotaDir.right;//超出范圍,改變方向進行旋轉
            }

        }
        else
        {
            if (rightAngle > 10)
            {
                transform.RotateAround(startTrans.position, Vector3.forward, -angleSpeed * Time.deltaTime);
            }
            else
            {
                nowDir = RotaDir.left;
            }

        }
    }

完成后效果如下:



移動
通過上面的步驟,我們可以很輕松的知道,鉤子的朝向總是自己的Up軸的反方向。那么移動的方向也是如此。只要一直朝這個方向移動就行了,返回也是同樣的道理。代碼如下:
   
[AppleScript] 純文本查看 復制代碼
 public float angleSpeed;
    public void PlayMoveForward()//前向移動
    {
        transform.position += transform.up * -1 * moveSpeed * Time.deltaTime;
    }
    public void PlayBackMove()//返回移動
    {
        transform.position += transform.up * moveSpeed * Time.deltaTime;
    }

完成后效果如下:



道具交互
不同的道具有不同的交互效果,本作中主要的效果就是得分增加,道具增加,以及玩家移動減速了。
道具效果
新建一個PropScript腳本,專門用來記錄當前道具的接觸效果或者獲得分數。其中通過道具的類型來進行處理。代碼如下:
[AppleScript] 純文本查看 復制代碼
public enum PropType
{
    None,
    Fraction,    // 分數類型道具
    Boom,    // 炸彈
    Potion,    // 雙倍藥劑
} //定義道具類型枚舉
public class PropScript : MonoBehaviour {

    public int fraction;// 當前道具分數
    public PropType nowType;// 當前道具類型
    public int scaleLevel=1;  //當前道具的縮放道具  默認為1  用于計算玩家鉤住時的速度
    public void UseProp()//使用道具的方法
    {
        switch (nowType)
        {
            case PropType.Fraction:
                GameMode.Instance.AddFraction(fraction);//分數增加
                break;
            case PropType.Potion:
                GameMode.Instance.isDouble = true;//開啟雙倍開關
                break;
            case PropType.Boom:
                GameMode.Instance.AddBoomProp();//添加炸彈道具
                break;
        }
    }
}

人物減速
我們使用觸發器來檢測鉤子是否抓中了物體,如果抓中了。就在此時更改玩家的速度。由于之前在PropScript中設置了縮放的等級,我們可以通過這個來計算新的速度(PS:人物速度 = 原人物速度-原人物速度*減速系數*縮放等級)。代碼如下:
[AppleScript] 純文本查看 復制代碼
public class Player : MonoBehaviour {
...
    private void OnTriggerEnter2D(Collider2D collision)
    {
        PropScript propScript = collision.gameObject.GetComponent<PropScript>();
        if (propScript != null)
        {
            float tempDistance = Vector3.Distance(transform.position, propScript.transform.position);
            propScript.transform.position = transform.position + transform.up * -1 * tempDistance;//位置修正
            propScript.transform.SetParent(transform);//設置父物體用于拖拽移動
            ComputeSpeed(propScript.scaleLevel);
        }
    }
    public void ComputeSpeed(int scaleLevel)//計算新的玩家速度
    {
        moveSpeed = moveSpeed - moveSpeed * 0.15f * scaleLevel;
    }
}

道具生成
黃金礦工游戲中,有多種道具來豐富游戲的內容。在進行道具生成之間,先準備好對應的游戲數據,能夠使開發事半功倍。
數據準備
首先制作所有的道具的2D預制體,并統一將他們的Order in Layer參數改為1(PS:由于背景的2D物體對應參數設置的為0,為了能夠覆蓋在背景之上,就需要調高參數),然后將他們保存在Resources/Prefabs文件夾下(PS:子文件夾可以隨便設置,但是必須得是在Resources文件夾下),方面后續代碼的讀取。如下:

不同用途的預制體
接下來,新建一個Gamemode腳本,來控制并管理游戲中的道具生成以及勝利相關功能等。然后在里面初始化對應的道具數據。代碼如下:
[AppleScript] 純文本查看 復制代碼
public class GameMode : MonoBehaviour {
    public Dictionary<string, GameObject> tempLates;        //存儲所有的道具預制體模板
    public string[] objNames;       //所有分數道具的物體名稱
    public int[] fractionData;      //道具的分數數據
    public int[] targetFraction;    //每一關的目標分數
    public float[] scaleData;       //縮放數據
    public string[] propName;       //特殊道具名稱
    public float minX;       //生成的最小X值 面板賦值
    public float maxX;       //生成的最大X值 面板賦值
    public float minY;       //生成的最小y值 面板賦值
    public float maxY;       //生成的最大y值 面板賦值
    void Start() {
        targetFraction = new int[] { 3000, 4000, 5000, 7000, 9000, 12000 ,15000,20000,25000};
        objNames = new string[] { "Diamonds", "gold", "goldTwo", "stoneOne", "stoneTwo" };
        fractionData = new int[] { 1000, 300, 500, 100, 150 };
        propName = new string[] { "explosive", "Potion" };
        scaleData = new float[] { 1.0f, 1.2f, 1.5f, 1.8f, 2.0f };//手動填入關卡的相應數據
        InitData();//初始化 讀取數據并填充字典
    }
}

其中設置的道具生成的范圍大致如下圖:

道具生成范圍
道具生成
隨機位置
已經準備好了對應的數據,接下來就是根據對應數據生成道具。首先隨機道具生成的位置,通過之前GameMode設置的生成數值,我們可以輕松得到在范圍內的隨機坐標。代碼如下:
  
[AppleScript] 純文本查看 復制代碼
  public Vector3 RandomPos()
    {
        float xVaule = Random.Range(minX, maxX);
        float yVaule = Random.Range(minY, maxY);
        Vector3 tempPoint = new Vector3(xVaule, yVaule, 0);
        return tempPoint;
    }

隨機旋轉:
   
[AppleScript] 純文本查看 復制代碼
 public Quaternion RandomRotate()
    {
        float angle = Random.Range(0, 360);
        Quaternion tempQuat = Quaternion.AngleAxis(angle, Vector3.forward);
        return tempQuat;
    }

由于之前設置了縮放等級,隨機縮放就只需要從數組中取出對應的值即可。于是代碼如下:
   
[AppleScript] 純文本查看 復制代碼
 public float RandomScale(out int scaleLevel)    // 隨機道具縮放 返回縮放值,用于計算
    {
        int index = Random.Range(0, scaleData.Length);
        scaleLevel = index+1;
        float scaleVaule = scaleData[index];
        return scaleVaule;
    }

通過之前設置的關卡分數信息,以及各種道具的分數。我們來生成當前關卡的道具。主要是先隨機出道具,然后計算當前已經生成道具分數的總和,查看是否超出目標關卡分數,超出就不在生成,不超出就重復上面的操作。直到分數超出(PS:道具的分數=道具配置的分數*道具的縮放值)。代碼如下:
[AppleScript] 純文本查看 復制代碼
public class GameMode : MonoBehaviour {
...
    public int level;//當前游戲關卡數
    public void SwitchLevel()
    {
        int creatfraction = 0;      //現在已經生成的分數
        int tempfraction = targetFraction[level];//當前關卡的目標分數
        tempfraction += minFraction;//為了降低游戲難度,讓生成道具的分數總和,能夠超過目標分數+minFraction
        while (creatfraction < tempfraction)//如果現在生成的分數小于目標分數
        {
            int objIndex = Random.Range(0, objNames.Length);
            string tempName = objNames[objIndex];//隨機道具名稱
            GameObject tempObj = RandomProp(tempName);
            float tempScale = 1;//道具的縮放值
            int scaleLevel = 1;//道具的縮放等級
            if (objIndex != 0)//鉆石不進行旋轉縮放操作
            {
                Quaternion tempQuat = RandomRotate();
                tempObj.transform.rotation = tempQuat;
                tempScale = RandomScale(out scaleLevel);
                tempObj.transform.localScale *= tempScale;//設置道具的縮放
            }
            var tempScript = tempObj.AddComponent<PropScript>();//給生成道具添加腳本
            tempScript.nowType = PropType.Fraction;//設置類型
            int fraction = fractionData[objIndex];//活動設定的道具分數
            fraction = (int)(fraction * tempScale);//計算出現在的道具分數
            creatfraction += fraction;
            tempScript.fraction = fraction;
            tempScript.scaleLevel = scaleLevel;//設置道具的縮放等級
            levelObjs.Add(tempObj);
        }
        int propCount = Random.Range(0, 3);       //場上最多2個特殊道具
        while (propCount > 0)
        {
            propCount--;
            GameObject tempObj = RandomSpecialProp();//同上
            levelObjs.Add(tempObj);
        }
    }
    public GameObject RandomProp(string name)//隨機道具
    {
        GameObject templateObj = tempLates[name];
        Vector3 tempPoint = RandomPos();
        GameObject tempObj = Instantiate(templateObj, tempPoint, Quaternion.identity);
        return tempObj;
    }
}

游戲演示

結語
這樣,一個簡答的黃金礦工就算完成了。但是還缺少UI顯示,關卡切換等功能,文章沒有給出實現的講解。歡迎童鞋參考后續的完整版工程食用,來補上缺失的部分。
知乎@繁華如夢

回復

使用道具 舉報

7日久生情
2068/5000
排名
4092
昨日變化

0

主題

1350

帖子

2068

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
254705
好友
1
蠻牛幣
1883
威望
0
注冊時間
2017-11-16
在線時間
356 小時
最后登錄
2019-8-12
沙發
2019-4-28 13:35:45 只看該作者
6666666666666666666666666
回復 支持 反對

使用道具 舉報

5熟悉之中
713/1000
排名
10706
昨日變化

0

主題

463

帖子

713

積分

Rank: 5Rank: 5

UID
301976
好友
1
蠻牛幣
1069
威望
0
注冊時間
2018-10-31
在線時間
152 小時
最后登錄
2019-8-12
板凳
2019-4-28 14:09:57 只看該作者
童年的記憶....
回復

使用道具 舉報

4四處流浪
326/500
排名
17816
昨日變化

0

主題

137

帖子

326

積分

Rank: 4

UID
184198
好友
0
蠻牛幣
453
威望
0
注冊時間
2016-11-16
在線時間
153 小時
最后登錄
2019-7-26
地板
2019-4-28 15:43:03 只看該作者
用心了,感謝分享
回復

使用道具 舉報

0

主題

3

帖子

6

積分

Rank: 1

UID
310191
好友
0
蠻牛幣
2
威望
0
注冊時間
2018-12-29
在線時間
3 小時
最后登錄
2019-6-10
5#
2019-4-28 16:35:35 只看該作者
很完美  喜歡 謝謝分享
回復 支持 反對

使用道具 舉報

0

主題

3

帖子

5

積分

Rank: 1

UID
299292
好友
0
蠻牛幣
1
威望
0
注冊時間
2018-10-9
在線時間
2 小時
最后登錄
2019-5-25
6#
2019-4-28 17:27:31 只看該作者
不錯,支持下
回復

使用道具 舉報

5熟悉之中
883/1000
排名
3817
昨日變化

0

主題

130

帖子

883

積分

Rank: 5Rank: 5

UID
246100
好友
0
蠻牛幣
994
威望
0
注冊時間
2017-9-26
在線時間
359 小時
最后登錄
2019-5-30
7#
2019-4-28 17:34:09 只看該作者
厲害了,大佬
回復

使用道具 舉報

7日久生情
2297/5000
排名
2612
昨日變化

2

主題

1128

帖子

2297

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
209046
好友
0
蠻牛幣
3239
威望
0
注冊時間
2017-3-30
在線時間
613 小時
最后登錄
2019-8-10
8#
2019-4-29 09:10:24 只看該作者
很棒
回復

使用道具 舉報

0

主題

3

帖子

13

積分

Rank: 1

UID
315095
好友
0
蠻牛幣
31
威望
0
注冊時間
2019-2-28
在線時間
10 小時
最后登錄
2019-8-9
9#
2019-4-30 14:25:59 只看該作者
我曹 摸魚必備啊
回復

使用道具 舉報

2初來乍到
141/150
排名
18792
昨日變化

0

主題

62

帖子

141

積分

Rank: 2Rank: 2

UID
4602
好友
1
蠻牛幣
11
威望
0
注冊時間
2013-9-26
在線時間
47 小時
最后登錄
2019-5-8
10#
2019-5-5 15:17:59 只看該作者
黃金礦工
回復

使用道具 舉報

7日久生情
1711/5000
排名
832
昨日變化

2

主題

153

帖子

1711

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
5714
好友
0
蠻牛幣
3284
威望
0
注冊時間
2013-10-15
在線時間
374 小時
最后登錄
2019-8-12
11#
2019-5-8 08:33:01 只看該作者
不錯,有點意思
回復

使用道具 舉報

排名
64931
昨日變化

3

主題

26

帖子

47

積分

Rank: 1

UID
312777
好友
0
蠻牛幣
434
威望
0
注冊時間
2019-1-24
在線時間
16 小時
最后登錄
2019-5-10
12#
2019-5-9 11:43:11 只看該作者
666666666666666666666666666666
回復 支持 反對

使用道具 舉報

2初來乍到
133/150
排名
64931
昨日變化

6

主題

57

帖子

133

積分

Rank: 2Rank: 2

UID
244724
好友
0
蠻牛幣
376
威望
0
注冊時間
2017-9-19
在線時間
68 小時
最后登錄
2019-8-12
13#
2019-5-13 18:20:07 只看該作者
66666666666666666666666666666666666666666666666666666666666666666666
回復 支持 反對

使用道具 舉報

7日久生情
2516/5000
排名
2252
昨日變化

0

主題

1115

帖子

2516

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
163777
好友
2
蠻牛幣
1044
威望
0
注冊時間
2017-2-27
在線時間
777 小時
最后登錄
2019-8-12
14#
2019-5-17 09:29:54 只看該作者
感謝分享
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 注冊帳號

本版積分規則

女校游泳队彩金