写在前面
这个系列(坑) 来自一个用Unity开发的2D横版射击游戏的开发过程,用来记录学习进度以及一些学习心得。和大家分享共勉,有错误的话请评论指出,我会积极回复。
=+=+=+=+=+=+=+=+=+=
那么,我们开始吧
=+=+=+=+=+=+=+=+=+=
前情提要
上一次,我们提到了Rigidbody2D 以及Collider2D ,总而言之,如果你希望你的物体运动、碰撞,那么是Collider2D 在负责。而受力是Rigidbody2D 的特性。 如果你希望创建一个拥有运动逻辑的活物,比如一个Player,给他一个Rigidbody2D 吧
Question Again
你好,我是Player,你想让我动起来?凭啥?
确实,我们用什么方法让它动起来呢?你可能会说WASD,或者抄起你的手柄一通猛搓。 但是并没有什么用,因为你还什么都没写呢。 虽然你什么都没写,但是在这个时候其实你的输入已经被Unity读取了,这是通过我们的Input Manager实现的,你可以在Edit -> Project Settings -> Input Manager 里找到它。 Like this ↑ 有了这个,我们可以开始着手编写脚本Script 了。
关 于 脚 本
脚本是你操纵Unity中的物体的遥控器,就像Minecraft的创造模式的控制台指令一样,你可以通过写下一些简单的代码来实现对组件参数的定义和操作。 同样地,你所需要的逻辑判断、数值系统,也都需要写在脚本里。可以说,脚本就是一个物体的灵魂Soul 。
首先
确保你的Visual Studio有Unity支持组件,有C#编译环境 并且,确保你的Edit -> Preferences -> External Tools里面的External Script Editor是你正在使用的Visual Studio。 当然了,如果你不需要自动补全,也可以用记事本写代码,Unity无所谓的。
创建一个C# Script
在你这个项目的随便什么地方(我建议创建一个Scripts文件夹)里,右键新建一个C# Script,然后打开它。你可以将它命名为Player或者PlayerController或者aaabc之类的。 你应该会看到这样的景象 上面的using是库函数引用,你现在不用管他们。
- CSDN是我给这个脚本的命名,你可以从上面的Tab看到。 它是一个
public class 公共的类,并且: 继承了MonoBehaviour 。 MonoBehaviour 是个啥? 它是一个继承了Component 的脚本基类,所有的Unity脚本都得继承MonoBehaviour 。当然, 如果你不需要Unity,自己写脚本,或者你的所有方法里都没有用到Unity提供的组件和函数,那你自然也不必要继承MonoBehaviour 。- 下面的两个方法
Start() Update() ,是我们获取Component 和捕捉信号,判断逻辑的地方。 Start() 顾名思义,这个方法在对象被创建时用来初始化我们的脚本,获取一些必要的信息,比如我们需要的Rigidbody2D ,巧妇难为无米之炊,如果没有刚体,我们又怎么能让刚体运动呢?Update() 更新方法,这个方法每一帧都会被执行一次,所以你不能将所有的代码内容放到这个里面,至少我不建议你这么做。我们需要在Update 里面来读取一些基本的输入信息,更新/维护我们的人物状态。总而言之,在保证功能能够正常实现的情况下,Update里执行的代码行数越少越好。
现在,将手放到键盘上吧。
我们考虑实现运动所需要的组件是什么,因为我们要在Start() 里面去获取它。 答案呼之欲出:Rigidbody2D 但是首先,我们需要在代码中先创建一个空的Rigidbody2D
[SerializeField] Rigidbody2D RB;
你也可以不加[SerializeField] 将它改成public ,这都是为了让我们能够在Unity里面看见这个属性,没错,这是脚本的一个属性,稍后我们需要将Player的Rigidbody2D 组件拖动到Player的Player(Script)的这个位置。
然后,在你的Start() 中写下这样一行:
RB = GetComponent<Rigidbody2D>();
这样,我们就从脚本附着的对象上摘取了它的名为Rigidbody2D 的Component了,我们就成功了一半了,接下来,你对RB做的所有改变,都能如实地在你的Player身上体现。
现在,输入吧。
Start() 写完了,接下来让我们把目光转向Update() 。 我们该从Unity那里搞点输入数据过来了,没有输入数据的话我怎么给你算这个东西应该怎么运动啊(恼)
很多时候写脚本就像老妈子唠叨一样,跟Unity问这问那,有没有这个啊,整点这个,啊啊那我明白了,应该得是这样的吧,你看看怎么动一下子。
在Unity给我们提供的库里,有这样的一系列方法,他们叫Input ,一般来说,你可以从他们的名字来读出他们的用处,前提是你认识那些词汇的话,当然不认识也没关系,可以翻译一下,词汇量非常少。比如我们这里用到的
direction = Input.GetAxis("Horizontal");
在C#中,. 是一种声明父子关系的符号,所以Input.GetAxis("Horizontal") 就是Input 类里面的一个用来获取某一条轴上的输入的方法。它返回一个-1~1的浮点数。"Horizontal" 是它的参数,你也可以改成"Vertical" 或者其它的什么轴,总之,现在我们的direction 就是你的输入数值。(噢,别忘了声明direction作为一个float变量,然后设置合适的权限,比如private,这个我就不多赘述了)
- 在手柄上,这个数值和你推摇杆的轻重正相关
- 然而键盘的话这个数字会以极快的速度变化到极大或极小值。
因为这个原因,我们在做键盘输入的时候,也可以不使用GetAxis 方法,而一转使用GetAxisRaw ,GetAxisRaw 只会返回-1,0,1 之中的一个数。 当然了,你也可以使用GetButtonDown 或者GetKeyDown ,不知道怎么用的话,将鼠标悬停在他们的名字上,你可以看到这个方法的使用手册。 接下来,我们希望在我们输入之后,物体朝着我们想要的方向运动。
Pull Your Mind Out Now
在现实中,我们希望一个物体运动,有什么办法呢? 给一个力推它,给它一个速度(当然现实中你无法给瞬时速度),或者使用传送魔法 好消息是,这些方法在Unity中都能实现,你猜猜哪种最好用?
Come Back To Script
这一部分代码你可以写在Update() 中或者是FixedUpdate() 中,因为你需要时刻检测物体是否运动。
Update() 检测周期 T = 1/fps(s) fps是你的电脑帧率FixedUpdate() 检测周期 T = 1/50(s) 首先我们忽略传送术,就算是Dash,我们也不是将人物直接传送到目标位置。直接修改坐标的方法我们留到有用的时候再说。 那么现在还剩两种方法:调用刚体的AddForce 方法和直接修改刚体的velocity 属性
AddForce
它提供了一个加速度,这意味着你的物体在你的按键下会做一个匀加速直线运动,不可或缺地,这样方式操作的运动会有一个很平滑的速度曲线,像Mario里面的黄油手感一样。AddForce 方法有两种施力模式,默认下是Force ,也就是原力 ,你还可以通过在第一个参数后再加一个参数声明ForceMode2D.Impulse ,如此一来,就算你按住,这个力也只会被施加一次给这个刚体,你可以看成提供了一个碰撞冲量。
RB.AddForce(Vector2D.right * force);
整个参数是一个二维向量,force 是我们自己定义的一个推力大小,建议设置成float类型。而Vector2D.right 其实就是new Vector2D(1,0) 的简便写法。
如此一来,我们就添加了一个二维的恒力。它会提供一个恒定的 (大概) 加速度。 现在回到Unity里,开始你的Game,人物应该能左右平移了。
velocity
相似地,我们也可以通过直接设置刚体的速度velocity 来实现移动的效果,事实上,我正在使用的以及比较推荐初学者使用的就是这种。 像下面这样使用:
RB.velocity = new Vector2(direction * speed, RB.velocity.y);
我们新建一个二维向量,x 是我们的输入乘以速度系数speed ,同样是一个需要定义的float变量。而y 是刚体目前的纵向速度。我们在左右移动时不希望垂直速度被改变,所以这样引用。你会发现,形如RB.velocity.y 这样的引用,你可以把. 翻译成的 。 所以这一条的意思就是RB 的速度velocity 的y轴投影 大小
Tip here
这样写完之后,你的人物理论上就可以以一个匀速在大部分时间内运动了,当然,速度不会突变,就像现实中那样。起步由于前面提到键盘输入的累加性,必然是一个加速的过程,然后匀速。 如此你会发现,在你松开方向键时,你其实是希望他马上停下来的,然而他会因为输入延迟等因素向前滑行一小段。有可能使血压升高。 所以我推荐这样的写法:
if (Mathf.Abs(direction) > 0.2f)
{
RB.velocity = new Vector2(direction * speed, RB.velocity.y);
}
else
{
RB.velocity = new Vector2(0, RB.velocity.y);
}
也就是在输入绝对值小于0.2时,我们认为用户根本没在输入了,因为这个值足够小,以致于推手柄都不太好达到这个值以下。于是我们将水平速度设置为0。
大功告成!
现在,你的人物可以左右移动了,今天我们写了第一个C#脚本,这是珍贵的一步,代表着你正式开始使用Unity了!
试着自己写写跳跃的代码吧!
虽然,现在离你心目中的运动 还有很大区别,首先,人物不会掉头,而且,他也没有跑步的动作。有关于贴图Sprite 、动画机Animator 、状态控制我们将在下一期进行讲解
To be Continued…
See U!
|