猿创征文 |【游戏开发实战——2D项目1 - Ruby‘s Adventure】控制游戏角色移动(1-2)

简介: 猿创征文 |【游戏开发实战——2D项目1 - Ruby‘s Adventure】控制游戏角色移动(1-2)

1)使用指南


①前言

本项目的完整开发流程在Unity官方项目的教学文档中编写了详细的教程文档,但是因为官方文档距离现在已经有一段时间了,个别地方有错误或者读者在使用自己机器上的Unity 编辑器进行操作的过程中,仍然遇到了零零散散的问题,无法再和官方教程相对应,本博客是对官网提供的项目的再补充以及个人心得复盘和经验分享。


本系列博客是来源于官方教程但是最终绝对会高于官方教程,让读者综合官方教程以及我自己的升华,能够独立开发出一个比官方教程更加完整可行的游戏。

最终的开发结果,使用资源也会开源在GitHub以及Gitee。


②官方教程地址

【官方文档 —— 1、设置 Unity 编辑器】

【官方文档 —— 2、主角和第一个脚本】

【官方文档 —— 3、角色控制器和键盘输入】

③如何处理本系列博客和官方教程之间的关系


个人建议是先大致浏览本系列专栏的博客,对注意事项和要点有个初步印象,再跟着官方文档逐步操作


因为本系列博客是对官方教程的修订,补充,升华,而且本系列博客的内容篇幅不会特别冗长,完整看完大概需要5 — 7 分钟。

假如只看文章的目录,留意需要订正的地方,那么大致只是需要1分钟左右。


2)具体步骤详细剖析


2.1)《1.创建新场景》再补充


在官方教程中,此处在创建新场景之后并没有介绍如何将相机挂接上去,故进行一定程度的补充。

现阶段其实也可以直接使用创建2D项目之后,自带的一个SampleScene开展后续的操作。

微信图片_20221020195410.png

在创建好的MainScene场景中,进行如下操作的补充:

① 创建一个新的空的游戏对象

Create Empty 在Unity 编辑器中表示创建一个空的游戏对象。

名场面——面向对象学习

微信图片_20221020195439.jpg

② 添加摄像机组件

微信图片_20221020195506.png

③ 设置添加的Camera组件上的属性

主要是将Inspector中清楚标志的Clear Flags 调整为纯色Solid Color,以及将控制投影的Projection调整为正字形Orthographic,其他的可以保持默认。


image.png


2.2)《9.声明变量》再补充


在官方提供的Unity教程中,对各个Unity中的API 阐述比较模糊,教程的目的更多是想让大家快速做出成品,至于为什么需要调用这些API并未详细说明。


因为我自己已经跟着教程初步做成完这个项目,现在处于复盘和再认知阶段,我会尽可能详细的阐介绍代码中使用这些类,函数,变量的作用,做到知其然也能知其所以然。


① 用于表示 2D 向量和点 的 Vector2类

脚本 API —— Vector2

在2D场景中,可以使用该结构表示位置和向量。同理,当前的场景是3D的时候,就需要使Vector3。


本次项目中,主要是使用它的用于存储X分量的变量x 和 用于存储Y分量的变量y来存储在2D坐标下获得的位置信息。

微信图片_20221020195613.png

② 用于描述对象的位置、旋转和缩放的Transform类

脚本 API —— Transform

在Unity 编辑器中,Inspector窗口中会显示加入场景中的游戏对象会默认添加一个Transform组件。

微信图片_20221020195639.png

在Unity提供的库中,也设置了Transform类用于控制该组件,对于本案例而言,就使用了其中的position变量。

微信图片_20221020195702.png

2.3)《4.审查你的脚本更改》再补充


在教程上面的内容中已经写到,在Unity 编辑器中 Edit -> Project Settings窗口中的 Input Manager 页面列出所有玩家能够进行输入的控件。

同时Unity提供的API中,也设置了相应的Input类用于操控编辑器中的这个用于检测用户输入的功能


③ 用于访问输入系统的接口,Input类

脚本API —— Input


image.png

在编辑器中,能够进行检测玩家输入的Axes目录下,在Input类中,也因此调用GetAxis类来检测玩家是否使用Horizontal以及Vertical列表下罗列的按键进行输入操作。


2.4)《11.以单位/秒表示 Ruby 的移动速度》再补充


按照教程文档中解释的,倘若直接把计算进行上下左右控制的功能写到一帧调用一次的Update函数中,再按照上述的计算逻辑,倘若有小伙伴计算机性能更加优秀比如一秒800帧,另一位小伙伴计算机性能较为一般,比如一秒30帧,在相同的时间中机器性能好的小伙伴已经进行800次位置计算了,而另一个,就蛮惨了。


下图是官方教程文档中的原话,可能有小伙伴读起来会比较拗口和难理解。

微信图片_20221020195802.png

其大致思想是这种的:


首先,我们检测进行按键输入的功能是放在Update函数中的,该函数每一帧调用次。

其次,不同机器的帧率是不同,比如有些1秒10帧,那么一帧花费1/10秒;有些1秒60帧,那么每帧会花费1/60秒。

那么,无论不同的机器是多少帧的,最后计算的都是1秒 * 速度而产生的距离。

