一.主角的问题
1.移动和转身方法的实现
hor和ver获取键盘的Axis轴数据,写个欧拉角转即可
float hor = Input.GetAxis("Horizontal");
float ver = Input.GetAxis("Vertical");
ChangeSpeed();
if(upSpeed)//这个upSpeed是加速的,写个判断是否按下某个键即可
{
transform.position += ver * transform.forward * Time.deltaTime * moveSpeed*2;
transform.eulerAngles += hor * transform.up * turnSpeed;//结束
}
else
{
transform.position += ver * transform.forward * Time.deltaTime * moveSpeed;
transform.eulerAngles += hor * transform.up * turnSpeed;//结束
}
2.开火的方法
按下开火,创建子弹预置体,设置好velocity矢量即可
fire = Input.GetButtonDown("Fire");//获取虚拟按键是否按下
if(fire)
{
GameObject blt =Instantiate(bulletPerf, firePoint.position, Quaternion.identity);
blt.GetComponent().velocity = transform.forward * shotSpeed;
Destroy(blt, 2f);
}
二.摄像机跟随的问题
获取跟随目标的GameObject 测量位置,并保持距离相等
public Transform playerTransform;
private Vector3 offset;
private void Awake()
{
offset = playerTransform.position - transform.position;
}
void Update () {
transform.position = playerTransform.position - offset;
}
三.敌人生成
public GameObject enemy;
public float interval=1f;//坦克生成的时间间隔
private float timer;//计时器
private int tankCount = 0;//计数器
[Header("坦克最多数量")]
[Range(10,60)]
public int maxEnemy = 10;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
timer += Time.deltaTime;
if(timer>interval)
{
//TODO
if (maxEnemy > tankCount)
{
CreateEnemy();
tankCount++;
//每隔一段时间,生成新的坦克(如果不够数的话)
}
timer = 0;
}
}
private void CreateEnemy()
{
Vector3 pos;
do {
float x = Random.Range(-40f, 40f);
float z = Random.Range(-40f, 40f);
pos = new Vector3(x, 1, z);
} while (NotUsePos(pos));//检测到生成的位置有人,就继续随机生成位置
int y = Random.Range(0, 360);//随机一个预置体的角度
Quaternion q= Quaternion.Euler(new Vector3(0, y, 0));//三维变量转换为四元数
GameObject et = Instantiate(enemy,pos, q);//初始化预置体
}
private bool NotUsePos(Vector3 pos)
{
//检测到碰撞体,返回true,没有检测到 返回False
return Physics.CheckSphere(pos, 2f, ~(1 << 8));
//(1<<8||1<<9)表示只检测第八层和第九层,加~为取反
}
public void TankDestory() //外部调用 死了在场坦克数量-1
{
tankCount--;
}
四.敌人AI
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyTankController : MonoBehaviour {
private Transform player; //获取玩家对象
public GameObject bullet; //获取子弹预置体
private float distance;//玩家与当前坦克距离
private float shotinterval=0.5f;//炮弹发射时间间隔
private float shotTimer = 0; //炮弹发射计时器
private float randomTurnTimer = 0; //AI随机转动角度的时间
private float y;//随机转动角度
private Transform firePoint;//获取发射点(炮口)
private RaycastHit hit;//射线碰撞检测
[Header("转身速度")]
public float turnSpeed = 1f;
[Header("移动速度")]
public float moveSpeed = 1f;
[Header("子弹速度")]
public float shotSpeed = 2f;
private void Awake()
{
player = GameObject.FindGameObjectWithTag("Player").transform;
firePoint = transform.Find("Top/Gun/FirePoint");
}
// Update is called once per frame
void Update () {
//計算距離
distance = Vector3.Distance(transform.position, player.position);
if (distance<10)
{
RotateToPlayer();
//TODO:kaipao
Attack();
}else if(distance<20)
{
//TODO:逼近
MoveToPlayer();
}else
{
//TODO:逛街
Patrol();
}
}
private void Attack()//攻击玩家
{
if (!CheckForwardFriend(10))//判断10距离内是否为友军
{
Fire();
}
}
//开火
private void Fire()
{
shotTimer += Time.deltaTime;
if (shotTimer > shotinterval)
{
GameObject blt = Instantiate(bullet, firePoint.position, Quaternion.identity);
blt.GetComponent().velocity = transform.forward * shotSpeed;
shotTimer = 0;
Destroy(blt, 2f);
}
}
///
/// 转向一个地方
///
/// 方向向量
private void RotateTo(Vector3 dir)
{
//方向向量转换为四元数
Quaternion targetQua = Quaternion.LookRotation(dir);
Lerp(targetQua);
}
private void Lerp (Quaternion targetQua)
{
//Lerp对过去
transform.rotation = Quaternion.Lerp(transform.rotation, targetQua, Time.deltaTime * turnSpeed);
}
private void RotateToPlayer()
{
Vector3 dir = player.position - transform.position;
RotateTo(dir);
}
//逼近
private void MoveToPlayer()
{
RotateToPlayer();//先转向
if (!CheckForwardFriend(5))
{
transform.position += transform.forward * Time.deltaTime * moveSpeed;
}
}
//巡逻
private void Patrol()
{
transform.position += transform.forward * Time.deltaTime * moveSpeed;//往前走
randomTurnTimer+=Time.deltaTime;
if (randomTurnTimer > 2)//两秒钟随机转一次向
{
// Debug.Log("gogogo");
y = Random.Range(15, 360);//随机转15-360度之间
randomTurnTimer = 0;
}
Lerp(Quaternion.Euler(Vector3.up * y));
}
//判断前方dis米有无友军
private bool CheckForwardFriend(float dis)
{
if(Physics.Raycast(firePoint.position, transform.forward, out hit, dis))//利用Raycast方法获取范围内射线碰撞到的第一个RaycastHit对象
{
if (hit.collider.transform.root.tag == "Enemy")//该对象组件的根标签为Enemy判断是否为友军
{
return true;//存在友军
}
}
return false;
}
//碰到子弹 死
private void OnCollisionEnter(Collision other)
{
if (other.gameObject.tag == "Coin")//这边子弹的标签为Coin
{
Destroy(other.gameObject);
Destroy(this.gameObject);
GameObject.Find("EnemyTankManager").GetComponent().TankDestory();//跨脚本调用
}
}
}



