添加敌人
1.新建青蛙节点
拖动青蛙sprite到场景,命名为FrogSprite
在FrogSprite下新建空子节点,命名为EnemyFrog,使其坐标位置和FrogSprite一致
再将EnemyFrog拖到和FrogSprite一个层级
最后将FrogSprite拖到EnemyFrog的子节点下
注:青蛙上下跳动,使其坐标位置不固定,EnemyFrog用于记录青蛙的坐标
2.制作青蛙动画
在Animations下新建Enemies文件夹,用于存放敌人的动画
点击EnemyFrog,新建动画Frog_Idle,存放在Enemies文件夹下
点击录制按钮,再点击切换到FrogSprite上,切换帧,拖动图片到SpriteRender中的Sprite下,使其更换图片显示
制作完成后,停止record,点击播放测试效果
3.添加基本组件
EnemyFrog添加Rigidbody 2D组件
FrogSprite添加Box Collider 2D组件,调整碰撞区域
新建脚本EnemyController,绑定到EnemyFrog
public float moveSpeed; //移动速度
public Transform leftPoint; //移动范围左边点
public Transform rightPoint; //移动范围右边点
private bool movingRight; //是否向右移动
private Rigidbody2D theRB; //Enemy刚体
public SpriteRenderer theSR; //Enemy SR
在EnemyFrog下添加两个空节点LeftPoint和RightPoint,分别标识移动范围的左右临界点,设置位置,并指向两个Transform
在Start中初始化
void Start()
{
theRB = GetComponent<Rigidbody2D>();
//设置左右点父节点为空,使其为固定点,不随父节点移动而变化
leftPoint.parent = null;
rightPoint.parent = null;
movingRight = true;
}
Update中实现移动
void Update()
{
if(movingRight)
{
//设置速度为moveSpeed
theRB.velocity = new Vector2(moveSpeed, theRB.velocity.y);
theSR.flipX = true;
if(transform.position.x > rightPoint.position.x)
{
movingRight = false;
}
}
else
{
theRB.velocity = new Vector2(-moveSpeed, theRB.velocity.y);
theSR.flipX = false;
if (transform.position.x < leftPoint.position.x)
{
movingRight = true;
}
}
}
4.添加移动和等待时间
添加参数
//暂停
public float moveTime;
public float waitTime;
private float moveCount;
private float waitCount;
Start中初始化
moveCount = moveTime;
Update中加入判断,并设置移动和等待时间随机
void Update()
{
if (moveCount > 0)
{
moveCount -= Time.deltaTime;
if (movingRight)
{
//设置速度为moveSpeed
theRB.velocity = new Vector2(moveSpeed, theRB.velocity.y);
theSR.flipX = true;
if (transform.position.x > rightPoint.position.x)
{
movingRight = false;
}
}
else
{
theRB.velocity = new Vector2(-moveSpeed, theRB.velocity.y);
theSR.flipX = false;
if (transform.position.x < leftPoint.position.x)
{
movingRight = true;
}
}
if (moveCount <= 0)
{
//waitCount = waitTime;
waitCount = Random.Range(waitTime * 0.75f, waitTime * 1.25f);
}
}
else if(waitCount > 0)
{
waitCount -= Time.deltaTime;
theRB.velocity = new Vector2(0, theRB.velocity.y);
if (waitCount <= 0)
{
//moveCount = moveTime;
moveCount = Random.Range(moveTime * 0.75f, moveTime * 1.25f);
}
}
}
5.添加Jump动画
在EnemyFrog上,新建动画Frog_Jump,保存在Animations/Enemies文件夹下
点击record,切换到FrogSprite上,在相应帧上切换图片
在相应帧调整Y坐标,使其看起来上下跳跃
6.动画衔接
切换到Animator,添加bool型参数isMoving
添加衔接Frog_Idle---->Frog_Jump
添加衔接Frog_Jump---->Frog_Idle
新建动画主体参数,在Start中初始化获取
private Animator anim; //动画主体
anim = GetComponent<Animator>();
在Update中判断moveCount后面和else后面分别设置动画
//设置移动动画true
anim.SetBool("isMoving", true);
//设置移动动画false
anim.SetBool("isMoving", false);
7.Curves,优化动画
调节时间点
设置Curves,平缓动画
8.消灭敌人
在player下添加空节点,命名为Stompbox
添加碰撞检测,设置为Trigger,并调整碰撞体大小和位置
新加Tag,命名为Enemy
设置FrogSprite的Tag为Enemy
新建脚本组件Stompbox,绑定至Stompbox节点
添加碰撞检测函数
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Enemy"))
{
//Debug.Log("Hit Enemy");
other.transform.parent.gameObject.SetActive(false);
}
}
9.死亡特效
添加参数deathEffect,并添加死亡特效指向
public GameObject deathEffect;
碰撞检测中加入死亡特效显示
Instantiate(deathEffect, other.transform.position, other.transform.rotation);
10.消灭敌人时,弹起效果
在PlayerController中添加弹力参数bounceForce,添加函数Bounce()给角色加弹力
public float bounceForce; //消灭敌人后弹力
//给角色加消灭敌人后的弹力
public void Bounce()
{
theRB.velocity = new Vector2(theRB.velocity.x, bounceForce);
}
player节点下设置弹力值
在Stompbox中,碰撞检测函数里,加入给角色弹力
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Enemy"))
{
other.transform.parent.gameObject.SetActive(false);
//死亡特效
Instantiate(deathEffect, other.transform.position, other.transform.rotation);
//消灭敌人后给角色加弹力
PlayerController.sInstance.Bounce();
}
}
11.敌人死亡时掉落宝物
在Stompbox中添加参数
public GameObject collectible; //掉落宝物
[Range(0, 100)]public float chanceToDrop; //掉落的几率
碰撞检测里,敌人死亡后添加
float dropSelect = Random.Range(0, 100f);
if (dropSelect <= chanceToDrop)
{
Instantiate(collectible, other.transform.position, other.transform.rotation);
}
在节点Stompbox中,添加宝物,设置掉落几率值
12.敌人攻击角色
在EnemyFrog节点上添加组件Box Collider 2D,并设置
添加脚本组件DamagePlayer,伤害角色
设置Frog_Jump动画,使其与Frog跳跃时一致
调整跳跃时Curves,使其与FrogSprite大致一致
13.该篇章最终代码
Stompbox.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Stompbox : MonoBehaviour
{
public GameObject deathEffect; //死亡特效
public GameObject collectible; //掉落宝物
[Range(0, 100)]public float chanceToDrop; //掉落的几率
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Enemy"))
{
//Debug.Log("Hit Enemy");
other.transform.parent.gameObject.SetActive(false);
//死亡特效
Instantiate(deathEffect, other.transform.position, other.transform.rotation);
//消灭敌人后给角色加弹力
PlayerController.sInstance.Bounce();
float dropSelect = Random.Range(0, 100f);
if (dropSelect <= chanceToDrop)
{
Instantiate(collectible, other.transform.position, other.transform.rotation);
}
}
}
}
EnemyController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyController : MonoBehaviour
{
public float moveSpeed; //移动速度
public Transform leftPoint; //移动范围左边点
public Transform rightPoint; //移动范围右边点
private bool movingRight; //是否向右移动
private Rigidbody2D theRB; //Enemy刚体
public SpriteRenderer theSR; //Enemy SR
private Animator anim; //动画主体
//暂停
public float moveTime;
public float waitTime;
private float moveCount;
private float waitCount;
// Start is called before the first frame update
void Start()
{
theRB = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
//设置左右点父节点为空,使其为固定点,不随父节点移动而变化
leftPoint.parent = null;
rightPoint.parent = null;
movingRight = true;
moveCount = moveTime;
}
// Update is called once per frame
void Update()
{
if (moveCount > 0)
{
moveCount -= Time.deltaTime;
if (movingRight)
{
//设置速度为moveSpeed
theRB.velocity = new Vector2(moveSpeed, theRB.velocity.y);
theSR.flipX = true;
if (transform.position.x > rightPoint.position.x)
{
movingRight = false;
}
}
else
{
theRB.velocity = new Vector2(-moveSpeed, theRB.velocity.y);
theSR.flipX = false;
if (transform.position.x < leftPoint.position.x)
{
movingRight = true;
}
}
if (moveCount <= 0)
{
//waitCount = waitTime;
waitCount = Random.Range(waitTime * 0.75f, waitTime * 1.25f);
}
//设置移动动画true
anim.SetBool("isMoving", true);
}
else if(waitCount > 0)
{
waitCount -= Time.deltaTime;
theRB.velocity = new Vector2(0, theRB.velocity.y);
if (waitCount <= 0)
{
//moveCount = moveTime;
moveCount = Random.Range(moveTime * 0.75f, moveTime * 1.25f);
}
//设置移动动画false
anim.SetBool("isMoving", false);
}
}
}