个人项目(4):敌人2
敌人的行动逻辑
第二种类型敌人(即敌人2,远程)当主角位于其攻击范围之外时并不会做任何行动,当主角位于其攻击范围之内时便会向主角进行攻击,当主角进入其被攻击范围时便会逃跑,逃跑方向便是向主角移动方向的相反方向,该行动逻辑的部分实现代码如下:
Vector3 x=follow.position;
Vector3 y=this.GetComponent<Transform>().position;
float distances=Vector3.Distance(x,y);
if(distances<=maxdistance&&distances>mindistance){//当主体对象位于该对象攻击范围内时
movement.Set(0.0f,0.0f,0.0f);
Animator.SetBool("isrunning",false);
as1.Stop();
musicplaying=true;
if(canhit==true){//可以攻击
Animator.SetBool("isattacking",true);
canhit=false;
animaction=true;
}
else if(canhit==false){//攻击冷却
if(animaction==true){//动画执行中
animTimer+=Time.deltaTime;
if(animTimer>=animTime)
{
Animator.SetBool("isattacking",false);
animTimer=0;
animaction=false;//动画结束
}
}
hitTimer+=Time.deltaTime;
if (hitTimer>=hitTime)
{
canhit=true;
hitTimer=0;
animaction=true;
}
}
rotation2();
}
else if(distances<=mindistance){//当主体对象位于该对象逃跑范围时
if(musicplaying==true){
as1.Play();
}
musicplaying=false;
if(canhit==false){
if(animaction==true){
Animator.SetBool("isattacking",false);
animTimer=0;
animaction=false;
}
hitTimer+=Time.deltaTime;
if (hitTimer>=hitTime)
{
canhit=true;
hitTimer=0;
}
}
movement=this.GetComponent<Transform>().position-follow.position;
movement.Normalize();
Animator.SetBool("isrunning",true);
Animator.SetBool("isattacking",false);
rotation1();
}
else if(distances>maxdistance){//当主体对象位于该对象发觉范围外时
as1.Stop();
musicplaying=true;
if(canhit==false){
if(animaction==true){
Animator.SetBool("isattacking",false);
animTimer=0;
animaction=false;
}
hitTimer+=Time.deltaTime;
if (hitTimer>=hitTime)
{
canhit=true;
hitTimer=0;
}
}
movement.Set(0.0f,0.0f,0.0f);
Animator.SetBool("isrunning",false);
Animator.SetBool("isattacking",false);
}
为了避免敌人2随意地使用投掷技能,以及配合动画效果的实现,我为敌人2的投掷也设定了冷却时间,同时也设置了动画时间,确保子弹能在动画相应时间内发射出去。动画控制器如图:
子弹逻辑
既然是远程设计的敌人,那就需要设置远程射击物。因为没有现成模型,我就用胶囊体代表了子弹,因为动画效果是右手攻击一下再左手攻击一下,所以我准备了两颗子弹,一左一右。
当动画开始执行,即人物开始攻击时,右手子弹发射,等动画执行一秒后,此时左手运动,左手子弹再发射。所以我设置了动画时间这一参数,相关的代码逻辑如下:
void Update()
{
if(isfly==false){//子弹不在飞行
GetComponent<Renderer>().enabled = false;
if(mainbody.animaction==true) hit();
else if(mainbody.animaction==false){
transform.position=follow2.position;
}
}
else if(isfly==true){//子弹在飞行
GetComponent<Renderer>().enabled = true;
flytimer+=Time.deltaTime;
if (flytimer>=flytime)
{//子弹返回
isfly=false;
flytimer=0;
transform.position=follow2.position;
}
else{
transform.position = Vector3.Lerp (transform.position, TargetPosition,m_Speed * Time.deltaTime);
}
}
if(ishit==true){//子弹击中主体角色
if(player.invincibility==false){
ishit=false;
player.hp--;
player.ishit=true;
}
}
}
private void OnTriggerStay(Collider other){
if(other.transform==follow1){
ishit=true;
}
}
private void OnTriggerExit(Collider other){
if(other.transform==follow1){
ishit=false;
}
}
void hit(){//子弹飞向主体角色当前所在位置
isfly=true;
TargetPosition=follow1.position+Vector3.up;
transform.position = Vector3.Lerp (transform.position, TargetPosition,m_Speed * Time.deltaTime);
}
void hit(){//子弹经过一段时间后飞向主体角色当前所在位置
waitTimer+=Time.deltaTime;
if(waitTimer>=waitTime)
{
isfly=true;
waitTimer=0;
TargetPosition=follow1.position+Vector3.up;
transform.position = Vector3.Lerp (transform.position, TargetPosition,m_Speed * Time.deltaTime);
}
}
子弹触发器的逻辑与敌人1的攻击触发器逻辑类似。GetComponent().enabled 用于控制模型渲染呈现与否,当其为false时,模型会消失,即隐形,即子弹在飞行时会呈现,不飞行返回人物身边时会消失。我也设置了子弹的飞行时间,当飞行时间到了便会自动返回人物身边,返回的位置是加在人物模型旁边的特定位置(即position1和position2),因为模型移动时该位置也会相对于人物移动,就可以实现子弹返回的效果了(但是因为要添加多个敌人预制件,position1和position2的Tag位置相同的话会造成子弹全部只返回到一个敌人身边,所以我给每个敌人的子弹都重新添加了新的脚本,这就造成了脚本复用率的低下)。