unity3D实践报告-忍者跑酷

news/2024/10/22 8:31:31/

一、游戏介绍
背景:2D跑酷类游戏背景图需要与主角做相对运动,来让玩家感觉主角在移动,为实现这一效果,就需要背景图的移动,而由于机型的限制,图片资源每张大小不能超过2048*2048,所以做跑酷类游戏的时候需要多张散图拼凑成一张完整的大背景图,但是一个关卡所需要的背景资源又很大,所以就需要有限的背景资源循环使用。
情节:跑酷游戏就算失败也有会有金币之类的收益可以累积到之后的游戏之中,游戏之中还伴随着各项成就的达成,玩家就算死亡,也不是白费劲,总是有所收获的。而闯关类的游戏,死了就什么都没有了。2D跑酷类游戏是模拟3D场景的效果的一个过程,主要就是怎么样通过一些2D图片来呈现3D游戏的效果。在这里我主要总结了三点。在3D场景中随着障碍物的移动,其相应的坐标和大小也会发生变化。
让场景动起来。3D场景中是通过给主角一个速度让游戏场景跟随运动。而在2D游戏中可以选择让场景动起来(因为所谓的动是相对的,场景移动看起来就是主角在移动),因为受到各种因素的影响(比如场景中存在天空,若让主角动不好处理),我们可以选择让相对于主角的物体动起来。场景中物体的随机生成逻辑。为了游戏的趣味性,要让场景中物体的生成具有随机性。而且还要控制生成间隔防止物体重叠。
玩法:这是一款轻松爽快的跑酷游戏,玩家需要轻触屏幕躲避路途中的障碍,击杀拦路的敌人。同时还要收集路途中的金币。通过使用金币升级技能,购买道具来获得更高的分数。游戏中还有大量的任务供玩家完成。
二、总体设计
2.1游戏场景设置

2.2关卡跳转设计

2.3 操作方式
设置Player左右move程序脚本,用AddForce添加力,刚体组件LinerDrog可设置行走阻力。
三、详细设计
3.1物体的移动缩放
物体的移动会有一个从远到近的过程,我们知道离得越远的物体在我们的眼中是很小的,而离我们越近的物体我们会感觉很大。所以为了模拟真实世界中的物理效果,我们需要处理物体由远到近的过程中物体的缩放,在物体向主角靠近的过程中逐渐增大物体的Scale。
3.2场景的移动
若场景中存在交通线(类似斑马线)可以通过两张图片的动态切换实现道路的移动,场景中物体的移动轨迹不是直线,所以需要控制好物体移动和缩放的速度比来到达一个平衡。
3.3物体生成逻辑
物体的生成逻辑有很多,要根据具体的需求制定不同的方案。在这里作者根据自身的项目需求简述一种。该项目中物体分为两类,一类是道路两边的装饰物,一类是道路上的障碍物。在生成处也就是视觉最远处设置一个空物体作为父物体,创建几个生成点并放在父物体下,物体的实例生成可以放在每个生成点的节点下,这样只需通过控制父物体的位置和缩放来控制所有的物体。物体的间隔主要利用时间进行控制,将时间控制在一个随即范围内来保证物体不会发生重叠。另外为增加生成的随机性,每个生成点下随机生成物体,也可以为空(为空的简单处理就是创建一个空物体进行实例化)。
四、调试与测试

