//Bullet.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 子弹类,定义子弹共有行为类
/// </summary>
public class Bullet : MonoBehaviour
{
//public GameObject GameObj;
//子弹类:计算攻击的目标点(玩家检测环境,敌人)(敌人检测环境),执行移动,创建接触特效。
//射线检测变量,设置为本家族可用(设置为public也可以,不过设置protected更为贴切一点,因为不需要其他类调用)
protected RaycastHit hit;
//定义子弹攻击距离(飞多远)
public float attackDistance = 100;
//定义子弹移动速度
public float moveSpeed = 10;
//定义子弹攻击力,根据Gun类提供
//HideInInspector 的解释是在unity编译器中,此字段不可见
[HideInInspector]
public float BulletAtk;
//定义枪类的变量
private Gun GunVar;
//定义子弹移动到目标位置
private Vector3 targetPoint;
//定义层级int变量
public LayerMask mask;
//计算目标点方法
private void CountTargetPoint()
{
//利用射线检测Physics.Raycast是否接触目标点
//第一个参数是发射位置,第二个参数是发射朝向,因为枪类创建子弹的时候已经指定子弹的位置和朝向,所以这里直接this.transform即可拿到
//第三个参数是out 返回的射线信息,第四个参数是射线检测距离,第五个参数是射线检测层层级
//当前位置(枪口位置),当前方向(枪口方向),受击目标信息,攻击最大距离,射线检测层
//加上if判断是否检测到目标
if (Physics.Raycast(this.transform.position, this.transform.forward, out hit, attackDistance, mask))
{
//如果检测到目标,则把hit返回的三维向量目标点给子弹移动到目标位置点变量
targetPoint = hit.point;
}
else
{
//如果射线检测不到目标,则返回自身位置加上子弹攻击距离和朝向(继续向前飞~)
targetPoint = this.transform.position + this.transform.forward * attackDistance;
}
}
//游戏开始时就要开始计算目标点
private void Awake()
{
CountTargetPoint();
}
//计算目标点
//移动--updata调用
//到达目标点:销毁、创建相关特效--在updata里面做判断
private void Update()
{
BulletMoveFF();
//判定当前位置与目标点,如果接近到0.1,则代表到达目标点
if ((this.transform.position - targetPoint).sqrMagnitude < 0.1f)
{
//到达目标点后销毁子弹物体
Destroy(this.gameObject);
//生成相关特效本作业暂不做,暂时注释
//CreateEffects();
}
}
//子弹移动方法
private void BulletMoveFF()
{
this.transform.position = Vector3.MoveTowards(this.transform.position, targetPoint,moveSpeed * Time.deltaTime);
}
//创建相关特效,本作业不创建特效
//根据目标点物体的标签生成相关特效(计算目标点时,根据射线判断的方法获取碰撞点的标签--> string taginfo = hit.collider.tag;)
//知识点:--重点
//通过公开变量的游戏对象可以拖拽资源到脚本中:如 public GameObject GameObj;
//但是一个两个还可以拖拽,如果资源多达几十个,那就显得臃肿麻烦了,故可以使用代码读取资源,如下
/// <summary>
/// 创建特效方法,本作业不创建特效,故不调用
/// </summary>
private void CreateEffects()
{
if (hit.collider == null) return; //如果没有检测到物体,则直接返回,不生成特效
//通过Resources读取资源名称
//前提条件,资源必须放在Resources目录下,没有则需要创建
//"目录/资源名称"写法:Bullet/fly
//给之后提供思路,可以将环境物体都打上标签,特效命名的时候加上标签名称,这样之后就可以根据所需标签调用想用的特效了
//注意Resources.Load非常消耗资源,建议以后使用对象池替代!!
//string EffectsTag = hit.collider.tag; //获取射线检测到的物体返回的标签信息
//根据射线检测到的物体返回的标签信息找到相应的特效
//GameObject EffectsObj = Resources.Load<GameObject>("Resources/"+ hit.collider.tag);
GameObject EffectsObj = Resources.Load<GameObject>("Resources目录下的目录/资源名称");
//如果没有找到特效,则直接返回,不生成特效
if (EffectsObj == null) return;
//创建Resources读取到的资源(GameObject)
//Instantiate(生成特效对象,创建位置,旋转角度)
//注意,这样创建出来的特效不会旋转,创建出来的位置要根据法线创建,看下方
//Instantiate(EffectsObj, targetPoint,Quaternion.identity);
//特效创建出来的位置要向法线的方向移动0.01米(防止特效卡在接触面后面造成看不到特效,实际情况需要微调)
//旋转的角度是Z轴朝向法线方向--重点!!
//什么是法线?法线是 垂直 于射线接触面的方向--重点!!
Instantiate(EffectsObj, targetPoint + hit.normal * 0.01f, Quaternion.LookRotation(hit.normal));
}
}
|