[聚合文章] [原创]Unity2D 开发 + UGUI 中文教程二

c# 2015-11-17 4 阅读

哈哈,这个坑继续来填上~

据我了解,很多人也像我刚开始那样,以为角色站在地上是使用重力模拟出来的效果,地面和角色都有刚体来实现,跳跃就是给角色一个向上冲力。但是这样做有很多弊端,最主要的就是,你无法精确控制角色的位移距离、方向等,因为这一切都由引擎代替你控制了。但是用代码模拟,可能好多新人光是想想就觉得头大,我怎么计算角色应该在哪呢?我怎么才能做出超越物理模拟的效果呢?

下面我们就来一点点实现。

添加跳跃按钮

首先我们用ps涂一个纯色的矩形,作为跳跃按钮,然后将按钮的png放到Assets文件夹中。
然后选GameObject菜单,进入UI子菜单,选择Button(一定注意不要错选到Component菜单里)

点击之后,大家会发现屏幕上突然出现好大一坨按钮!我们先不要妄动,先看关系树,这里多出了一个EventSystem对象,这个是用来侦测事件的,然而我们现在还不用管它。还有个Canvas对象,点开以后有个Button,下面有个Text。哈哈,你刚刚就已经创建了一个UGUI(老版本有些人应该知道用的是NGUI)版的Button和Text了,这些我们以后会经常用到。我们选中Canvas对象(这个大家可以理解为一个专门放置UI的图层,一层可以放很多UI,也允许一个场景里有多个UI图层),做一些基本的设置:

将Canvas组件中的RenderMode选为图中的选项,表示我们用摄像机尺寸来作为UI面板尺寸,当然这就需要我们将参考的摄像机拖拽到下面的RenderCamera选项中,表示以此摄像机视野作参照,其他的不要修改,现在场景里的UI面板就恢复正常了。

接下来的操作对新人来说,可能比较复杂,我会尽力详细介绍。


图中按钮位置可能大家不尽相同,我们设置到一个箭头指向的位置或其他合理的位置。注意:这个和其他GameObject不同的地方就是,UI使用的不是Transform,而是一个叫Rect Transform的东西,本质上是Transform的升级版,我们现在只要知道这里也可以修改坐标和尺寸就行了。

这个组件使用的尺寸都很大,为什么呢?因为精灵对象,都是进行了一定比例的缩放,比如100像素=1unit,场景里实际使用的是单位长度unit,而不是像素尺寸(这个比例尺配置,选中Assets文件夹中任意的精灵,属性面板中有一个Pixels Per Unit即是比例尺,我就不赘述了)。但是,所有的UI面板,一般使用的都是原始尺寸,该多大就多大。这里我设置尺寸为160x100,坐标为176,150。

最后一步,将按钮素材拖拽到按钮的Image组件中。现在发现上面的一行Button文字很碍事,这个文字是Text对象显示的,在关系面板中,将Button下面的Text选中,右键删除即可,大功告成!

为按钮创建跳跃函数

在关系面板中,选中游戏主角对象,在属性面板中点击AddComponent按钮,进入New Script子菜单,输入文件名Player,Language选择C Sharp,然后我们就添加了一个主角脚本,用来控制主角的所有行为。

在Mono中打开脚本,添加一个public void Jump函数,这里我们将用代码进行跳跃的控制。先说一下思路:跳跃的过程无非是两个阶段,向上减速阶段,向下加速阶段。同时,我们需要几个数值来控制比如跳跃力度、重力加速度。在Player类中,先定义几个属性:

private float jumpForce = 2;
private float gravity = 0.2f;
private float speed = 0;
private float ground = 0;
private bool isJumping = false;

jumpForce表示跳跃初始速度,gravity表示每一帧速度衰减值,speed表示当前帧需要位移距离,也可以理解为速度。这几个值稍后我们会逐渐测试调整,直到合适为止,合适的值大家自己尝试吧我就不赘述了。ground表示地面高度,也就是角色的初始高度,isJumping表示当前是否在跳跃,因为跳跃是一个持续状态,需要在Update中控制,但是跳跃事件只能触发一次,相当于才一帧,所以我们在事件中设置状态,然后在Update中判断。