4.1基本设置
修改素材中“back”的【import setting】中的[Pixels Per Unit]属性从100到16(每个单位格中有多少个像素点)
4.2场景构成
unity提供全套的Tile工具来编辑地图,在场景中创建Tilemap游戏对象,场景中将出现一个[Grid]对象并带有一个[TileMap],Grid就是Tile的画布,可以设置画布每个单元的大小,通过调出【Tile Palette】窗口可以进行Tile的绘制。创建一个新的Palette(调色板)并保存在适当的位置,就可以向其中导入Sprite资源了,导入一张包含多个内容的Sprite资源时,应当将其Mode改为[Multiple],然后进入编辑界面进行Slice(切割),切割时注意切割设置,在此案例中选择[Grid By Cell Size]。切割完成后,原来的Sprite素材会包含分割完成的多个素材,将切割完成的Sprite素材拖拽导入【Tile Palette】,即可对每一个单元格进行绘制。点击所需要的Tile,选择brush(笔刷),即可在Grid中绘制场景
4.3图层&角色建立
图层排序[Sorting Layer],根据需要选择相应的图层排序(从上到下的图层为从后往前),若想要调整处于同一图层排序的对象的层次,则使用[Order in Layer],此属性越大越在前方
4.4角色建立
(注意[Pixels Per Unit]属性的大小)常创建一个Sprite对象,将Idel文件夹中的角色Sprite拖拽到【Sprite Renderer】中(或直接将一个角色Sprite拖拽入场景生成),创建角色实体:添加碰撞体和刚体,添加地形碰撞体:Tilemap Collider。
角色移动
void Movement()
{
float move = Input.GetAxis(“Horizontal”);
if (move != 0)
{
playerRig.velocity = new Vector2(move * speed, 0);
}
}
角色方向&跳跃
代码修正
1.增加左右移动判断,通过Scale道正人物朝向
void Movement()
{
float move = Input.GetAxis(“Horizontal”);//不灵敏的变速运动,若使用Raw则会向一个方向一直运动

	float direction = Input.GetAxisRaw("Horizontal");if (move != 0 && direction != 0){playerTransform.localScale = new Vector3(direction, 1, 1);//调整人物朝向 playerRig.velocity = new Vector2(move * speed, 0);}
}

2.进一步修正,通过deltaTime使移动更加均匀,并将移动函数的调用调整到FixedUpdata中(避免机器产生的差异),但相应基础速度值需要增大很多

void Movement()
{
float move = Input.GetAxis(“Horizontal”);//不灵敏的变速运动,若使用Raw则会向一个方向一直运动
float direction = Input.GetAxisRaw(“Horizontal”);
if (move != 0)//移动判断
{
playerRig.velocity = new Vector2(move * speed * Time.deltaTime, playerRig.velocity.y);
playerAnim.SetFloat(“Running”, Mathf.Abs(direction));
}
if (direction != 0)//朝向判断
{
playerTransform.localScale = new Vector3(direction, 1, 1);//调整人物朝向
}
}
3.通过FixedUpdata进行的移动函数调用会意外停顿
角色跳跃
1.添加角色跳跃代码(未修正手感等)
if (Input.GetButton(“Jump”))
{
playerRig.velocity = new Vector2(playerRig.velocity.x, jumpForce);
}

1.关于Tile的碰撞器
TileMap可以在现有基础上加一个CompositeCollider2D,并把原来的TileMapCollider2D的Used By Composite钩上,这样每一个瓦片的碰撞框会合并到一起,减少消耗,同时消除原碰撞体情况下可能导致的Bug,(注意这里地面刚体组件应当设置static)

动画效果
Run
1.从Idel状态到Run状态的切换应当立即切换,因此要取消勾选[Has Exit Time],并且将[Setting]中的[Transition Duration](切换时间)设置为0
2.由于转换标签类型为float,因此使用Raw数据作为判据(直接使用GetAxis可能导致无法恢复Idel)

Jump
1.设置多条判断Tag
2.通过Collider和Layer进行地面碰撞判断
错误修正
关于碰撞体
1.人物原有的方形碰撞体和地形的交互会存在一些问题,再这里为角色再新增一个圆形碰撞体,和方形碰撞体共同构成人物碰撞体(注意人物与地面的碰撞判断使用了原来的方形碰撞体,这里需要修正)

镜头控制
基本跟踪方式
1.可变动x或y轴的镜头跟踪

public Transform player;
void Update()
{
this.transform.position = new Vector3(player.position.x, player.position.y, transform.position.z);
}
考虑到背景,可以采取锁定y轴的镜头跟踪(置位置向量中y坐标为基准值)

使用Cinemachine插件
设置基本属性
1.添加一个2D摄像头(会覆盖原有摄像头)
2.将要跟随的角色拖拽入[Fallow]
镜头边际锁定
1.为Cinemachine 2D摄像头添加Confiner组件
2.为游戏背景添加多边形碰撞体,并加入Confiner组件
3.调整碰撞体为触发器
设置可收集物品&Prefabs
设置可收集物品
1.在场景中初始化收集物,添加动画,添加碰撞体(触发器)
2.为收集物设置Tag,便于在脚本中判断

private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag.Equals(“Collections”))
{
Destroy(collision.gameObject);
}
}
注意,此处销毁时应销毁collision.gameObject
3设置计数变量记录收集物获得数
保存预制体
1.将制作完备的Player和收集物保存为预制体
其他
设置更丰富的图层,并丰富场景
物理材质&空中跳跃
物理材质
1.解决遗留问题(当人物跳跃撞击地形后保持摁下移动,人物将挂在地形上无法正常下落),这是由于物理摩擦问题,再这里创建2D物理材质设置相应属性,并配置给Player的碰撞体
跳跃问题
1.使角色可以在地面进行跳跃,但不能在空中进行跳跃,可以进行如下两种修改:
(1)角色控制脚本中添加布尔变量couldJump作为判据,当角色处于地面时(利用碰撞判断)时置为true,进行跳跃后在移动控制方法中置为false
(2)直接将地面碰撞检测加入跳跃判断

