8.1 基本概念
这个炮弹,老余想刚开始的话,还是简单些比较好,毕竟是一门初级炮,做成圆的比较好,这玩意的难点在于方向(指哪里打哪里)和做一点爆炸效果出来。
8.2 炮弹
老余做了一个圆球(Sphere)当作炮弹,根据小余的要求,把炮弹从传统的黑色改成了绿色,看得出来,小余还有点美术细胞。老余也没有忘记把炮弹做成Prefab。
8.3 发射点
发射点是要解决炮弹从炮管发射出来的位置,它应该准准呆在炮口射出炮弹的位置,而且是在StdTurret这个几点下面,记住凡是改了Prefab的地方,需要在override的那个地方Apply All才能生效。
8.4 爆炸效果
起爆炸效果之前,老余改造了一下敌人通过的路线的质地,他他们有碰撞的感觉,加上了Box Collider:
然后老余生成了一个Particle System的节点,叫BulletImpactEffect:
其实老余没想做太复杂,毕竟是方块世界吗,有碰撞感和节操散落一地碎片的感觉就行了
其实就是改属性这几个地方就行,U3D已经把这部分做的很不错了:
除了基础项,还要勾上下面这几项:
基础选项数值照这个填写:
Emission选项和Shape选项
Collision选项和Renderer选项
8.5 让子弹飞
指引炮弹准确飞向敌人靠的是炮塔指引
在属性部分加了Header就是为了在U3D属性部分有分类显示,更清晰,老余做事情有条理,赞一下。其他部分,请看注释,易读的代码自己会说话:
核心部分:
if (fireCountdown <= 0)
{
Shoot();
fireCountdown = 1 / fireRate; // 连续发射及考量频率
}
fireCountdown -= Time.deltaTime;
参考正片:
public class Turret : MonoBehaviour
{
public Transform target;
[Header("General")]
public float range = 15;
[Header("Use Bullets (default)")]
public GameObject bulletPrefab;
public float fireRate = 1;
private float fireCountdown = 0;
[Header("Unity Setup Fields")]
public string enemyTag = "Enemy";
public Transform partToRotate; // 旋转部分的引用
public float turnSpeed = 10f; // 炮塔转动速度
public Transform firePoint;
// Update is called once per frame
void Update()
{
if (target == null)
{
return;
}
LockOnTarget();
if (fireCountdown <= 0)
{
Shoot();
fireCountdown = 1 / fireRate; // 连续发射及考量频率
}
fireCountdown -= Time.deltaTime;
}
/// <summary>
/// 锁定敌人
/// </summary>
void LockOnTarget()
{
// Target lock on
Vector3 dir = target.position - transform.position; // 炮塔和敌人的间距向量
Quaternion lookRotation = Quaternion.LookRotation(dir);
// 使用Lerp转动更加柔和,简单写的话可以Vector3 rotation = lookRotation.eulerAngles, 不过这个转动就有点硬
Vector3 rotation = Quaternion.Lerp(partToRotate.rotation, lookRotation, Time.deltaTime * turnSpeed).eulerAngles;
partToRotate.rotation = Quaternion.Euler(0f, rotation.y, 0f);
}
void Shoot()
{
// 根据预制类,生成炮弹
GameObject bulletGO = (GameObject)Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
Bullet bullet = bulletGO.GetComponent<Bullet>();
// 指引炮弹追踪敌人
if (bullet != null)
{
bullet.Seek(target);
}
}
追上敌人,消灭敌人需要的是炮弹
using System;
using UnityEngine;
public class Bullet : MonoBehaviour
{
private Transform target;
public float speed = 70;
public int damagePoints = 50; // 伤害值
public GameObject impactEffect; // 引用爆炸效果
public void Seek(Transform _target)
{
target = _target;
}
// Update is called once per frame
void Update()
{
if (target == null)
{
Destroy(gameObject);
return;
}
Vector3 dir = target.position - transform.position; // 获得炮弹本身和目标方向,距离
float distanceThisFrame = speed * Time.deltaTime;
// 如果小于或等于1帧间距,就做出打击动作和效果
if (dir.magnitude <= distanceThisFrame)
{
HitTarget();
return;
}
// 如果大于1帧间距,就紧随目标
transform.Translate(dir.normalized * distanceThisFrame, Space.World);
transform.LookAt(target);
}
/// <summary>
/// 打击目标物,并延迟出现方块爆炸效果
/// </summary>
private void HitTarget()
{
// 动态生成效果,并延迟销毁
GameObject effectIns = (GameObject)Instantiate(impactEffect, transform.position, transform.rotation);
Destroy(effectIns, 2f);
// 销毁敌人
Destroy(target.gameObject);
// 销毁炮弹自己
Destroy(gameObject);
}
}
这下,子弹可以飞了。