返回首页DA系统C#IDE文件同步服务屏保 今天是: 2026-05-05    "立夏"  夏季的第一个节气,表示盛夏时节的正式开始

搜索
热搜: linux 技术
Hi~登录注册
查看: 2015|回复: 0

[原创] 【原创】英雄无敌子弹模块

[复制链接]
发表于 2022-4-30 23:46:01 | 显示全部楼层 |阅读模式

少侠不来段修仙之旅吗~

您需要 登录 才可以下载或查看,没有帐号?注册成为修仙之旅的少年~

x
//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));
    }
}


 楼主| 发表于 2022-4-30 23:46:34 | 显示全部楼层
//EnemyBullet.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 敌人子弹类,继承自Bullet
/// </summary>
public class EnemyBullet : Bullet
{
    //编译器配置
    //Attack Distance--攻击距离
    //Move Speed--子弹速度
    //Mask--射线检测层(敌人应选择环境检测,如果检测玩家等于追踪锁头了。。。)

    //敌人子弹类,击中玩家后扣血。OnTriggerEnter检测碰撞判断,检测是否与玩家接触
    private void OnTriggerEnter(Collider other)
    {
        //如果与玩家接触,则玩家减血
        if (other.tag=="Player")
        {
            print("调用玩家受伤方法");
            //玩家减血
            PlayerStauts.PubPlayerStatus.PlayerDamage(BulletAtk);

            //击中玩家后销毁子弹,此段应该可以不加,到时注释调试
            Destroy(this.gameObject);
        }
    }
}


回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-4-30 23:48:00 | 显示全部楼层
//PlayerBullet.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 玩家子弹类,继承自Bullet
/// </summary>
public class PlayerBullet : Bullet
{
    //编译器配置
    //Attack Distance--攻击距离
    //Move Speed--子弹速度
    //Mask--射线检测层(玩家应选择环境检测和敌人检测)

    //定义敌人受伤详细数值变量--只有下方使用CountAttak方法才会调用
    private float EnemyAtkNum;

    //玩家子弹类,根据击中敌人部位扣血。
    //根据敌人部位减血。使用switch case
    //如果希望到达物体上在减血,需要使用委托

    private void Start()
    {

        //游戏开始前获取子弹攻击力,注意,只有射线检测到物体才会执行获取攻击力方法--只有下方使用CountAttak方法才会调用
        if (hit.collider != null)
        {
            EnemyAtkNum = CountAttak();
        }


        //判定射线检测是否检测到物体同时标签是否是Enemy标签
        if (hit.collider != null && hit.collider.tag == "Enemy")
        {
            //根据射线检测到敌人后获取敌人组件,调用敌人受伤方法
            print("调用敌人受伤方法");
            hit.collider.GetComponentInParent<EnemyInfo>().EnemyDamage(EnemyAtkNum);
        }

    }


    //计算攻击到的每个部位造成的攻击力-使用switch case
    private float CountAttak()
    {
        //以后建议使用配置文件替代
        switch (hit.collider.name)
        {
            case "Sphere":  //击中敌人1头部
                return BulletAtk * 30;
                break;
            case "Coll_EnemyHead":  //击中敌人2头部
                return BulletAtk * 3;
                break;
            case "Coll_EnemyBody":  //击中敌人2身体
                return BulletAtk * 1.5f;
                break;
            case "TwoZiObj":        //击中敌人3
                return BulletAtk * 1.5f;
                break;
            default:                //击中敌人其他部位,为正常攻击力
                return BulletAtk;
                break;
        }
    }

    //玩家子弹类,击中敌人后扣血。OnTriggerEnter检测碰撞判断,检测是否与玩家接触
    //此方法不同于switch case,是直接作为敌人标签判断
    /*
    private void OnTriggerEnter(Collider other)
    {
        //如果与玩家接触,则玩家减血
        if (other.tag == "Enemy")
        {
            //敌人减血
            other.GetComponentInParent<EnemyInfo>().EnemyDamage(base.BulletAtk);

            //击中敌人后销毁子弹,此段应该可以不加,到时注释调试
            Destroy(this.gameObject);
        }
    }
    */

}


回复 支持 反对

使用道具 举报

游客
回复
*滑块验证:

DA论坛飞机票来了~
快速回复 返回顶部 返回列表