UI入门
1.创建画布
2.创建文本框
3.通过脚本控制文本框(相应设置分数等)
注意事项
1.利用锚点限定UI的相对位置
2.是否应当将静态文本和分数分离为两个文本框?
3.由于碰撞检测的频率问题可能导致收集物带来两次分数加成
解决方案:通过动画事件来触发计数
Enemy
设置敌人
1.设置敌人,增添刚体和碰撞体脚本,添加动画

消灭敌人
1.在脚本中添加消灭敌人方法
注意,再这里通过tag辨别碰撞信息时,触发器和碰撞体有如下差别:
(收集物相关代码)
if (collision.tag.Equals(“Cherrys”))
{
Destroy(collision.gameObject);
cherry++;
cherryText.text = “Cherry:” + cherry;
SetCount(10);
}
(消灭敌人相关代码)

if (collision.gameObject.tag.Equals(“Enemys”))
{
Destroy(collision.gameObject);
}
碰撞体需要间接通过碰撞对象获得tag

2.进一步修改,碰撞到敌人时应当触发角色“受伤”事件,消灭敌人应当仅限于踩踏,这里借助动画状态机的逻辑进行实现,在人物下落状态时发生碰撞才会消灭

优化
消灭敌人后,可以为角色添加一个类似超级玛丽的弹起的跳跃效果。这里使用跳跃控制代码放入成功消灭敌人的代码块中

人物受伤
1.人物受伤应被弹开,并且触发受伤动画效果
值得一提的是,项目中原本用来控制角色运动的是刚体速度属性,这似乎会产生一些问题,官方文档中并不建议使用改写速度的方式来控制运动,而提倡使用addForce等
这里暂时使用改写速度的方式,判断角色在左边还是右边,然后给角色一个相应方向的速度,在消灭敌人方法中加入:

else
{
playerRig.velocity = new Vector2(transform.position.x - collision.transform.position.x, jumpForce * Time.deltaTime);
isHurt = true;
//playerRig.velocity = new Vector2();
//playerAnim.SetBool(“Injured”,true);//置于动画切换方法中
}
由于Movement方法在FixedUpdata方法中一直在调用,运动时横向速度在被不断改写,因此加入判断条件,使受伤时Movement不被调用

