草庐IT

用Unity开发一款2D横版游戏demo

不想敲代码啊啊 2023-10-31 原文

 

# LanW Game Project

目录

(一) 介绍

(二) 安装教程

(三) 开发流程

1.  新建工程

2.  设置人物

3.  控制主角的移动

4.   添加切换动作的动画

5.   镜头跟踪

6.   收集物体

7.   创建ui

8.   创建敌人

9.   制作敌人ai

10.   创建青蛙动画

11.   优化代码

12.   设置音效

13.   制作对话框

14.   制作死亡边界

15.   制作场景切换

16.   制作前中后景视觉差 Parallax

17.   创建菜单

18.   制作音轨

19.   打包游戏

(四)常见问题及解决方法

(五) 致谢


 

 

(一) 介绍

本文主要是介绍了如何使用用unity开发一款简单的横版平台跳跃类游戏demo,该游戏所展现的素材均来自unity商店,开发流程所展示的仅为部分参考代码,该游戏所有工程文件及代码在https://gitee.com/lan-dashai/lan-w-game-project/tree/master

软件环境
Visual stdio 2019 
Unity Hub;
编辑器版本:Unity 2021.3.7f1c1(LTS);


(二) 安装教程

1.  首先在网页搜索网址:https://unity.cn/unity-ggac-2021
2.  点击下载unity hub
3.  安装编辑器版本

(三) 开发流程

1.  新建工程

*Asset Store商店搜索好包 并下载 在Package manager中下载并导入
*将背景图片的Pixels Per Unit 改为16(每个格中含有16像素)并Apply 将背景图片拖入Level窗口加载并reset其位置

主界面如下


 在level中新建2D obj Tilemap
*将背景图片隐藏以便观看 在Window 2D 中选Tile Palette
*在窗口中Create新的 命名为map 在缺省跳到的文件夹中新建文件夹命名maps
*将瓦片素材设置为16 Sprite 自动切割 将Mode改为Mutiple 点击Sprite Editor 点击窗口中的GridByCellSize Pixel设置为16*16 并切割
*切割完点击Apply后将其拖入 Tile Palette  点击画笔绘制地图(关掉edit)(用橡皮可擦掉 记得选择当前的Tile map)
*调整好main camera的属性size设为6
点击背景图片 添加新的Sorting Layer 命名为 Background和Frontground 将背景设置为BG

 

 

2.  设置人物

*将人物图片改为20, 在level中新建2D Sprite 将人物拖拽到Sprite Render的编辑面板的Sprite中 并reset
 点击人物的Add Component 添加Rigidbody 2D(刚体 将纸片变成物件)
*继续为人物添加碰撞体 Box Collider 2D 点击三个盒子相连的图标(编辑)将绿色边框拉至合适位置
 为地图添加Tilemap Collider 2D 此时运行游戏人物可立于地面上

 

 

 

3.  控制主角的移动

*为人物添加代码 Add New Scrips 命名为PlayerController
打开script
创建刚体 public Rigidbody2D Rd; 将刚体拖入到创建的刚体中
创建初速度 public float Speed; 设置为10
创建移动方式 newfloat用来接收input了的GetAxis(horizontal) if语句当它不为0时(即-1或1)Rd.velocity刚体的移动 = newVector2(HorizontalMove * Speed, Rd.velogy.y);
将人物刚体中的Constrains中的Freeze Rotation Z勾上(冻结z轴)否则会发生移动时刚体旋转
试玩中可调整速度参数 但试玩结束后不会保存 需要手动再设置
写代码 修改人物朝向 在移动方式中创建float用来接受input的GetAxisRaw(horizontal)-1 0 1整数 if语句当它不为0时 物体的transform.scale(在unity中) = new Vector3(FaceDirection,1,1);
*(优化代码)将Update修改为FixedUpdate() 让程序在低于60帧的电脑上流畅运行 在*Speed 后再 *Time.deltaTime 保存后将游戏中的Speed改为400(不推荐使用此条 很麻烦)
写代码 创建跳跃的力 public float JumpForce 在Movement函数中添加if语句如果Input.GetButtonDown("Jump") 则Rigidbody.velocity = (Rigidbody.velocity.x, JumpForce * Time.deltaTime); 并设置unity人物的JumpForce为400 将刚体的Gravity Scale重力称改为2

 

 

 

4.   添加切换动作的动画

