学习游戏制作记录(史莱姆敌人的制作)
1.史莱姆的状态机
我们需要创建与之前骷髅敌人类似的史莱姆,因此实现骷髅的脚本我们是可以照搬的
修改Enemy_Slime脚本:
public enum SlimeType { big,medium,small}//史莱姆的类型
[Header("Slime Spesific")]
[SerializeField] private SlimeType slimeType;
[SerializeField] private int slimesToCreate;//分裂的数量
[SerializeField] GameObject slimePrefab;//分裂的预制体
[SerializeField] Vector2 minCreateVelocity;//分裂的推力
[SerializeField] Vector2 maxCreateVelocity;
public override void Die()
{
base.Die();
enemyStateMachine.ChangeState(deadState);
if (slimeType == SlimeType.small)//如果是最小的则不分裂
return;
CreateSlime(slimesToCreate, slimePrefab);
}
private void CreateSlime(int _SlimesToCreate,GameObject _slimePrefab)
{
for(int i=0;i<_SlimesToCreate;i++)
{
GameObject newSlime = Instantiate(_slimePrefab, transform.position, Quaternion.identity);//循环创建分裂体
newSlime.GetComponent<Enemy_Slime>().SetupSlime(facingDir);
}
}
public void SetupSlime(int _facingDir)
{
if (_facingDir != facingDir)//设置朝向
Flip();
float xVelocity=Random.Range(minCreateVelocity.x,maxCreateVelocity.x);
float yVelocity=Random.Range(minCreateVelocity.y,maxCreateVelocity.y);
isKnockback = true;
GetComponent<Rigidbody2D>().velocity = new Vector2(xVelocity * -facingDir, yVelocity);//执行推力
Invoke("CancelKnockBack", 1.5f);
}
private void CancelKnockBack()=>isKnockback = false;
2.实现史莱姆的击晕效果
SlimeStunnedState脚本:
public override void Exit()
{
base.Exit();
enemy.state.MakeInvicibale(false);//退出无敌
}
public override void Update()
{
base.Update();
if(rb.velocity.y<.1f&&enemy.isGroundDetected())//如果史莱姆落地
{
enemy.entityFX.Invoke("CancelColorChange", 0);//取消颜色变化
enemy.anim.SetTrigger("StunFold");//播放眩晕动画
enemy.state.MakeInvicibale(true);//被击晕保持一段时间的无敌
}
if (stateTimer < 0)
{
enemy.enemyStateMachine.ChangeState(enemy.idleState);
}
}
3.实现玩家击退怪物的差异
Entity脚本:
[SerializeField] protected Vector2 KnockbackOffest;//击退偏差
protected virtual IEnumerator HitKonockback()
{
isKnockback = true;
float xoffest=Random.Range(KnockbackOffest.x, KnockbackOffest.y);//设置偏差
//if(KnockbackPower.x>0||KnockbackPower.y>0)//这会使玩家的冻结效果失效
rb.velocity = new Vector2((KnockbackPower.x+xoffest) * knockbackDir,KnockbackPower.y);
yield return new WaitForSeconds(KnockbackDuration);
isKnockback = false;
SetZeroKnockBackPower();
}
4.实现敌人在周围检测玩家的统一化处理
Enemy脚本:
public float agroDistance = 2;//仇恨范围
SlimeGrounedState脚本:
public override void Update()
{
base.Update();
if (player == null)
{
player = PlayerManage.instance.player.transform;
}
if (enemy.isPlayerDetected() || Vector2.Distance(player.position, enemy.transform.position) < enemy.agroDistance)//仇恨距离内
{
enemy.enemyStateMachine.ChangeState(enemy.battleState);
}
}