if (!isHurt)
{
Movement();
}
重置isHurt的代码置于动画切换方法中

else if (isHurt)
{
if (Mathf.Abs(playerRig.velocity.x) < 0.1f)
{
isHurt = false;
}
}
问题
1.角色运动控制中,关于向量的使用
2.游戏运行时,时常会有动画未能正常切换到Idel,人物仍在跑动的情况
这里是由于Running这条tag(float)未能正常降为0,可以在脚本中适当位置直接手动设置为0
3.跑动下落偶尔会使人物嵌入地形

15:敌人移动(2019_11_23)
1.修改Frog的碰撞体为圆形碰撞体(避免与地形交互时发生的卡顿情况)
2.使Frog左右移动
(1)在脚本中获得Frog刚体组件控制位移,并且使之能够判断边界
方案1:通过两个空物体来限定Frog移动范围(为使空物体易于编辑,这里可以选择一个可视的彩色图标),两个空物体作为Frog的子物体并存储为预制体

public Transform LeftPoint,RightPoint;//获得左右临界点位置
1
void Movement()
{
if (isLeft)
{
FrogRig.velocity = new Vector2(-speedTime.deltaTime, FrogRig.velocity.y);
if (this.transform.position.x<=LeftPoint.position.x)//越过左侧点翻转
{
this.transform.localScale = new Vector3(-1, 1, 1);
isLeft = false;
}
}
else
{
FrogRig.velocity = new Vector2(-speed
Time.deltaTime, FrogRig.velocity.y);
if (this.transform.position.x>=RightPoint.rotation.x)
{
this.transform.localScale = new Vector3(1, 1, 1);
isLeft = true;
}
}
}
这里注意,左右临界点设置为Frog的子物体后,会跟随Frog同步运动,因此需要对此进行调整:
方案1:获取到两个Transform后使两个临界点不再是Frog子物体

this.transform.DetachChildren();
1
方案2:仅获得左右临界点位置值,然后进行销毁

void Start()
{
leftx = LeftPoint.position.x;
rightx = RightPoint.position.x;
Destroy(LeftPoint.gameObject);
Destroy(RightPoint.gameObject);
}
16:Animation Events
1.修正下落动画的触发,使角色初始化时或从高台平移下落时也可以触发下落动画
playerAnim.SetBool(“Idel”, false);
if (playerRig.velocity.y<0.1f && !playerCollider.IsTouchingLayers(ground))
{
playerAnim.SetBool(“Falling”, true);
}
2.使用动画事件,为Frog增加跳起和下落动画
void SwitchAnim()
{
if (FrogAnim.GetBool(“Jumping”))
{
if (FrogRig.velocity.y<0.1f)
{
FrogAnim.SetBool(“Jumping”, false);
FrogAnim.SetBool(“Falling”, true);
}
}
if (FrogCollider.IsTouchingLayers(ground) && FrogAnim.GetBool(“Falling”))
{
FrogAnim.SetBool(“Falling”, false);
}

	#region#endregion
}

