Unity2D学习记录第四期
Unity2D学习记录第四期
一、二段跳及其动画逻辑
二段跳其实不是很难,在我的理解来看就是加一个变量来记录跳跃次数,所以实现了二段跳就意味着可以很多段的跳跃,以下就是我写的代码:
//记录跳跃的次数
public int jumpcount = 0;
//jump的代码段,每次跳跃都要记录下来给跳跃次数加一
if (Input.GetButtonDown("Jump") && jumpcount<=1){
rb.velocity = new Vector2(rb.velocity.x, jumpforce);
jumpcount++;
anim.SetBool("jumping", true);
anim.SetBool("falling", false);
}
//用于管理下落动画和站立动画的部分
//注意给下落判断一些余地这样才不容易出现动画闪现的情况尽管这更多的是用户的操作问题
void SwitchAnim() {
anim.SetBool("idle", false);
if (anim.GetBool("jumping")){
if (rb.velocity.y < 0.3){
anim.SetBool("jumping", false);
anim.SetBool("falling", true);
}
}else if (coll.IsTouchingLayers(ground)){
anim.SetBool("falling", false);
anim.SetBool("idle", true);
jumpcount = 0;
}
}
强调一下动画,在这之前的动画可能也有这方面的问题,但是因为视觉效果是可以接受的所以没有提到。在unity中所有的动画状态都有留存时间,如果不希望动画有留存的话就要记得吧Has Exit Time和Transition Duration都取消掉.
二、踩头消灭敌人后弹跳和碰撞检测
在写这篇文章的时候我还不知道怎么判定矩形碰撞域的上边,但是我们可以另辟蹊径,可以设置两个碰撞域,敌人头部的圆形碰撞域和下身的矩形碰撞域,这样就可以实现效果了。而对于消灭后的弹跳其实也简单,就是在判定检测触发后再次调用jump的内容即可
private void OnTriggerEnter2D(Collider2D collision){
//enemies
if (anim.GetBool("falling"))
{
if (collision.gameObject.tag == "Enemy")
{
Destroy(collision.gameObject);
rb.velocity = new Vector2(rb.velocity.x, jumpforce);
anim.SetBool("jumping", true);
}
}
}
其实这就是之前收集物的那套代码,但我在做的过程中就有很有意思的事情了。
实际上unity的碰撞检测有两种,一种叫做触发检测trigger,一种叫做碰撞检测collision,两者起码在现阶段看来其实没有什么太本质的区别,最大的不同在于触发检测的碰撞域是允许和其它碰撞域重叠的也就意味着它会掉下去如果给它设置刚体属性. 而自然敌人肯定是有刚体属性的,那么为什么这里是出发检测那. 这就是最有意思的地方,之前提到了设置两个碰撞域,而实际上头部的圆形碰撞域是触发类型的碰撞域和收集物一样,这样就实现了真正的踩头消灭而不是下落动作消灭.
ps:两种碰撞检测在编程上有一些比较重要的区别
首先他们有共同的特点会有函数形参碰撞事件collision,trigger的能记录的更加详细一些,所以可以直接调用collision.tag这样来获取碰撞物的tag信息,但是碰撞检测就只能collision.gameObject.tag这样来调用.
但不管如何collision.gameObject才是被碰撞物,所以其实直接用这种方式来统一代码我觉得更加好.
三、受伤效果
这里特指触碰怪物后的效果,但如果是别的受伤效果其实也类似,如果需要血条可以参考前一张的UI自己设置,这里专注于受伤效果的统一模板
private bool isHurt = false;
//movement是管理平地移动和跳跃的函数
void Update(){
if(!isHurt)
Movement();
SwitchAnim();
}
void SwitchAnim() {
anim.SetBool("idle", false);
if (anim.GetBool("jumping")){
if (rb.velocity.y < 0.3){
anim.SetBool("jumping", false);
anim.SetBool("falling", true);
}
}else if(isHurt){
anim.SetBool("hurt", true);
anim.SetFloat("running",0);
if (Mathf.Abs(rb.velocity.x) < 1f){
isHurt = false;
anim.SetBool("hurt", false);
anim.SetBool("idle", true);
}
}else if (coll.IsTouchingLayers(ground)){
anim.SetBool("falling", false);
anim.SetBool("idle", true);
jumpcount = 0;
}
}
//collide enemy
private void OnCollisionEnter2D(Collision2D collision){
if (collision.gameObject.tag == "Enemy"){
isHurt = true;
if (transform.position.x < collision.gameObject.transform.position.x)
rb.velocity = new Vector2(-5, rb.velocity.y);
else
rb.velocity = new Vector2(5, rb.velocity.y);
}
}
思路比较简单,主要是用isHurt的bool型变量来引入受伤状态。因为update每一帧都会刷新运行所以就需要用受伤状态来阻止它的运行,然后用速度的绝对值小于1作为退出受伤状态的条件。需要注意的一个地方是running需要手动设置为0,因为浮点数实际上是比较难变成0的,最好手动设置一下。
这里贴上动画控制图方便代码的理解
代码中只做了run到hurt的部分,可以自己手动做一下剩余的几个部分
四、总结
这一期主要是对之前内容的一些扩展,虽然篇幅不长但是涉及代码的部分较多,细节也自然会多一些。下一期将会制作敌人的AI移动,届时游戏应该显得更加有活力一些