Preface: this section is mainly about adding enemies and adding movement logic to enemies, as well as the injury status and animation of characters and enemies
1, Add enemy
1. Open sunny land - > artwork - > sprites - > enemies - > Frog - > idle, select any one and drag it into the sense window (remember to set Pixels Per Unit)
2. Create an empty object in Hierarchy and name it Enemies. Put the frog just added under Enemies for easy management
3. Add a 2D circular Collider and 2D rigid body for frog, and adjust the Collider to the appropriate size.
2, Add animation (refer to chapter 04 for the detailed steps of creating animation and animation switching. Only the steps are described here, and the specific operation process is omitted)
1. Add the collection classification folder Enemies in project - > asset - > animation
2. Create an Animation of frog in the Animation window and add an Animation (frog_idle, frog_jump, frog_fall, frog_death)
(death animation is in sunny land - > artwork - > sprites - > FX - > enemy death)
3. Set animation switch
3, Injury status
1. Any State
Here, a state Any State needs to be added. Any State represents all States in Animator.
Usage scenarios, such as injury status and death status. Whether the character or the enemy is standing, running, jumping, climbing or flying, they can switch to this kind of state. If one state is connected back and forth, the state transition will become very complex.
At this time, use Any State to go to such a state to use only one connection
Note: Any State includes all States, which means it also includes the death state here. It is necessary to remove the √ of can transition to self in the figure below, otherwise the dead cycle of death - > death will appear.
Here, frog is added with the effect of triggering death after injury when isDamaged is turned to true.
2. Add injury status to character
Similarly, the character also sets an injury state for the character through Any State. The character can be restored to its original state after injury, so a bool value is given to identify that it can be cut out of the hut state.
(death animation in sunny land - > artwork - > sprites - > player - > hurt)
3. Limit the enemy's range of movement
When the enemy moves in the scene, they need to set a range to prevent them from losing. Here, the range of frog moving left and right is specified by two position marks.
Create two empty objects under frog and move them around frog. Then you can get these two positions and set the boundary of frog movement when the code runs.
(leftPoint does not require any other settings and is only used as a position marker)
(tip: you can set the Icon of these two empty objects to display in the editing interface for easy viewing)
4. Upper code
Enemy public method
using UnityEngine; public class Enemy : MonoBehaviour { public bool isDamaged; protected Collider2D enemy_Coll; protected Rigidbody2D enemy_Rbody; protected virtual void Start() { enemy_Rbody = GetComponent<Rigidbody2D>(); enemy_Coll = GetComponent<Collider2D>(); } public void Damaged() { isDamaged = true; enemy_Coll.enabled = false;//When the enemy is injured death, disable the collision body. Anyway, it can be encountered when it disappears enemy_Rbody.constraints = RigidbodyConstraints2D.FreezeAll;//When the enemy is injured death, freeze the rigid body to prevent the collision body from falling out of the ground due to failure } public void Death() { Destroy(gameObject); } }
frog's code
using UnityEngine; public class Frog : Enemy { public LayerMask groundLayer; public bool isOnGround; public Transform leftPoint, rightPoint;//The enemy's left and right range of motion private float leftX, rightX;//x value of range public float moveSpeed = 6f;//Horizontal speed public float jumpForce = 6f;//Longitudinal velocity protected override void Start() { base.Start(); //Obtain the preset points on the left and right of AI and obtain the horizontal x value leftX = leftPoint.transform.position.x; rightX = rightPoint.transform.position.x; Destroy(leftPoint.gameObject); Destroy(rightPoint.gameObject); } void FixedUpdate() { isOnGround = enemy_Coll.IsTouchingLayers(groundLayer); } private void Movement() { //Turn if you exceed the range of motion float posX = transform.position.x; if (posX < leftX) transform.localScale = new Vector3(-1, 1, 1); else if (posX > rightX) transform.localScale = new Vector3(1, 1, 1); //Give AI enemies horizontal speed (forward) and vertical speed (jump) enemy_Rbody.velocity = new Vector2(moveSpeed * -transform.localScale.x, jumpForce); } }
Enemy animation
using UnityEngine; public class EnemyAnimation : MonoBehaviour { private Animator enemy_anim; private int isOnGroundID; private int yVelocityID; private readonly string State_isDamaged = "isDamaged"; private Frog frog; private void Start() { frog = GetComponent<Frog>(); enemy_anim = GetComponent<Animator>(); //Note: the Parameters in StringToHash should be consistent with the Parameters set in Animator isOnGroundID = Animator.StringToHash("isOnGround"); yVelocityID = Animator.StringToHash("yVelocity"); } private void Update() { enemy_anim.SetFloat(yVelocityID, GetComponent<Rigidbody2D>().velocity.y); enemy_anim.SetBool(isOnGroundID, frog.isOnGround); if (frog.isDamaged)//Trigger death animation when injured enemy_anim.SetTrigger(State_isDamaged); } }
Code to be added for role
public class PlayerControl : MonoBehaviour { public bool isHurt; void FixedUpdate() { //Put it on the top of the original code to identify that if you are injured, you cannot operate the role if (isHurt) return; } private void OnCollisionEnter2D(Collision2D collision) { if (collision.gameObject.tag == "Enemy") { //When encountering the enemy, if the character's position is higher than the enemy and the speed is down, it is regarded as stepping on the enemy GameObject enemyObj = collision.gameObject; if (transform.position.y > enemyObj.transform.position.y && player_Rbody.velocity.y < 0) { player_Rbody.velocity = new Vector2(player_Rbody.velocity.x, 5f);//Give the character a little jump enemyObj.GetComponent<Frog>().Damaged();//Call the enemy's injury method } //Otherwise, it will cause damage to the character and make the character retreat slightly else { bool isOnLeft = transform.position.x < enemyObj.transform.position.x; player_Rbody.velocity = new Vector2(isOnLeft ? -3f : 3f, player_Rbody.velocity.y); isHurt = true; } } } private void HurtEnd() { isHurt = false; } }
Hang on frog
5. Supplementary animation events
After reading the above code, it is not difficult to find that Frog's Movement(), Enemy's Death(), PlayerControl's hurend (), are not used.
This is because Frog's Movement() needs to be placed behind the standing animation ID, Enemy's Death() needs to be placed after the disappearance animation, and PlayerControl's hurend () needs to be placed after the character's injury animation.
It is not difficult to find that these are called in the form of animated events.
6. Supplementary label
In the code, it is judged that the tag is used to collide with the enemy. Remember to set frog for this. Without this tag, you can add one at the bottom of the drop-down box (Add Tag)
So far, frog's simple action, character's injury and the way to destroy the enemy have been completed