void Movement()
{

	if (isLeft){//FrogRig.velocity = new Vector2(-speed*Time.deltaTime, FrogRig.velocity.y);if (transform.position.x <=/*LeftPoint.position.x*/leftx-1)//越过左侧点翻转{transform.localScale = new Vector3(-1, 1, 1);isLeft = false;}if (FrogCollider.IsTouchingLayers(ground)){FrogAnim.SetBool("Jumping", true);FrogRig.velocity = new Vector2(-speed * Time.deltaTime, jumpForce * Time.deltaTime);}}else{//FrogRig.velocity = new Vector2(speed*Time.deltaTime, FrogRig.velocity.y);if (transform.position.x >=/*RightPoint.rotation.x*/rightx+1){transform.localScale = new Vector3(1, 1, 1);isLeft = true;}if (FrogCollider.IsTouchingLayers(ground)){FrogAnim.SetBool("Jumping", true);FrogRig.velocity = new Vector2(speed * Time.deltaTime, jumpForce * Time.deltaTime);}}

增添如上代码后,在Updata中仅调用SwitchAnim即可

3.其他问题
1.Frog的左右跳跃过程中,存在朝向和速度方向不协调的问题。
在这里可以:在转向代码前将水平速度手动调零(未解决)

17:Class调用
Eagle动画效果
1.注意锁定x轴的移动,避免玩家角色施加的作用力使Eagle脱离设定位置

单个Enemy被消灭的特效制作
1.添加Enemy死亡动画
2.代码逻辑实现
(1)使Frog内置Death方法和OnJunp方法,分别用于调用死亡特效动画和销毁物体,将原来的通过碰撞体踩踏“Enemy”销毁的逻辑修改,先常见创建一个Frog类的对象并通过GetComponent方法获得碰撞体的相应脚本引用,然后调用其OnJump方法销毁对象
(问题:未能对各种敌人进行统一管理)
(2)将Death和OnJump功能互换,通过在Death动画结束后插入事件实现死亡特效

通过创建Class主类,使所有Enemy都能调用动画效果
(解决上述遗留问题)
1.创建一个Enemy类用于统一管理敌人
(1)在Enemy中,定义Protected的Animator变量Anim,在Awake或Start中完成初始化。使Frog和Eagle成为Enemy子类。若想要子类可以继承其Awake或Start等方法并可重写,在Enemy的方法中声明virtual关键字,在子类相应方法中声明override关键字,并在子类对应方法中通过base.XX();继承
(2)将Death和JumpOn方法转移到父类中进行统一调用(声明为public),然后更新消灭敌人部分的代码
(问题:Enemy被消灭后播放死亡特效动画时,爆炸效果会根据原来的运动状态发生移动)

18:音效Audio
BGM
1.为Player添加Audio Source(这个举动只会配适给当前场景的Player,不会自动添加在Prefab上。想要配适给所有的Player可以通过Overrides按钮添加)

其他
1.添加怪物死亡音效(注意取消开始时播放),在代码中实现调用(置于OnJump中,若置于Death可能会由于对象销毁而无法正常播放)
2.添加跳跃音效
3.添加受伤音效
4.添加收集物收集音效
5.添加。。。
19:对话框Dialog
1.在Canvas中添加一个Panel,并将其放在合适的位置
2.在Panel中增加Text显示文本
3.通过在相应对象上设置触发器用于Panel的显示,将Panel控制脚本设置给相应的对象(Panel的引用需要使用GameObject)
4.通过动画系统为Panel的显示增加渐变效果

20:下蹲效果Crouch
1.代码修正
若在FixedUpata中调用移动控制代码时,应使用fixedDealtTime,若使用dealtTime应置于Updata中进行调用、
2.按键设置
在项目设置里修改Input属性,为Jump增加“w”作为副键,并复制一个设置更名为Crouch
3.设置Crouch动画,添加相关代码

void Crouch()
{
if (Input.GetButtonDown(“Crouch”))
{
playerAnim.SetBool(“Crouching”, true);
boxCollider.enabled = false;
} else if (Input.GetButtonUp(“Crouch”))
{
playerAnim.SetBool(“Crouching”, false);
boxCollider.enabled = true;
}
}
将下蹲方法置于Movement方法中引用
4.加入代码限制,使角色无法在卡在夹缝中时起立而被卡主
(1)在角色下添加一个空物体,作为头顶检查点
(2)使用Physics2D中的OverlapCircle方法进行检查
(问题:暂未添加由跑动到下蹲的动画状态转换逻辑)
if (!Physics2D.OverlapCircle(CellingCheck.position, 0.2f, ground))//
{
if (Input.GetButtonDown(“Crouch”))
{
playerAnim.SetBool(“Crouching”, true);
DisCollider.enabled = false;
} else if (Input.GetButtonUp(“Crouch”))
{
playerAnim.SetBool(“Crouching”, false);
DisCollider.enabled = true;
}
}
这里0.2f的判定半径需要根据实际情况有所调整

21:场景控制
1.代码修正
在完成了前述代码后,控制角色移动时,保持下蹲姿势从夹缝中走出后,角色无法自动恢复Idel状态。这里可以对代码作出如下修改:
if (!Physics2D.OverlapCircle(CellingCheck.position, 0.5f, ground))
{
if (/Input.GetButtonDown(“Crouch”)/Input.GetButton(“Crouch”))
{
playerAnim.SetBool(“Crouching”, true);
DisCollider.enabled = false;
} else /if (Input.GetButtonUp(“Crouch”))/
{
playerAnim.SetBool(“Crouching”, false);
DisCollider.enabled = true;
}
}
将GetButtonDown和GetButtonUp的使用调整为GetButton(下蹲需要长摁),此时脱离夹缝地形可以自动恢复站立
2.掉落死亡机制和场景重启
(1)在场景下端设置“死线”,用于判定角色下落死亡,并重置场景

if (collision.tag.Equals(“DeadLine”))
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
将以上逻辑包装为一个方法,通过Invoke调用来实现延迟调用,然后禁用所有音频

//场景重置
if (collision.tag.Equals(“DeadLine”))
{
GetComponent().enabled = false;//禁用所有音频
Invoke(“Restart”, 2);
}
3.关卡切换
在切换点设立触发器,挂载脚本,通关按下按键切换场景
(问题:关于文本框的动画触发)
这里可以使用两种方法:
(1)通过切换门的触发器,在触发器中时,按下E切换场景(无效,可能由于按键类操作需要在Updata中)
(2)将脚本加载到EnterDialog上,触发代码置于Updata中
这里使用(1)的思路,在Updata中检测碰撞
if (doorCollider.IsTouching(playMainCollider))
{
if (Input.GetKeyDown(KeyCode.E))
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);//切换到下一个编号的场景
}
}
22:2D光效
1.将Tilemap的材质修改为Default-Diffuse(默认的漫反射类型),并新建同类型的材质给场景中包括Player的其他对象
2.在适当位置添加点光源,2D开发中点光源仍是一个3D物体,其在2D平面上的照射和其z轴位置有关,因此需要注意调整光源的z轴
23:代码优化
1.Animator条件瘦身
在动画切换中,可以将代码和状态机中“Idel”相关的进行删除(因为Idel是默认的动画效果)(未更正)
2.跳跃手感的优化
在官方文档中,有关物理计算如Rigbody相关的内容置于FixedUpdata中进行调用更为顺滑,而GetButton相关的方法则在Updata中调用更合适(都需要使用deltaTime或fixedUpdata平衡),因此需要调整代码内容
此中,跳跃可以修改为GetButton来进一步调整手感
3.Enemy死亡后Bug消除
Enemy死亡后仍会进行一定的物理运动,在Death中销毁Enemy前禁用其Collider来阻止这种运动
4.避免角色移动速度太快时Cherry计数器的重复触发(并添加收集动画)(未更正)
建立一个统御收集物的类用于管理所有收集物,将PlayerController中的相关逻辑迁移至其中
(问题:跳跃功能出现bug,会莫名其妙跳的很低,偶尔会跳的异常高,并时常陷入Tilemap)
24:视觉差Parallax
——使场景中不同层次的景观以不同的速度移动,来造成视觉上的偏差
1.整理场景中的各类对象
2.新建本Parallax控制视差
public Transform CameraTransform;
public float MoveRate;
private float startPointX,startPointY;
public bool lockY = false;
// Start is called before the first frame update
void Start()
{
startPointX = transform.position.x;
startPointY = transform.position.y;
}
// Update is called once per frame
void Update()
{
if (lockY)
{
transform.position = new Vector2(startPointX + CameraTransform.position.x * MoveRate, transform.position.y);
}
else
{
transform.position = new Vector2(startPointX + CameraTransform.position.x * MoveRate, startPointY + CameraTransform.position.y * MoveRate);
}
}
(问题:部分场景的起始位置会发生很大改变)

