Unity Development Diary [Day 6] - Enemy, Injury and Movement Feel Improvement

Table of contents

1. Realization of the enemy

Second, the realization of the injury effect 

3. Code optimization and double jump implementation


1. Realization of the enemy

Trying to add enemies today to make the game more interesting

First, follow the previous steps to use the material to make animations of three enemies

The components that need to be added here (the enemy first needs to be a rigid body, and then animations and collision bodies need to be added)

Some of the operations here are no different from the previous blog, so I won’t go into details here. Here we will try to add the effect of characters destroying monsters. The idea here is the same as that of collectibles, but note that we cannot use collision objects here. Set it as a trigger, which will cause the monster to fall out of the map directly, so we use another function here

The idea is the same as the previous collectibles. In order for our script to identify what the item is currently colliding with, we need to add a Tag

In this way, we can use this Tag to distinguish the object type in the script, but we found that there will be a bug after we write the code, that is, we will destroy the monster as long as we encounter it, which does not conform to our idea, our thinking It will be destroyed by stepping on it, so we use whether it is in the falling state as the condition for elimination

Then in order to achieve the effect of stepping on monsters and jumping, you can add a jumping function when destroying

private void OnCollisionEnter2D(Collision2D collision) //消灭怪物
{
    if(anim.GetBool("falling") && collision.gameObject.tag == "enemy")
    {
        Destroy(collision.gameObject); //消灭怪物
        rb.velocity = new Vector2(rb.velocity.x, jumpforce); //跳跃
        anim.SetBool("jumping", true);
    }
}

Second, the realization of the injury effect 

Then we have the enemy to make the effect of injury. First of all, our idea is that when the player touches the enemy, it will be injured and bounce back. We first implement such a function in the code.

 if(collision.gameObject.tag == "enemy")
 {
    if(anim.GetBool("falling"))
    {
        Destroy(collision.gameObject); //消灭怪物
        rb.velocity = new Vector2(rb.velocity.x, jumpforce); //跳跃
        anim.SetBool("jumping", true);
    }
    else if (transform.position.x < collision.gameObject.transform.position.x) //如果玩家在敌人的左侧
    {
        rb.velocity = new Vector2(-10, rb.velocity.y);
    }
    else if (transform.position.x > collision.gameObject.transform.position.x) //如果玩家在敌人的左侧
    {
        rb.velocity = new Vector2(10, rb.velocity.y);
    }
}

 But after execution, we found that there is no rebound effect. After analysis, it is because our Move function will continue to execute, covering our changes, so we define a bool value to judge whether it is injured, and do not execute Move when it is injured.

private bool isHurt;
if(!isHurt)
{
    Move();
}

We will change this variable to true at the place where the player is injured, but there is a new bug that the player will keep moving back and cannot stop. We need to switch the player's state back in the animation switching function, so here we first put Add the animation, then add this animation to the animator and add a hurting variable as the judgment condition

Then we rewrite the part of the animation transition function

if(Mathf.Abs(rb.velocity.x) < 0.1f) //人物可以返回站立状态
{
    anim.SetBool("hurting", false);
    isHurt = false;
    anim.SetBool("idleing", true);
}

 In this way, our effect is realized, which is relatively simple.

3. Code optimization and double jump implementation

After a few days, my code has been very messy, and there are still many places that can be optimized. I decided to optimize the code, and then implement a double jump function

public Transform groundCheck; //地面检测点

First of all, in order to realize the double jump, I defined a ground detection point to judge whether the player returned to the ground, and then wrote a corresponding judgment variable

public bool isGround;

 Note that when not initialized here, the default is false.

bool jumpPressed;
int jumpCount;

Then define the variables for the jump button press and count

if(Input.GetButtonDown("Jump") && jumpCount > 0)
{
    jumpPressed = true;
}

Then change the original jump function to the code of whether to allow jumping in Update, we will implement another jump function to achieve jumping

We first create an empty object for the character to use for ground detection

We put this variable at the bottom of the foot

 

 Like the previous squat idea, we use this object to detect whether we are standing on the ground

isGround = Physics2D.OverlapCircle(groundCheck.position, 0.1f, ground);

The implementation part of the jump

void Jump() //控制玩家跳跃函数
{
   if(isGround) //落到地面恢复跳跃次数
   {
        jumpCount = 2;
   }

   if(jumpPressed && jumpCount > 0) //跳跃
   {
        rb.velocity = new Vector2(rb.velocity.x, jumpforce);
        jumpCount--;
        jumpPressed = false; //确保跳跃执行完毕
   }
}

This code is executed in fixedupdate, so far we have achieved a smooth double jump, and then we will modify the character animation

But this leads to a problem that the jumping animation will be displayed when the character climbs the slope. We fix this bug by adjusting the radius of the detection circle

Then we deleted the unused footstep collision body, and then I found a new bug that when double jumping in the air, if it is in the falling state, the double jump will not switch back to the jumping state, so modify the animator and add an edge, successfully resolved the issue