因为Update按照帧调用,60帧就是调用60次,每帧计算的距离是速度 * 每帧的间隔时间(Time.deltaTime),

总的计算式就是 60 * 速度 * 1/60 = 速度 * 1秒


④ 从 Unity 获取时间信息的接口,Time类

脚本API —— Time

使用其静态变量deltaTime计算从上一帧到当前帧的时间间隔可以解决上述问题。

那么官方文档中推荐的代码我就不放这里了,相信大家已经跟着敲了。现在我们要完善文档中,当同时摁下垂直和水平的控制按键,出现速度叠加的情况。

关于速度叠加的原因,可以参考这篇文章的部分内容:

一个开发者的自学之路(7)——Unity3d中角色的移动


为了避免出现这种速度叠加的情况,较为统一的解决方法是使用标准化

//游戏角色的移动速度,开放为public,可以在Unity编辑器中进行设置
    public float speed =4.0f;
    //声明一个2D的刚体变量,用于存放游戏角色对象
    Rigidbody2D _rigidbody2d;
    //水平输入
    float _inputX;
    //垂直输入
    float _inputY;
    // Start is called before the first frame update
    void Start()
    {
        //返回Rigidbody2D类型的组件
        //务必已经在Ruby游戏对象上挂接Rigidbody2D组件
        _rigidbody2d = GetComponent<Rigidbody2D>();
    }
    // Update is called once per frame
    void Update()
    {
        /*
         * GetAxisRaw不使用平滑滤波器
         * 就是说GetAxis可以返回-1到1之间的数,比如检测到按键按下的时候,由0不断增加过渡到1
         * GetAxisRaw只能返回-1,0,1三个值!
         */
        _inputX = Input.GetAxisRaw("Horizontal");
        _inputY = Input.GetAxisRaw("Vertical");
        Vector2 input = new Vector2(_inputX, _inputY).normalized;
        _rigidbody2d.velocity = input * speed;
    }

⑤ 用于 2D 精灵的刚体物理组件,Rigidbody2D

脚本API —— Rigidbody2D

向精灵添加 Rigidbody2D 组件后,其运动将受到物理引擎的控制。这意味着精灵将受到重力的影响,并且可以在脚本中使用力对其进行控制。通过添加适当的碰撞体组件,精灵还能响应与其他精灵的碰撞。

Rigidbody2D 类提供与 Rigidbody 类基本相同的功能,两者的区别在于:Rigidbody2D 用于 2D 环境,Rigidbody 用于 3D 环境。


⑥ 用于返回挂接Rigidbody2D 组件的游戏对象,GetComponent

微信图片_20221020195850.png

  _rigidbody2d = GetComponent<Rigidbody2D>();

对于此行代码,当我在游戏角色Ruby上挂着了Rigidbody2D 脚本,在Ruby运行该脚本,调用Start函数之后,就会返回Ruby游戏对象。


上述代码存在一个与C#不同的坑,看到尖括号<>的第一反应可能是泛型,但是泛型是用在定义通用类中,而此处的Getcomponent是一个公共函数

参加文献 —— C#泛型(Generic)


⑦ 表示 2D 向量和点 的 Vector2类的构造器 以及 变量

Vector2 —— Vector2构造器

构造器会使用传入的参数产生一个新的向量,normalized则是让向量的长度最大只能为1,通过这个限制,就能够解决速度叠加问题。

微信图片_20221020195930.png

⑧ 表示刚体的速度矢量,即刚体位置的变化率,velocity

脚本API —— Rigidbody.velocity


3) 总结


① 清楚游戏角色对象移动的本质是位置的改变,因此我们应该围绕获取游戏对象的位置,修改其位置开展代码编写来实现角色移动。


②掌握按照速度*时间的方式来产生移动,避免出现因为帧率而产生不同的运行效果。


③ 基本知晓本篇文章中总结的8个经常在角色移动中经常涉及的类、方法、变量


相关文章
|
存储 前端开发 JavaScript
前端学Ruby:全栈论坛(地宫)项目二
前端学Ruby:全栈论坛(地宫)项目二
56 0
|
关系型数据库 数据库 Docker
前端学 Ruby:唐诗API项目
前端学 Ruby:唐诗API项目
105 0
|
机器人 图形学 Ruby
【unity learn】【Ruby 2D】角色发射飞弹
【unity learn】【Ruby 2D】角色发射飞弹
|
机器人 图形学 Ruby
【Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏中动画制作(4-1)
【Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏中动画制作(4-1)
252 0
【Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏中动画制作(4-1)
|
定位技术 API 图形学
【Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏世界中各个对象的交互(3-1)
【Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏世界中各个对象的交互(3-1)
300 0
【Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏世界中各个对象的交互(3-1)
|
存储 定位技术 图形学
【猿创征文|Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏地图绘制(2-1)
【猿创征文|Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏地图绘制(2-1)
291 0
【猿创征文|Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏地图绘制(2-1)
|
监控 调度 Ruby
【Ruby高级技术】在项目中使用多线程之后的一系列问题解决方案-同步控制、异常处理、死锁处理
【Ruby高级技术】在项目中使用多线程之后的一系列问题解决方案-同步控制、异常处理、死锁处理
187 0
|
7月前
|
Ruby
|
7月前
|
JSON 数据格式 Ruby
|
7月前
|
调度 Ruby