25:主菜单MainMenu
1.新建场景Menu,通过UI制作主菜单
2.在Canvas中,新建两个Panel,其一作为主菜单背景,其二作为主菜单控制面板
3.完善主菜单页面显示
4.完善主菜单功能,编写场景载入脚本,并在按钮上添加相应点击事件(其中,退出事件在游戏测试中无法生效,需要完成导出后实现)

public void PlayGame()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}

public void QuitGame()
{Application.Quit();
}public void UIEnable()
{GameObject.Find("Canvas/MainMenu/UI").SetActive(true);
}

5.加入主菜单的动画效果

26:暂停菜单和AudioMixer
暂停菜单的基本构建
1.根据25中步骤完善菜单的基本页面构建,游戏画面中设置Pause按钮用于调出菜单,菜单中设置Continue按钮用于返回游戏
2.在脚本中添加按钮需要的方法(通过Time.timeScale控制游戏暂停)

AudioMixer
1.创建一个AudoMixer用于音量控制
2.将Player中的BGM的输出设置为该混音器
3.将暂停菜单的Slider的端值设置为混音器的声音端值
4.在代码中引用混音器,创建方法用于控制声音输出的大小
5.将混音器中的Volume一项设置为可被代码修改的
6.在Slider中添加拖动事件,选择代码中设置的方法“bgmVolume”(这里将会有上下两个方法供选择,应选择上面的一个)
27:手机控制/触控测试/真机测试(略)
28:二段跳/单向平台
1.二段跳和跳跃手感的优化
(1)定义一个管理跳跃的bool变量,通过物理检测的方式判断跳跃是否可以进行
(2)定义一个变量用于可跳跃次数的管理,以此实现二段跳
(3)重新编写跳跃方法
(在代码中,可以通过Alt+上下来调整光标所在行的行位置)