*为人物添加Add Animator组件 再新建Animation文件夹以管理 下面新建Player文件夹 里面新建Animation Controller 命名为Player 将其拖入到组件中的Controller位置中
点击Window Animation Animation 创建Animation 点击Create创建 命名为Idle(原地站立)将Asset中idle的图片全部改为16 全部拖入时间轴
*将采样率Samples(三个点打开)设置为10 (或者全选节点拖拽至合适长度)
*创建新的Animation 命名为Run 注意文件存放位置 打开Asset中人物图片的Run 图片改为16全部拖入时间轴 Samples采样率改为10 (缺省勾选了Loop Time循环播放)
*在Animator中右键Run Idle Make Transition将两个互相链接 在Animator组件的Parameters组件的下拉三角形中选择Float 添加Float命名为Running
*选中连接线 将Has Exit Time取消勾选(没有动画缓冲 马上切换)Settings中的Transition Duration改为0(不需要转换时间)在Conditions中点击加号添加条件 数值改为0.1 
两条连接线同理操作 Run到Idle的Conditions的Greater改为Less
*写代码 新建变量public Animator Animator;在Movement函数中新增Animator.SetFloat("Running", Math.Abs(接受的Horizontal的绝对值)) 保存后回到unity的人物编码组件 将Animator组件拖入
*创建Animation Jump和Fall 将图片16拖入 在Animator组件中设置好连线(Run,Idle链接Jump,Jump链接Fall,Fall链接Idle)
*添加Prarmeters Jumping Falling Idle
*设置好连线参数 (Run与Idle 的Jumping是true时到Jump)(Jump的Jumping是false且Falling是true时到Fall)(Fall的Falling是false且Idle是true时到Idle)
*打开PlayController脚本
*编写代码 void SwitchAnimation  if(Animator.GetBool("Jumping")){if刚体的y坐标< 0时 设置Jumping为false,设置Falling为true}
*写代码 public LayerMask Ground;以获取地面 将Tilemap的Layer设置添加新的命名为Ground并选择 将Player中编码组件的Ground 设置为Ground
*写代码 public Collider2D Collider2D;以获取人物的碰撞体 续写SwitchAnimation的elseif(Collider2D.IsTouchingLayers(Ground)){设置Falling为false,Idle为true} *在函数最前定义Bool Animator.SetBool("Idle", false);
(出现闪烁则检查图层或elseif)!
*将Box Collider 缩小 为人物新增 Cricle Collider碰撞体 设置到下半身位置
*写代码 将Rigidbody和Animator改外private 在start中写他们的获取方式 = GetCompenent<Rigidbody 2D>; = GetComponent<Animator>;(<>内名字就是unity组件中的名字)
(在定义的时候前面加[SerializeField]可将其设为可见不可操作)

 

 

5.   镜头跟踪

*为Main Camera 添加代码 命名为CameraControl
添加组件Cinemachine 在组件菜单中添加摄像头Create 2D Camera 将player拖拽到Follow中跟随 (Dead Zone调整开始跟随区域 Screen X/Y调整角色固定位置)
ctrl d 复制背景直到填充屏幕 新建Empty命名为BackGround将三个back整理 
在2DCamera中的Add Extension组件中选择CinemachineConfiner
为BackGround添加Polygon Collider2D 并将其设置为is Trigger(打勾)点击编辑将多边形的顶点拉至屏幕边角 不需要的按住ctrl点击可删 将其添加到2D摄像机的Bounding Shape2D中

 

6.   收集物体

*为Cherry创建文件夹 将图片素材改为16后拖拽导入 添加组件Animator 在Assets的动画文件夹下创建AnimationController命名为Cherry 将其拖拽导入到Animator中 在组件编辑器中Create新的Cherry动画 将图片拽入
*为Cherry添加Box Collider2D 点击编辑将其调整好 设置为isTrigger(这是一个检测是否碰撞的装置 并不要让它有碰撞效果)
*为Cherry新建Tag标签 叫做Collection
*打开人物的代码 新建函数void OnTriggerEnter2D() 里面写 if语句if(collision.tag == "Collection"){Destory(collision.gameObject);} 如果碰撞物体的标签是Collection的话就销毁该碰撞物体
*创建计数器 public int Cherry 在销毁后面写Cherry ++;

 

7.   创建ui

*在level1中新建ui画布UI Canvas  右键Canvas 添加UI Text 命名为Cherry
f找到物件位置 将Text移动到合适位置 修改Text内容 并调整合适大小
*在新增UI Text 命名为Numbers 修改Text内容及其属性
写代码获取ui文本 public Text CherryNumber;并using 保存后将Number拖入
*在OnTriggerEnter中新增代码 CherryNumber.text = Cherry.ToString();
(固定文本位置)
*点选Cherry文本的设置方位图(centermiddle图标)并将位置选为始终在左上角
Number文本同理操作
(为Cherry创建UI Image 并为Gem创建UI及碰撞体和代码)

 

 


