26.敌人-移动的敌人
26.1 知识点
明确移动的敌人需求
移动的敌人需要实现以下功能:
- 在多个点之间来回巡逻。
- 敌方坦克始终盯着玩家坦克移动。
- 当玩家坦克距离移动的敌人坦克较近时,按一定攻速开火。
- 敌人坦克死亡时需要加分。
拖拽移动的敌人资源做成预制体
将移动的敌人资源拖拽到场景中,并调整其属性以符合游戏需求。然后将其制作成预制体,以备后续使用。
创建移动的敌人脚本,要让敌方坦克在多个点之间来回的巡逻,让坦克一直看向一个随机点后往前移动,当距离小于一个很小值的时候更新随机点,实现巡逻。Update内要让地方坦克炮口一直盯着玩家坦克。重写死亡函数,移动敌人坦克死亡时需要加分。
using UnityEngine;
// 移动的敌人
public class MonsterObj : TankBaseObj
{
// 当前的目标点
private Transform targetPos;
// 多个巡逻点
public Transform[] randomPos;
// 坦克要一直盯着的目标
public Transform lookAtTarget;
// 开火距离
public float fireDis = 5f;
// 开火时间间隔
public float fireOffsetTime = 1f;
private float nowTime = 0f;
void Start()
{
RandomPos();
}
void Update()
{
// 多个点之间的随机移动
this.transform.LookAt(targetPos);
this.transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
if (Vector3.Distance(this.transform.position, targetPos.position) < 0.05f)
{
RandomPos();
}
// 看向自己的目标
if (lookAtTarget != null)
{
tankHead.LookAt(lookAtTarget);
// 当自己和目标对象的距离小于等于配置的开火距离时
if (Vector3.Distance(this.transform.position, lookAtTarget.position) <= fireDis)
{
nowTime += Time.deltaTime;
if (nowTime >= fireOffsetTime)
{
Fire();
nowTime = 0;
}
}
}
}
// 随机选择巡逻点
private void RandomPos()
{
if (randomPos.Length == 0)
return;
targetPos = randomPos[Random.Range(0, randomPos.Length)];
}
// 开火
public override void Fire()
{
for (int i = 0; i < shootPos.Length; i++)
{
GameObject obj = Instantiate(bulletObj, shootPos[i].position, shootPos[i].rotation);
// 设置子弹的拥有者,用于之后进行伤害计算
BulletObj bullet = obj.GetComponent<BulletObj>();
bullet.SetFather(this);
}
}
// 重写死亡函数
public override void Dead()
{
base.Dead();
// 移动怪物死亡时需要加分
GamePanel.Instance.AddScore(10);
}
}
26.2 知识点代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//移动的敌人
public class MonsterObj : TankBaseObj
{
//1.要让坦克 在两个点之间 来回的移动
//当前的目标点
private Transform targetPos;
//随机用的点 外面去关联
public Transform[] randomPos;
//2.坦克要一直盯着自己的目标
public Transform lookAtTarget;
//3.当目标到达一定范围内过后 间隔一段时间 攻击一下目标
//开火距离 当小于这个距离时 就会主动攻击
public float fireDis = 5;
//为了避免 太难 加一个 攻击间隔时间
public float fireOffsetTime = 1;
private float nowTime = 0;
//开火点
public Transform[] shootPos;
//子弹预设体
public GameObject bulletObj;
//两张 血条的图 外面关联
public Texture maxHpBK;
public Texture hpBK;
//显示血条计时用时间
private float showTime = 0;
//之所以没有new 是因为是结构体 可以不用new 直接在下面赋值
private Rect maxHpRect;
private Rect hpRect;
void Start()
{
RandomPos();
}
void Update()
{
#region 多个点之间的随机移动
//看向自己的目标点
this.transform.LookAt(targetPos);
//不停的向自己的面朝向位移
this.transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
//知识点 Vector3里面有一个得到两个点之间距离的方法
//当距离过小时 认为到达了目的地 重新随机一个点
if (Vector3.Distance(this.transform.position, targetPos.position) < 0.05f)
{
RandomPos();
}
#endregion
#region 看向自己的目标
if( lookAtTarget != null )
{
tankHead.LookAt(lookAtTarget);
//当自己和目标对象的距离 小于等于 配置的 开火距离时
if( Vector3.Distance(this.transform.position, lookAtTarget.position) <= fireDis)
{
nowTime += Time.deltaTime;
if( nowTime >= fireOffsetTime )
{
Fire();
nowTime = 0;
}
}
}
#endregion
}
//随机点
private void RandomPos()
{
if (randomPos.Length == 0)
return;
targetPos = randomPos[Random.Range(0, randomPos.Length)];
}
//开火
public override void Fire()
{
for (int i = 0; i < shootPos.Length; i++)
{
GameObject obj = Instantiate(bulletObj, shootPos[i].position, shootPos[i].rotation);
//设置子弹的 拥有者 用于之后 进行伤害计算
BulletObj bullet = obj.GetComponent<BulletObj>();
bullet.SetFather(this);
}
}
//重写死亡函数
public override void Dead()
{
base.Dead();
//移动怪物死亡时 需要加分
GamePanel.Instance.AddScore(10);
}
//在这里进行血条UI的绘制
private void OnGUI()
{
if(showTime > 0)
{
//不停计时
showTime -= Time.deltaTime;
//画图 画血条
//1.把怪物当前位置 转换成 屏幕位置
//摄像机里面提供了API 可以将 世界坐标 转为 屏幕坐标
Vector3 screenPos = Camera.main.WorldToScreenPoint(this.transform.position);
//2.屏幕位置 转换成 GUI位置
//知识点:如何得到当前屏幕的分辨率高
screenPos.y = Screen.height - screenPos.y;
//然后再绘制
//知识点:GUI中的 图片绘制
//底图
maxHpRect.x = screenPos.x - 50;
maxHpRect.y = screenPos.y - 50;
maxHpRect.width = 100;
maxHpRect.height = 15;
//画底图
GUI.DrawTexture(maxHpRect, maxHpBK);
hpRect.x = screenPos.x - 50;
hpRect.y = screenPos.y - 50;
//根据血量和最大血量的百分比 决定画多宽
hpRect.width = (float)hp / maxHp * 100f;
hpRect.height = 15;
//画血条
GUI.DrawTexture(hpRect, hpBK);
}
}
public override void Wound(TankBaseObj other)
{
base.Wound(other);
//设置显示血条的时间
showTime = 3;
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com