玩家控制管理
1) 实现玩家垂直虚拟轴的控制达到自由移动的目的
2) 基础相机跟随
相机跟随:声明固定向量距离,利用玩家与相机之间的固定距离关系得出固定距离:
玩家位置向量 - 相机位置向量 = 固定距离向量;
在帧更新中不断更新相机位置向量,公式变形:
相机位置向量 = 玩家位置向量 - 固定距离向量
这样就可以实现基础的相机跟随,但视角旋转跟随还未实现。
3) 发射炮弹,创建预制体,调整发射点,拿到发射点位置,通过给予刚体.Velocity速度实现炮弹发射,发射方向也设为当前坦克前方方向;
第一人称玩家相机跟随:

敌人行为管理:
1) 敌人预制体创建
1)敌人预制体创建:要求随机位置随机朝向
a.随机位置的管理:
随机地图范围,但是会出现坦克堆叠生成现象
解决方案:
范围为玩家(0,0,0)位置利用Random.range;
生成位置重叠,利用检测一定范围内是否存在碰撞体(此处用的是球形检测),注意此时地面碰撞也得去除
方法是给地图加图层,一般设置为第8层,`~(1<<8)`意思就是排除第8层的检测;主要检测方法是封装布尔函数:
** Physics.CheckSphere(Vector3 position,检测半径,~(1<<8))**
Vector3 Position 一般用do..while()判断生成位置是否重叠,先生成位置,再放入判断函数是否可用
b. 随机角度生成:
利用随机函数随机角度:
int y = Random.Range(0,360)
因为Instantiate( , ,四元数角度)所以需要将随机的Vector3角度转化为四元数:
Quaternion targetAngle=Quaternion.Euler(new Vector3(0,y,0))

2) 敌人数量控制:
定义生成间隔时间internavl,敌人的最大数量maxEnemy,计数坦克器countEnemy,时间计算器timer;
timer+= Time.deltaTime;
if(timer>internavl){
if(countEnemy<maxEnemy){
CreatEnemy();
}
timer=0;
}
3)敌人行为控制(基础AI行为):
主题思路: 10米内开火 ,20米内向着玩家移动,20米外自由移动
开火设计: 1.转向玩家 2.开火
1) 转向玩家: 先拿到与玩家之间的位置向量,转为四元数再使用四元数旋转插值函数完成相对流畅的转向;
Vector dir=player.transform.position-tranform.position
Quaternion targetAngle=Quaternion.LookRotation(dir)
tranfrom.rotation=Quaternion.Lerp(transform.position,targetAngle,Time.deltaTime*转向速度);

2)开火:若前方范围内是友军,则不开火;
检测前方是不是友军,这里用的是物理射线的方式;
先定义射线碰撞器 private RaycastHit hit;
再判断范围内是否是友军:
private bool CheckFriend(float 射线范围){
if(Physics.Raycast(射线发射位置,发射方向为当前前方,out hit ,射线范围长度)){
if(hit.collider.transform.root.tag=="Enemy"){
要拿到射线碰撞到的物体,此处带Enemy标签是有空物体创建+多个子对象物体形成的坦克;
如果直接拿标签是拿不到的比如:hit.collider.tag=="Enemy",是错误的;
所以要拿到其根对象的标签 : 因为root是Transform里的属性,所以要通过transform.root拿;
return true;
}
}
return false;
}

20米内向玩家移动:
1)转向玩家 2) 移动
private void Move()
{
RotateToPlayer();
if (!CheckForwardFriend(2f)) {
transform.position += transform.forward * Time.deltaTime * moveSpeed;
}
20米外自由移动
1) 移动 2) 每隔三秒调整一次方向移动;
private void Patrol() {//随机转向移动
transform.position += transform.forward * Time.deltaTime * moveSpeed
tranfrom.rotation=Quaternion.Lerp(transform.position,
Quaternion.Euler(Vector3.up * y),
Time.deltaTime*转向速度);
if (timer > 3f) {
y = Random.Range(0, 360)
timer = 0
}
}
击中敌人,敌人消失;
我的思路一: 将子弹勾选为触发器挂载脚本,当子弹接触到坦克后,坦克销毁;
但是当我实现时,我发现拿不到敌人标签,还是前面讲述的问题,碰撞体是空物体下的子物体实现的,要想拿到空物体的标签,必须拿到他的根。
other.gameobject.transform.root.tag=="Enemy"
但是新的问题又出现了,我击中后摧毁的确实敌人的零件,击中哪个子物体就摧毁哪个子物体,显然这不是我要的结果;
于是我又声明了新游戏对象,通过标签直接拿到整个游戏对象,然后摧毁时就摧毁这整个对象;
虽然效果实现了但还是不够完美,子弹为触发器后,会穿模地板,我取消了重力,但是击中效果还是有不灵敏现象击中两次才摧毁;
于是我有了第二个想法:
因为我认为敌人对象勾选触发器后会穿地板模型,所以将子弹设为触发器为我的第一思路;
当我勾选敌机为触发器时,显然没有穿模,而且拿到碰撞对象也简单的多,子弹不是空对象可以直接拿,然后触发效果也很顺利,没有出现不灵敏现象;
所以,击中后消失挂载在敌人对象上是最适合的
难道是因为子弹为触发器时子弹速度过快而导致的穿模吗?