在FixedUpdata中

isGround = Physics2D.OverlapCircle(GroundCheck.position, 0.2f, ground);
1
新的Jump方法

void NewJump()
{
if (isGround)
{
extraJump = 1;
}
if (Input.GetButtonDown(“Jump”) && extraJump>0)
{
playerRig.velocity = Vector2.up * jumpForce;//Vector.up等效于new Vector(0,1)
extraJump–;
playerAnim.SetBool(“Jumping”, true);
}
if (Input.GetButtonDown(“Jump”) && extraJump==0 && isGround)/
{
playerRig.velocity = Vector2.up * jumpForce;
playerAnim.SetBool(“Jumping”, true);
}
}
2.单向平台的实现
(1)新建管理单向平台的Tilemap
(2)为该Tilemap添加PlatformEffector2D组件,取消Use Collider Mask(勾选后可从单向平台上跳下),勾选TilemapCollier的Used By Effector(注意最后修改Layer)
五、团队成员及分工
组长 丁世杰 总体设计,场景的创建,素材人物的分割,人物各种动作的脚本书写,实践报告书写等。
组员 王聪聪 游戏登录注册页面代码,背景音乐添加,预制体的创建,游戏中物体生成代码,实践报告总结等
组员 张冰洁 游戏设置和退出游戏代码书写,图层的创建,物体碰撞的代码书写,实践报告等。
六、项目开发实践总结
本次游戏开发过程中学到了很多知识,有些东西课堂上老师也是讲过了,但是在真正自己使用的过程中往往会出现一些问题,而且自己不知道什么原因,就是因为自己学的和实践没有能够有效的结合起来。通过游戏项目的创作,熟悉了游戏的开发流程,还有一些游戏中具体人物和物体之间有着怎样的联系,该如何控制人物等等。其中在游戏中也遇到了很多问题,比如预制体在脚本中没有正常生成,人物原有的方形碰撞体和地形的交互会存在一些问题,应该再游戏中为角色再新增一个圆形碰撞体,和方形碰撞体共同构成人物碰撞体等等。遇到问题去网上搜索原因及解决方法,这也是我们提升的一个地方。通过这个开发的一个小游戏,熟悉了整个课堂学到了知识,也熟悉了游戏的开发流程和解决问题的能力,小组分工的方式也让我们有了团队合作意识和如何合理分工。我们的游戏人物的动作以及游戏场景还比较单一,下一步我们将会优化这些问题,多创建几个场景供用户选择,使得界面更加优化。


