请选择 进入手机版 | 继续访问电脑版

查看: 6626|回复: 96

[原创] 简单两步使用Unity制作ZigZag游戏

  [复制链接]

910

主题

1570

帖子

2万

贡献

管理员

Rank: 9Rank: 9Rank: 9

积分
20185
QQ
发表于 2016-9-6 03:59:52 | 显示全部楼层 |阅读模式
单手操作却独具挑战性的ZigZag游戏是否也让你玩上瘾了呢?今天来教大家使用Unity制作一款ZigZag游戏,附详细步骤及源码。

如果还不知道ZigZag怎么玩,请看:

0.gif

准备工作

首先新建Unity 3D工程,任意命名并保存。将相机的Clear Flags设为Solid Color,如下:

1.png

然后需要一个脚本让相机可以跟着小球移动。新建C#脚本命名为CameraFollow,将其绑定到Main Camera上,并添加以下代码:

[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;

public class CameraFollow : MonoBehaviour
{
        public bool shouldRotate = false;

        // 跟随目标
        public Transform target;
        // 目标距XZ平面的距离
        public float distance = 10.0f;
        // 相机在目标上方的高度
        public float height = 5.0f;
        public float heightDamping = 2.0f;
        public float rotationDamping = 3.0f;
        float wantedRotationAngle;
        float wantedHeight;
        float currentRotationAngle;
        float currentHeight;
        Quaternion currentRotation;

        void LateUpdate ()
        {
                if (target){
                        // 计算当前旋转角度
                        wantedRotationAngle = target.eulerAngles.y;
                        wantedHeight = target.position.y + height;
                        currentRotationAngle = transform.eulerAngles.y;
                        currentHeight = transform.position.y;
                        currentRotationAngle = Mathf.LerpAngle (currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);
                        // 计算当前高度
                        currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);
                        // 将角度转换为欧拉角
                        currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
                        // 设置相机至XZ平面的距离设置
                        transform.position = target.position;
                        transform.position -= currentRotation * Vector3.forward * distance;
                        // 设置相机高度
                        transform.position = new Vector3 (transform.position.x, currentHeight, transform.position.z);
                        // 保持朝向目标
                        if (shouldRotate)
                                transform.LookAt (target);
                }

        }
}


到此前期的准备工作完毕,下面来看实现步骤。

第一步


整个游戏都只包含一些基本几何体,所以不需要额外的资源。按照如下步骤在场景中添加平台:

新建Cube,将Position和Rotation均设为(0, 0, 0),Scale设为(5, 1, 5)。
为Cube添加Rigidbody组件并勾选Is Kinematic:
3.png

新建Materials文件夹,在文件夹下新建材质Material命名为MatPlatform,将其赋予Cube。将MatPlatform材质的着色器设置为Legacy Shaders-> Bumped Specular,并按照自己的喜好设置Main Color及Shininess等属性。

4.png

至此小球所在的平台就设置完毕了,如下:

5.png

下面按照与平台相同的步骤来创建小球:

新建Sphere,将Position、Rotation及Scale分别设为(0, 1, 0),(0, 45, 0)和(0.5, 0.5, 0.5)。
为Sphere添加Rigidbody组件,展开Constraints,勾选Freeze Rotation后的所有项(X、Y、Z)以避免小球因为摩擦力而发生旋转。

6.png

在Materials文件夹下新建材质Material命名为MatSphere,将其赋予Sphere。将MatSphere材质的着色器设置为Legacy Shaders-> Bumped Specular,并按照自己的喜好设置Main Color及Shininess等属性。

7.png

小球创建完成后,下面就让相机可以跟随小球移动。前面已经将CameraFollow脚本绑定到Main Camera上了,接下来勾选CameraFollow脚本的ShouldRotate属性,并将小球(Sphere)拖拽至CameraFollow脚本的Target字段,设置好其它的属性值:

8.png

运行场景会发现,此时相机会跟随小球移动。

9.gif

第二步

游戏需要的所有物体都创建完毕,接下来就是添加脚本逻辑了。新建C#脚本命名为Ball,这个脚本将用于控制小球的行为。Ball脚本的完整代码如下:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;

public class Ball : MonoBehaviour
{    
        public GameObject _platfrom;
        GameObject _lastPlatform;

        enum BALL_STATE
        {
                LEFT,
                RIGHT
        }

        Rigidbody _rb;
        BALL_STATE _ballState = BALL_STATE.RIGHT;
        bool _isStarted = false;
        float _speed = 3;

        void Start ()
        {
                _rb = GetComponent<Rigidbody>();
                // 在上一块平台相同位置生成新的平台
                _lastPlatform = Instantiate (_platfrom) as GameObject;
                // Now create 50 platfroms initially
                for (int index = 0; index < 50; index++) {
                        // 随机向左或向右生成50快平台
                        SpawnPlatform ();
                }
        }

        // 在平台结束处生成新的平台
        void SpawnPlatform ()
        {
                // 随机数0和1用于决定平台生成方向
                int randonNumber = Random.Range (0, 2);
                // 如果随机数为0
                if (randonNumber == 0) {
                        // 在平台结束处左边生成新的平台
                        _lastPlatform = Instantiate (_platfrom, new Vector3 (_lastPlatform.transform.position.x + 1,
                                _lastPlatform.transform.position.y,
                                _lastPlatform.transform.position.z),
                                Quaternion.identity) as GameObject;
                } else {
                        // 在平台结束处右边生成新的平台
                        _lastPlatform = Instantiate (_platfrom, new Vector3 (_lastPlatform.transform.position.x,
                                _lastPlatform.transform.position.y,
                                _lastPlatform.transform.position.z + 1),
                                Quaternion.identity) as GameObject;
                }
        }