实现出的详细逻辑如下:

void Start () {
    ground = transform.position.y;
}

// Update is called once per frame
void Update () {
    if(isJumping){
        transform.position += new Vector3(0, speed * Time.deltaTime, 0);
        speed -= gravity;

        if(transform.position.y <= ground){
            transform.position += new Vector3(0, ground - transform.position.y, 0);
            isJumping = false;
        }
    }
}

public void Jump(){
    if(!isJumping){
        speed = jumpForce;
        isJumping = true;
    }
}

代码分解

Start函数在游戏对象首次激活之后会被调用,做一些初始化工作。可以理解为:游戏开始时,我们先将角色当前高度标记为地面高度。

跳过Update,我们先来说Jump函数。待会我们会将Jump函数绑定到跳跃按钮上,点击按钮,这个函数就会被调用。跳跃触发的时候,我们先判断是不是已经跳起来了,如果已经跳了,就不再跳一次了(大家可以尝试自己实现二段跳),如果没有跳跃,那么可以起跳一次。设置状态为true,设置起跳速度为jumpForce。

Update函数在每一帧会执行一次,一定注意!有时候unity会以30帧执行,有时是60帧,有时会有波动,千万不要以为一定是60帧。
我们先判断跳跃状态是否被激活,如果触发了跳跃,那么将主角位置提高一个值speed * Time.deltaTime,Vector3是三维数组,unity重载了操作符,二维数组之间、三维数组之间都可以直接做加减法,这样修改坐标非常的方便(但是unity好像是不支持直接修改transform.position的xyz坐标,这里也可以先取出来到一个Vector3变量中,然后修改y的值,然后再赋值回去)。
Time.deltaTime我们提过了,是上一帧到这一帧的间隔时间。用这个值乘以速度,可以保证每一秒移动的距离不受帧率影响,如果大家不明白原理也没关系,我这里把原理列出来,大家慢慢体会就好,给像我这样的数学渣的福利。

每秒移动的距离 = 速度 x 1秒
=> 两边除以每秒的帧数,比如60,仍然相等
每秒移动的距离/帧数 = 速度 x 1秒/帧数
1秒/帧数 也就是每一帧的时间Time.deltaTime,所以
每一帧移动的距离 = 速度 x Time.deltaTime

然后我们看下一行,speed每一帧会减少一个重力值gravity。到达最高点以后,速度减为0,然后开始下落,y轴速度变为负数(假设向上为正数)。
掉落的时候,判断是否掉到了地面以下,如果掉到地下了,立即停止跳跃状态,同时计算一下当前位置和地面的高度差ground - transform.position.y,故技重施,叠加到当前角色的position中,这样角色又回到了地面上。

好了!全部讲解完毕,希望大家没有看晕,有什么疑问,评论里讨论吧~

绑定事件到按钮中

先上图:

回到Editor,在关系树面板中,选中Button按钮,看属性面板,最下面有个Button(Script)组件,最下面有个On Click,这里是用来添加按钮事件的,可以添加多个。我们先点一下加号,然后将主角对象拖拽到带有小圆圈的框里,在后面的下拉选框中选择Player子菜单,在选择里面的Jump函数,就是我们刚才写的那个函数。

将主角对象拖拽到小框里,表示这个事件将会以主角为主体,这个主角身上有很多个组件,每个组件都内置了一些函数事件,下拉选框中我们可以看到好几个子菜单,就是这些组件。我们自己写的主角脚本,也是绑定在主角身上的一个组件,我们定义在脚本中的public函数,在这里都可以选。

好了,今天就到这里了。这些内容对没有基础的童鞋们来说,还是略复杂的,不过边学边练,加上自己多尝试,总能学会的。加油吧!

下一篇:(原创)Unity2D 开发 + UGUI 系列教程三

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。