找回密码
 注册帐号

扫一扫,访问微社区

士郎 我们来用Unity复刻一下《黄金矿工》

14
回复
2183
查看
打印 上一主题 下一主题
[ 复制链接 ]
排名
1
昨日变化

8141

主题

8699

帖子

3万

积分

Rank: 16

UID
1231
好友
186
蛮牛币
12705
威望
30
注册时间
2013-7-29
在线时间
4172 小时
最后登录
2019-9-18

活力之星原创精华达人突出贡献奖财富之证游戏蛮牛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;
        }
    }
}

人物减速
我们使用触发器来检测钩子是否抓中了物体,一分极速PK10抓中了。就在此时更改玩家的速度。由于之前在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)//一分极速PK10现在生成的分数小于目标分数
        {
            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日久生情
2219/5000
排名
4093
昨日变化

0

主题

1479

帖子

2219

积分

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

UID
254705
好友
1
蛮牛币
2005
威望
0
注册时间
2017-11-16
在线时间
378 小时
最后登录
2019-9-18
沙发
2019-4-28 13:35:45 只看该作者
6666666666666666666666666
回复 支持 反对

使用道具 举报

5熟悉之中
884/1000
排名
10706
昨日变化

0

主题

612

帖子

884

积分

Rank: 5Rank: 5

UID
301976
好友
1
蛮牛币
1324
威望
0
注册时间
2018-10-31
在线时间
174 小时
最后登录
2019-9-18
板凳
2019-4-28 14:09:57 只看该作者
童年的记忆....
回复

使用道具 举报

4四处流浪
326/500
排名
17816
昨日变化

0

主题

137

帖子

326

积分

Rank: 4

UID
184198
好友
0
蛮牛币
455
威望
0
注册时间
2016-11-16
在线时间
154 小时
最后登录
2019-9-3
地板
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熟悉之中
928/1000
排名
3817
昨日变化

0

主题

152

帖子

928

积分

Rank: 5Rank: 5

UID
246100
好友
0
蛮牛币
622
威望
0
注册时间
2017-9-26
在线时间
382 小时
最后登录
2019-9-18
7#
2019-4-28 17:34:09 只看该作者
厉害了,大佬
回复

使用道具 举报

7日久生情
2325/5000
排名
2612
昨日变化

2

主题

1140

帖子

2325

积分

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

UID
209046
好友
0
蛮牛币
3369
威望
0
注册时间
2017-3-30
在线时间
629 小时
最后登录
2019-9-18
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日久生情
1732/5000
排名
832
昨日变化

2

主题

154

帖子

1732

积分

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

UID
5714
好友
0
蛮牛币
3348
威望
0
注册时间
2013-10-15
在线时间
394 小时
最后登录
2019-9-17
11#
2019-5-8 08:33:01 只看该作者
不错,有点意思
回复

使用道具 举报

排名
64937
昨日变化

3

主题

26

帖子

47

积分

Rank: 1

UID
312777
好友
0
蛮牛币
457
威望
0
注册时间
2019-1-24
在线时间
16 小时
最后登录
2019-5-10
12#
2019-5-9 11:43:11 只看该作者
666666666666666666666666666666
回复 支持 反对

使用道具 举报

2初来乍到
145/150
排名
64937
昨日变化

6

主题

63

帖子

145

积分

Rank: 2Rank: 2

UID
244724
好友
0
蛮牛币
265
威望
0
注册时间
2017-9-19
在线时间
84 小时
最后登录
2019-9-16
13#
2019-5-13 18:20:07 只看该作者
66666666666666666666666666666666666666666666666666666666666666666666
回复 支持 反对

使用道具 举报

7日久生情
2679/5000
排名
2252
昨日变化

0

主题

1226

帖子

2679

积分

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

UID
163777
好友
2
蛮牛币
1199
威望
0
注册时间
2017-2-27
在线时间
829 小时
最后登录
2019-9-18
14#
2019-5-17 09:29:54 只看该作者
感谢分享
回复

使用道具 举报

0

主题

1

帖子

1

积分

Rank: 1

UID
331893
好友
0
蛮牛币
12
威望
0
注册时间
2019-9-18
在线时间
0 小时
最后登录
2019-9-18
15#
半小时前 只看该作者
大神能分享下黄金矿工的unity资源包吗
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则