Visual Studio 2022 开启AI智能提示
右上角搜索,输入”intellicode“,然后在“常规”中,勾选“整行完成”即可:
【良好的编码习惯】函数封装
比如选中某一行代码,可以使用快捷键Ctrl+.,或者右键选择“快速操作与重构”:
选择“提取方法”:
然后命名(示例为Movement)即可。
碰撞检测
为了防止“无限跳越”的情况发生,因此需要设置碰撞检测。
首先,选择“Platform”组件,在其属性中的layer中,增加一个layer,起名为“Ground”:
然后在Layer中选择新建后的”Ground“图层,接着需要检测Player的位置以确定”地面“的位置,然后判断只有接触地面的时候,Player才可以跳跃,需要在C#脚本中实现。
首先创建一个地面半径检测函数public float GroundcheckRadius;
,然后创建OnDrawGizmos
,来绘制检测区域,使用线球体(Gizmos.DrawWireSphere),参数为中心和半径(中心为Transform的位置,半径则为GroundcheckRadius):
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(transform.position, GroundcheckRadius);
}
此时回到Unity的界面,Player的属性中就会出现GroundcheckRadius的属性,通过输入数值或拖动,可以调整检测区域(但此时的检测区域只能以Player为中心进行缩小和放大,无法对区域进行拖动):
由于需要设置检测区域为Player组件的正下方(即角色的脚底),因此首先要在Player下方创建一个Empty Object,命名为GroundCheck,然后在C#代码中修改:
public Transform GroundCheck;
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(GroundCheck.position, GroundcheckRadius);
}
此时回到Unity界面,在右侧属性中,将GroundCheck拖动至Player的GroundCheck,然后选择GroundCheck组件,就可以对检测区域进行任意拖动了:
设置好检测区域后,还需要在C#中编写代码来进行碰撞检测:
private void collisionCheck()
{
groundDetected = Physics2D.OverlapCircle(groundCheck.position,groundCheckRadius);
}
然后要记得在Update中调用碰撞检测collisionCheck
。此时回到Unity界面,播放查看:
可以看到Ground Detected被成功检测到,但是如果将Player组件挪动,离开地面时,会发现Ground Detected依然是勾选状态的。这是因为它检测自身引起的,因此还需要对C#代码进行完善,通过创建一个层变量来解决该问题:
public LayerMask whatIsGround;
private void collisionCheck()
{
groundDetected = Physics2D.OverlapCircle(groundCheck.position,groundCheckRadius,whatIsGround);
}
然后在Unity界面中,将whatIsGround设置为Ground:
再次播放,当挪动Player组件离开地面时,Ground Detected问题解决。最后就是增加一个判断,当检测到碰撞地面时才可以跳跃即可。
private void Jump()
{
if(groundDetected)
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
}
连续(浮空)跳跃问题获得解决。
【良好的编码习惯】‘分割线’
通过使用[Header("")]
可将某个特性进行‘归类’,从而在属性窗口增加其易读性:
[Header("Collision Check")]
public float groundCheckRadius;
public Transform groundCheck;
public bool groundDetected;
public LayerMask whatIsGround;
切片
在导入资源后,选中要切片的资源,在Sprite Mode中选择“Multiple”,然后点击Sprite Editor,在切片类型中,选择“Grid By Cell Size”,然后输入Pixel Size为16*16,点击Apply即可:
此时将Sprite拖入场景后,发现是比较小的,而且是比较模糊的,然后再次选择素材的Sprite,在Pixels Per Unit中将值改为16:
然后在Compression中选择None,在Filter Mode中选择Point(no filter),就可以解决模糊问题:
动画制作
首先在Assets文件中新建一个文件夹,起名为Animation,然后在Animation文件中创建Animator Controller,起名为Player_AC,然后点击上方的Player组件,将Player_AC拖入右侧的属性窗口,就可以在属性窗口中随时调整Animator的属性。
接着打开Windows-Animator和Animation窗口,将导入资源中的素材2(2个图片)拖入Animation窗口,然后播放时会发现人物的眨眼动作过于快速,因此需要将采样率降低,通过点击Animation窗口右上角的按钮,将Samples显示出来:
然后在左侧Samples的值从60降低为4,再次播放就会发现眨眼动作变慢了。这一步是将人物静止时的动作做好了,接下来做人物在走动时的动画。
同样在Animation窗口左侧,新建(Create New Clip..),起名为playerMove,然后将导入资源中的走路的两张图片拖入Animation窗口,同样调整Samples采样率为6左右。
然后切换到Animator窗口,在playeridle按钮上点击右键,选择创建过渡(Make Transition),将箭头拖入playerMove,在左侧Parameters中,点击+号,新建一个Bool,起名为isMoving来判断人物是否在行走中:
同样的步骤,在playerMove上点右键,创建过渡,将箭头拖入playeridle,然后点击箭头后,在右侧属性窗口,将isMoving选择为false(同理,另一个箭头的isMoving选择为true)。
此时,回到场景(Scene),点击播放,通过右侧属性窗口,勾选isMoving,如果一切正确,就可以看到人物会在眨眼和走路动作中切换。
最后需要在C#代码中,将移动动作判定实现:
首先创建一个Animator的对象,并在Start中获取该组件:
private Animator anim;
void Start()
{
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
}
然后封装一个AnimationController的方法,增加判断(判断人物的X坐标是否为0,如果为0则表示人物为静止状态):
private void AnimationControllers()
{
bool isMoving = rb.velocity.x != 0;
anim.SetBool("isMoving", isMoving);
}
Blend Tree(混合树)
首先在Animation窗口中,创建两个(Create New Clip..),一个名为playerJump,一个名为playerFall,分别拖入导入素材中Jump和Fall图片,然后在Animator窗口中,可以将playerJump和playerFall的按钮删除,然后创建一个Blend Tree(From New Blend Tree),起名为“Jump/Fall”:
然后双击“Jump/Fall”按钮,将左侧的Blend更名为yVelocity,然后在右侧属性窗口,添加两个Motion Field:
分别为playerFall和playerJump,然后在Threshold中分别设置-1和1来表示人物的跌落和跳跃,最后在代码中增加yVelocity来控制人物的跌落和跳跃:
private void AnimationControllers()
{
bool isMoving = rb.velocity.x != 0;
anim.SetBool("isMoving", isMoving);
anim.SetFloat("yVelocity",rb.velocity.y);
}
回到Animator窗口,右侧创建一个bool,起名为“isGrounded”,用于判断是否接触地面,然后在playeridle按钮中创建过渡至Jump/Fall,并在右侧属性中将过渡持续时间调为0:
同样,再创建一个返回的过渡。但这样完成后有一个小问题,就是人物可以从空闲状态中切换至Jump/Fall状态,但无法从移动(Move)状态切换至Jump/Fall状态:
设置完过渡后,还要记得在C#代码中增加isGrounded的设置:
private void AnimationControllers()
{
bool isMoving = rb.velocity.x != 0;
anim.SetBool("isMoving", isMoving);
anim.SetFloat("yVelocity",rb.velocity.y);
anim.SetBool("isGrounded",isGrounded);
}
接着来解决无法从移动(Move)状态切换至Jump/Fall状态的问题,一种方法是,删除人物从空闲状态到Jump/Fall状态的过渡,转为从Any State状态到Jump/Fall状态的过渡:
(推荐)另一种更加简洁的方法是,删除playeridle和playerMove的按钮,重新创建一个新的Blend Tree,起名为Idle/Move,左侧窗口创建一个float,起名为xVelocity:
然后双击Idle/Move按钮,在右侧属性窗口,首先将Parameter设置为刚刚新建的xVelocity,然后创建3个Motion Field,并分别设置为playerMove、playerIdle、playerMove,并将Threshold设置为0、-1、1:
接着回到Base Layer层,选中Idle/Move按钮,右键设置该层为默认层:
删除Any State与Jump/Fall的过渡,增加Idle/Move与Jump/Fall的过渡,同样要记得修改过渡的持续时间以及isGrounded的Bool值:
最后在C#代码中进行调整,调整后的代码则更加简洁明了:
private void AnimationControllers()
{
anim.SetFloat("xVelocity", rb.velocity.x);
anim.SetFloat("yVelocity",rb.velocity.y);
anim.SetBool("isGrounded",isGrounded);
}
回到Unity界面,点击播放,如果一切正常,人物在空闲状态时,会眨眼睛,在移动时会切换走路状态,而在跳跃时,则会有跳跃和跌落状态的切换。