        void Update ()
        {
                OnTap ();
        }

        void OnTap ()
        {
                // 检测是否有点击
                if (Input.GetMouseButtonDown (0)) {
                        // 检测游戏是否开始
                        if (!_isStarted) {
                                // 游戏开始标志
                                _isStarted = true;
                                // 首次点击时为小球增加一些速度
                                _rb.velocity = new Vector3 (_speed, 0, 0);
                                // 返回
                                return;
                        }

                        // 点击切换小球前进方向
                        switch (_ballState) {
                        // 如果当前方向为左
                        case BALL_STATE.LEFT:
                                // 切换为右
                                _ballState = BALL_STATE.RIGHT;
                                // 让小球向右移动
                                _rb.velocity = new Vector3 (_speed, 0, 0);
                                break;
                        case BALL_STATE.RIGHT:
                                // 切换为左
                                _ballState = BALL_STATE.LEFT;
                                // 让小球向左移动
                                _rb.velocity = new Vector3 (0, 0, _speed);
                                break;
                        }
                }
        }

        void OnCollisionExit (Collision other)
        {
                // 这里只有平台与小球碰撞,所以退出平台后直接生成新平台
                SpawnPlatform ();
                // 新建游戏对象保存当前平台
                GameObject platform = other.gameObject;
                // 关掉isKinematic属性让平台下落
                platform.GetComponent<Rigidbody> ().isKinematic = false;
                // 下落1秒后销毁平台
                InvokeDestroyPlatfrom (platform);
        }

        void InvokeDestroyPlatfrom (GameObject platform)
        {
                // 调用协程销毁平台
                StartCoroutine (DestroyPlatform (platform));
        }

        IEnumerator DestroyPlatform (GameObject platform)
        {
                // 等待1秒
                yield return new WaitForSeconds (1.0f);
                // 销毁平台
                Destroy (platform);
        }
}
其中BALL_STATE枚举用来定义小球的移动方向。OnTap函数检测玩家输入,并控制小球移动方向的转换,在玩家点击屏幕时开始游戏或切换小球前进方向。在Update函数中调用OnTap,每帧都要检测玩家输入。

添加了移动的代码后,小球就可以移动了,但还不够流畅。为了让小球可以流畅向前滚动,需要将小球和平台的摩擦力去掉。在Materials文件夹下新建Physical Material重命名为Frictionless,并将所有的摩擦力和弹力等属性值设为0:

14.png

然后将Frictionless分别赋给平台(Cube)Box Collider和小球(Sphere)Sphere Collider上的Material字段:

15.png

这样小球就可以流畅地向前移动了,下面来创建平台Prefab以便运行时动态生成平台。新建文件夹Resources,这是由Unity控制的特殊文件夹,所以文件夹名字不要写错。
•        新建Cube重命名为Platform,分别设置Position、Rotation、Scale为(3, 0, 2)、(0, 0, 0)和(1, 1, 1)。
•        将Materials文件夹下的Frictionless赋给Box Collider的Material,MatPlatform赋给Mesh Renderer的Material。

16.png

最后将Platform从层级视图拖拽至项目视图的Resources文件夹下保存为Prefab,删除层级视图的Platform。

SpawnPlatform函数用于生成平台,在游戏开始时及小球走过一个平台后调用。游戏开始时一次性生成50块平台,此后每次小球经过一块平台则重新生成一个。小球已经经过的平台会在等待一秒后坠落,这是通过调用StartCoroutine来实现的。

将Ball脚本绑定到小球(Sphere)上,然后将Resources下的Platform拖拽至Ball脚本的Platform字段:

17.png


到此整个游戏就完成了,一共就两个脚本,两个步骤。最后运行效果如下:

18.gif

这还只是最简单的版本,大家还可以继续打磨,比如增加一些道具和游戏计分的逻辑等等。
下载工程文件(请回复本贴哦):

游客,如果您要查看本帖隐藏内容请回复




0

主题

2

帖子

25

贡献

初级UU族—1级

Rank: 1

积分
25
发表于 2016-9-6 05:42:53 来自手机 | 显示全部楼层
看起来不错

0

主题

2

帖子

25

贡献

初级UU族—1级

Rank: 1

积分
25
发表于 2016-9-6 05:43:54 来自手机 | 显示全部楼层
看起来不错

0

主题

3

帖子

125

贡献

初级UU族—2级

Rank: 2

积分
125
发表于 2016-9-6 05:43:58 | 显示全部楼层
简单两步使用Unity制作ZigZag游戏

0

主题

3

帖子

20

贡献

初级UU族—1级

Rank: 1

积分
20
发表于 2016-9-6 06:44:02 | 显示全部楼层
看起来不错,推荐给学生学习

0

主题

3

帖子

20

贡献

初级UU族—1级

Rank: 1

积分
20
发表于 2016-9-6 06:45:15 | 显示全部楼层
still have problem for download?

0

主题

3

帖子

20

贡献

初级UU族—1级

Rank: 1

积分
20
发表于 2016-9-6 06:47:35 | 显示全部楼层
VResearcher 发表于 2016-9-6 06:45
still have problem for download?

OK le
thank you!

0

主题

1

帖子

10

贡献

初级UU族—1级

Rank: 1

积分
10
发表于 2016-9-6 07:49:09 | 显示全部楼层
看上去不错可以试试

1

主题

2

帖子

40

贡献

初级UU族—1级

Rank: 1

积分
40
发表于 2016-9-6 08:32:43 | 显示全部楼层
学习学习~~~~~~~~~~

0

主题

1

帖子

25

贡献

初级UU族—1级

Rank: 1

积分
25
发表于 2016-9-6 09:06:39 | 显示全部楼层
感谢分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表