http://www.ppmy.cn/news/414603.html

相关文章

UNITY 跑酷学习2

前言 今天又看了知乎&#xff0c;又看到了学习方法&#xff0c;里面提到意志力的重要性&#xff0c;以及有效学习的概念&#xff0c;我看到了里面说&#xff0c;写博客能增强我的意志力&#xff0c;所以我今天来将昨天的工作添加到博客&#xff0c;算一次积累&#xff0c;训练意…

单片机中移植lua解释器

一、基本开发环境 开发环境基于野火STM32开发板。 前测试的 Lua 解释器版本为 5.4.2。 官网下载lua资源包&#xff0c;下载地址如下&#xff1a; https://www.lua.org/ https://github.com/rjpcomputing/luaforwindows/releases lua: Lua 国内镜像 (gitee.com)‍ 二、移植Lua解…

对象存储服务MinIO简介

黑马程序员学习资料 MinIO简介 MinIO基于Apache License v2.0开源协议的对象存储服务&#xff0c;可以做为云存储的解决方案用来保存海量的图片&#xff0c;视频&#xff0c;文档。由于采用Golang实现&#xff0c;服务端可以工作在Windows,Linux, OS X和FreeBSD上。配置简单&…

Python 中的结构模式匹配

文章目录 结构模式匹配简介及其重要性在 Python 中使用结构模式匹配match ... case 语句的基本使用使用 match ... case 来检测和解构数据结构使用 match ... case 与捕获模式和序列模式使用 match ... case 和通配符模式在类模式中使用 match ... case使用 match ... case 和 …

AIGC 加持 Cocos,游戏开发需要几步?

近日&#xff0c;游戏行业知名的 B2B 大会 WN 2023 大会于土耳其首都伊斯坦布尔顺利举办。本次大会邀请了来自全球的游戏开发商、媒体、发行商、分发平台等行业决策者&#xff0c;共同探讨游戏行业未来发展态势&#xff0c;进一步拓展业务&#xff0c;并在世界范围内寻找新的合…

智驾传感器新风向!拐点将至

“大家都比较关注激光雷达&#xff0c;尤其是在今年整个行业聚焦降本的大背景下&#xff0c;这个赛道还行不行&#xff1f;”6月8日&#xff0c;2023年度&#xff08;第十四届&#xff09;高工智能汽车开发者大会上&#xff0c;高工智能汽车研究院首发《2023-2025年中国汽车市场…

华为认证 | HCIA-SDN 考试大纲

01 考试概述 02 考试范围 HCIA-SDN V1.0考试覆盖数据通信基础知识&#xff0c;SDN架构&#xff0c;SDN二、三层网络原理&#xff0c;SDN接口协议原理比如OpenFlow协议、Netconf协议、RestFul协议原理&#xff0c;以及在华为交换机与路由器中的实现。 SDN二三层技术&#xff1…

Ubuntu显示设置

作者 QQ群&#xff1a;852283276 微信&#xff1a;arm80x86 微信公众号&#xff1a;青儿创客基地 B站&#xff1a;主页 https://space.bilibili.com/208826118 参考 linux系统配置x11,配置Xorg X11窗口系统 恢复ubuntu20.04默认桌面管理器 Ubuntu18.04多显卡配置显示输出&…