8.   创建敌人

*创建Enemy Frog 将青蛙图片拖入 创建其Idle和Jump动画 为其添加Rigidbody 2D 及Box collider 2D并调整好碰撞体位置
*写代码 新函数private void OnCollisionEnter2D() {}
if语句 当collision.gameObject.tag (不是trigger类型的需要加gameObject) == "Enemy"; 时 Destory(collision.gameObject)
调整代码 添加新条件 && 当人物正在执行Falling动作时
*写代码 添加人物受伤后退 new public bool IsHurt;在Update中if(IsHurt == false)时 运行Movement;
当碰撞体碰到敌人时 && 人物x轴小于敌人x轴(从左边碰到敌人)则IsHurt = true 人物刚体.Velocity = New Velocity(-10,y)
右边反之同理
*写代码 在SwitchAnimation中新增else if(IsHurt)时 if(刚体的x速度绝对值<0.1f)时 IsHurt = false;(写在下落代码之上 否则会一直运行下落)
*写代码 在IsHurt中添加动画代码条件 并写SetFloat("Running", 0);以确保受伤动作完毕后回到正常动作

 

9.   制作敌人ai

*为Frog添加代码 私有变量rb 在Start中获取GetComponent<>
*在heri中为Frog添加子项目作为它的移动区域 为了方便观察可改变他们的颜色
*写代码 创建IsFaceLeft布尔值以观测 左右移动不超过左右两个点的x y坐标 子物体设置分家DetachChildren
*写代码 创建x y在Start中赋值 运行后将两个点销毁

 

 

10.   创建青蛙动画

*为青蛙分别添加Jump fall 动画 连线并设置
*写代码 将y轴移动改为JumpFoece 添加前置if语句 如果rb.IsTouchingLayers(Ground)并开启跳跃动画
自动执行跳跃 为animation组件控制器添加事件关键帧 将其拖到站立动画的最后 设置Function为写好的Movement() 并将代码中update里的Movement注释
*写代码 添加 SwitchAnimation()
if Jumping则改变跳 落 动画 else if 碰撞到地面则关闭下落动画
*添加青蛙死亡的动画 从Any State连线 添加控制器 Trigger开关 命名为Death
*写代码 为青蛙添加public Death函数
在人物动画中的触碰青蛙中的if语句中 添加EnemyFrog实体 EnemyFrog Forg = collision.gameObject.GetComponent<EnemyFrog>(); 并用Frog调用Death
*写代码 为青蛙添加Destroy函数 Destroy(gameObject); 在Death动画最后添加关键帧 设置为启用销毁

 

 

 

 

 

 

11.   优化代码

*根目录新建C# Enemy 新建变量protected Animator Anim;并获取 并把Start Update函数也改编为protected virtual void Start()(受保护的虚拟函数)
*将EnemyFrog的:父类改为 Enemy 并将青蛙的变量Animator及其Start中的获取 注释
*将青蛙的Start 设为 protected override void Start()(重写父类方法)同时在里面调用 base.Start()
*将Destory和Death函数注释并复制到Enemy中 并全部设为public
*修改人物代码中毁掉青蛙的代码 将new的青蛙注释 改外new Enemy 将底下的青蛙.销毁 改为Enemy.销毁

 

12.   设置音效

*为player添加组件 Audio Source 右上角点击overrides apply all 将所有新加的组件添加到perfabs预设
*在AudioClip中拖拽添加bgm 将Play on Awake勾选(启动游戏时播放)将loop勾选(循环播放)
*点击青蛙heri中的小箭头进入青蛙组件 为其添加AudioScouce 
*写代码 在enemy 中创建爆炸音效变量 protected AudioSource DeathAudio 并getComponent在Death中启用 DeathAudio.play();
同理 为人物add各种音效 写人物代码 public AudioSource ____ 并.play 并在组件中拽入音效 

 

13.   制作对话框

*在level1中的Canvas中新建UI Panel面板 命名为EnterDialog
*为其改变颜色 改变位置至固定在下方 width改为600 height125 Y轴改变至100
*为其创建子项目 右键UI Text 设置位置 内容 文字大小
在房子的门上创建Trigger碰撞体 (触碰到门则出现dialog)
*写代码 添加房子的代码 创建变量gameObject Dialog 
*写代码 添加函数 OnTriggerEnter2D 和OnTriggerExit2D if语句如果碰撞体的tag是player的话 则Dialog.SetActive(true/false); (设置开关)
(为text制作浅入浅出动画)
*为heri中的EnterDialog创建动画 命名EnterDialog
*点击红色圆圈录制 第一帧透明 第20帧显现 停止录制并运行

 

 