The total code is as follows (after optimization)

using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public Rigidbody2D rb; //刚体
    public Collider2D bodyColl; //身体碰撞体
    public Animator anim; //动画控制器
    public float speed = 10; //速度
    public float jumpforce; //跳跃力
    public LayerMask ground; //碰撞体过滤
    public int CherryCount = 0; //收集品樱桃计数器
    public int GemCount = 0; //收集品宝石计数器
    public Text Cherrynumber; //控制樱桃数目显示的UI
    public Text Gemnumber; //控制樱桃数目显示的UI
    public Transform groundCheck; //地面检测点

    bool isGround, isHurt; //监测玩家状态
    bool jumpPressed;
    int jumpCount;

    void Start()
    {

    }

    void Update()
    {
        if(Input.GetButtonDown("Jump") && jumpCount > 0)
        {
            jumpPressed = true;
        }
        if (!Physics2D.OverlapCircle(rb.position, 0.1f, ground)) //判断人物在下蹲的时候不可以起身,
        {
            if (Input.GetButton("Crouch")) //实现角色下蹲
            {
                anim.SetBool("crouching", true);
                bodyColl.enabled = false;
                speed = 5; //下蹲速度减慢的效果
            }
            else //恢复姿态
            {
                anim.SetBool("crouching", false);
                bodyColl.enabled = true;
                speed = 10;
            }
        }
    }

    private void FixedUpdate()
    {
        isGround = Physics2D.OverlapCircle(groundCheck.position, 0.2f, ground); //检测玩家是否在地面
        SwitchAnim();
        Jump();
        if(!isHurt)
        {
            Move();
        }
    }

    void Move() //控制玩家移动函数
    {
        float Horizontaldirection = Input.GetAxisRaw("Horizontal"); //玩家移动方向
        rb.velocity = new Vector2(Horizontaldirection * speed, rb.velocity.y); 
        if (Horizontaldirection != 0)
        {
            transform.localScale = new Vector3(Horizontaldirection, 1, 1); //控制角色翻转
        }
    }

    void Jump() //控制玩家跳跃函数
    {
        if(isGround) //落到地面恢复跳跃次数
        {
            jumpCount = 2;
        }

        if(jumpPressed && jumpCount > 0) //跳跃
        {
            rb.velocity = new Vector2(rb.velocity.x, jumpforce);
            jumpCount--;
            jumpPressed = false; //确保跳跃执行完毕
        }
    }

    void SwitchAnim() //玩家动画切换函数
    {
        anim.SetFloat("running", Mathf.Abs(rb.velocity.x)); //切换玩家奔跑的动画

        if(isGround)
        {
            anim.SetBool("falling", false); //从下落回到站立
        }
        else if(rb.velocity.y > 0) //向上移动
        {
            anim.SetBool("jumping", true);
            anim.SetBool("falling", false);
        }
        else if(rb.velocity.y < 0) //掉落
        {
            anim.SetBool("jumping", false);
            anim.SetBool("falling", true);
        }

        if(isHurt) //从受伤状态恢复
        {
            anim.SetBool("hurting", true);
            if(Mathf.Abs(rb.velocity.x) < 0.1f) //人物可以返回站立状态
            {
                anim.SetBool("hurting", false);
                isHurt = false;
                anim.SetBool("idleing", true);
            }
        }
    }

    private void OnTriggerEnter2D(Collider2D collision) //物品收集函数
    {
        if(bodyColl.IsTouching(collision) && collision.tag == "cherry") //如果身体碰到了樱桃
        {
            Destroy(collision.gameObject); //销毁游戏体
            CherryCount++; //收集品数量加一
            Cherrynumber.text = CherryCount.ToString();
        }
        if (bodyColl.IsTouching(collision) && collision.tag == "gem") //如果身体碰到了宝石
        {
            Destroy(collision.gameObject); //销毁游戏体
            GemCount++; //收集品数量加一
            Gemnumber.text = GemCount.ToString();
        }
    }

    private void OnCollisionEnter2D(Collision2D collision) //消灭怪物
    {
        if(collision.gameObject.tag == "enemy")
        {
            if(anim.GetBool("falling"))
            {
                Destroy(collision.gameObject); //消灭怪物
                rb.velocity = new Vector2(rb.velocity.x, jumpforce); //跳跃
                jumpCount = 1; //踩到怪物后恢复跳跃次数,但是反弹用掉一次
                anim.SetBool("jumping", true);
            }
            else if (transform.position.x < collision.gameObject.transform.position.x) //如果玩家在敌人的左侧
            {
                rb.velocity = new Vector2(-10, rb.velocity.y);
                isHurt = true;
            }
            else if (transform.position.x > collision.gameObject.transform.position.x) //如果玩家在敌人的左侧
            {
                rb.velocity = new Vector2(10, rb.velocity.y);
                isHurt = true;
            }
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_50688324/article/details/127006130