14.   制作死亡边界

*level1创建新项目DeadLine 并将其放在布局下面 调整好长度 并将其标签添加并改成DeadLine
*写代码 using UnityEngine.SceneManagement;
*在人物TriggerEnter2D中新增if语句 当collision.tag == "DeadLine"; 时
ScenManager.LoadScene(SceneManager.GetActiveScene().name);
*完善代码 新建函数Restart() 将切换场景剪切到里面
*在if中添加 Invoke("Restart",1);延迟1秒运行Restart切换场景
继续添加GetComponent<AudioSource>().enabled = false; 关闭音乐

 

15.   制作场景切换

*创建代码EnterHouse   using SceneManagement
*在update中写代码 if语句 当按下e时 scenManager.LoadScene(SceneManager.GetActiveScene().buildIndex +1) 当前场景编号+1
*打开File Build Settings 将场景拖入 可观察编号 
*将代码拖拽加入至 enter的dialog中
同理为场景2 写返回场景1的代码

 

16.   制作前中后景视觉差 Parallax

*新建Area 拷贝背景的多边形碰撞体至Area中 删除背景的碰撞体 将摄像机重新设置好
新建代码Parallax
*写代码 添加变量float MoveRate(调整幅度)float StartPoint(确定初始位置)transform Camera(调整位置)
*写代码 Start中获取StartPoint = transform.posion.x
*添加y轴变量  
*添加bool变量 lockY
*update添加if 如果lockY 则运行之前的代码 else y轴 = 初始坐标y + 镜头移动*幅度
*将不希望上下移动的物件的lockY勾选

 

17.   创建菜单

*新建场景Menu
*添加UI Panel 改为黑色 将Source Image(原图像)改为null
*再添加 Panel 控制颜色 改Scource为其添加组件Button Text Mesh... 添加按钮
*调整按钮大小 text文字 颜色
*写代码 Menu 直接创建函数 PlayGame()SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
*添加函数QuitGame()Application.Quit();
*将代码添加到按钮的父类中 在按钮里的On Click组件选择父类 选择PlayGame函数 此时运行游戏可点击按钮进入

 

 

18.   制作音轨

*Assets新建Audio Mixer命名为MainMixer 在Window Audio中找到AudioMixer打开菜单
*为bgm选择Output 选择master 将master的Inspector中的Attenuation的volume 右键改为可编辑的 expose
调整Menu中的音轨 将最小值设置为-80 最大值0
*写代码 在Menu中 新建变量 public AudioMixer AudioMixer 将组件拖入
*写代码 新建函数 public void SetVolume(float值) AudioMixer.SetFloat("刚改的可编辑的代码的名称",float值);
*为音轨条添加代码 用SetVolume函数 选择上面的
*为所有的音效添加master 可一起变换音量

 

19.   打包游戏

Build settings中选择左下角 Player Settings ,设置好自己想要的参数,返回,点击右下角build将游戏打包。

 

(四)常见问题及解决方法

1.提示unable to access unity services. please log in or request membership to this project

解决方法:①点击“Window” —— “General” —— “Service”(或者直接快捷键 ctrl + 0)②点击“new link” —— 选择自己的Project ID —— 点击“create”。

2.Unity报错:The variable ... has not been assigned.

解决方法:给物体添加刚体组件。

3.提示UnassignedReferenceException: The variable target of Moving has not been assigned.You probably need to assign the target variable of the Moving script in theinspector.Moving.Update () (at Assets/_Tutorial/Moving.cs:13)

解决方法:把物体拉到tagger里面进行设置。


(五) 致谢

1.  感谢我的Unity启蒙老师,麦扣老师,@M_STDIO
2.  游戏所使用素材均来自Unity商店
3.  欢迎一起交流学习,有什么问题可以私信我1228193430@qq.com。

 

 

有关用Unity开发一款2D横版游戏demo的更多相关文章

  1. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  2. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  3. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  4. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  5. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  6. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  7. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  8. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  9. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  10. unity---接入Admob - 2

    目录1.AdmobSDK下载地址2.将下载好的unityPackagesdk导入到unity里​编辑 3.解析依赖到项目中

随机推荐