21.武器和子弹

21.玩家-武器对象和子弹对象


21.1 知识点

查看武器对象和子弹对象类图

创建武器对象脚本,声明必要的对象和开火逻辑

// 武器对象
public class WeaponObj : MonoBehaviour
{
    // 用于实例化的子弹对象
    public GameObject bullet;

    // 外部决定到底有几个发射位置
    public Transform[] shootPos;

    // 武器的拥有者
    public TankBaseObj fatherObj;

    // 设置拥有者
    public void SetFather(TankBaseObj obj)
    {
        fatherObj = obj;
    }

    // 开火逻辑
    public void Fire()
    {
        // 根据位置创建对应个子弹
        for (int i = 0; i < shootPos.Length; i++)
        {
            // 创建子弹预设体
            GameObject obj = Instantiate(bullet, shootPos[i].position, shootPos[i].rotation);
            // 控制子弹做什么
            BulletObj bulletObj = obj.GetComponent<BulletObj>();
            bulletObj.SetFather(fatherObj);
        }
    }
}

在玩家坦克类脚本中,添加武器和调用武器的开火方法

// 当前装备的武器
public WeaponObj nowWeapon;

// 重写父类中的行为,玩家可能会存在特殊处理
public override void Fire()
{
    if (nowWeapon != null)
        nowWeapon.Fire();
}

创建子弹对象脚本和相关变量,让子弹实时移动,把子弹对象脚本添加到子弹预制体上

// 子弹对象
public class BulletObj : MonoBehaviour
{
    // 移动速度
    public float moveSpeed = 50;
    // 谁发射的我
    public TankBaseObj fatherObj;
    // 特效对象
    public GameObject effObj;

    void Update()
    {
        // 相对于自己的面朝向移动
        this.transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
    }
}

给子弹预制体添加刚体和碰撞体,碰撞体做成触发器

给子弹添加碰撞触发检测函数,在触发某些条件的时候销毁子弹生成特效,根据设置看时候播放音效,并且也添加一个设置是谁发射子弹对象方法,在武器中调用,通过武器做中间人间接知道发射子弹的对象是谁

private void OnTriggerEnter(Collider other)
{
    // 判断碰撞到的对象是否需要处理
    if (other.CompareTag("Cube") || 
        (other.CompareTag("Player") && fatherObj.CompareTag("Monster")) || 
        (other.CompareTag("Monster") && fatherObj.CompareTag("Player")))
    {
        // 判断是否受伤
        TankBaseObj obj = other.GetComponent<TankBaseObj>();
        if (obj != null)
            obj.Wound(fatherObj);

        // 创建爆炸特效
        if (effObj != null)
        {
            GameObject eff = Instantiate(effObj, transform.position, transform.rotation);
            AudioSource audioS = eff.GetComponent<AudioSource>();
            audioS.volume = GameDataMgr.Instance.musicData.soundValue;
            audioS.mute = !GameDataMgr.Instance.musicData.isOpenSound;
        }

        Destroy(gameObject);
    }
}

// 设置拥有者
public void SetFather(TankBaseObj obj)
{
    fatherObj = obj;
}

在武器类中,添加开火时设置子弹拥有者的逻辑

//开火逻辑
public void Fire()
{
    //根据位置 创建对应个子弹 即可
    for (int i = 0; i < shootPos.Length; i++)
    {
        //创建子弹预设体
        GameObject obj = Instantiate(bullet, shootPos[i].position, shootPos[i].rotation);
        //控制子弹做什么
        BulletObj bulletObj = obj.GetComponent<BulletObj>();
        bulletObj.SetFather(fatherObj);
    }
}

注意玩家坦克的刚体要勾选锁定旋转和锁定y轴位置,不然会和立方体碰撞产生扭矩力的作用


21.2 知识点代码

WeaponObj

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

//武器对象
public class WeaponObj : MonoBehaviour
{
    //用于实例化的子弹对象
    public GameObject bullet;

    //外部决定到底有几个发射位置
    public Transform[] shootPos;

    //武器的拥有者
    public TankBaseObj fatherObj;
    
    //设置拥有者
    public void SetFather(TankBaseObj obj)
    {
        fatherObj = obj;
    }

    //开火逻辑
    public void Fire()
    {
        //根据位置 创建对应个子弹 即可
        for (int i = 0; i < shootPos.Length; i++)
        {
            //创建子弹预设体
            GameObject obj = Instantiate(bullet, shootPos[i].position, shootPos[i].rotation);
            //控制子弹做什么
            BulletObj bulletObj = obj.GetComponent<BulletObj>();
            bulletObj.SetFather(fatherObj);
        }
    }
}

BulletObj

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

//子弹对象
public class BulletObj : MonoBehaviour
{
    //移动速度
    public float moveSpeed = 50;
    //谁发射的我
    public TankBaseObj fatherObj;

    //特效对象
    public GameObject effObj;

    void Update()
    {
        //相对于自己的面朝向移动 第二个参数不填默认是自己的坐标系
        this.transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
    }

    //和别人碰撞触发时
    private void OnTriggerEnter(Collider other)
    {
        //子弹 设计到立方体 会爆炸 
        //同样 子弹设计到 不同阵营的对象也应该爆炸
        if( other.CompareTag("Cube") ||
            other.CompareTag("Player") && fatherObj.CompareTag("Monster") ||
            other.CompareTag("Monster") && fatherObj.CompareTag("Player"))
        {
            //判断是否受伤
            //得到碰撞到的对象身上 是否有坦克相关脚本 我们用里氏替换原则
            //通过父类去获取
            TankBaseObj obj = other.GetComponent<TankBaseObj>();
            //判断 对象上 是否挂载了 坦克相关脚本 
            if (obj != null)
                obj.Wound(fatherObj);

            //当子弹销毁时 可以创建一个 爆炸特效
            if(effObj != null)
            {
                //创建爆炸特效
                GameObject eff = Instantiate(effObj, this.transform.position, this.transform.rotation);
                //改音效的音量和开启状态
                AudioSource audioS = eff.GetComponent<AudioSource>();
                //设置大小
                audioS.volume = GameDataMgr.Instance.musicData.soundValue;
                //设置是否开启
                audioS.mute = !GameDataMgr.Instance.musicData.isOpenSound;
            }

            Destroy(this.gameObject);
        }
    }

    //设置拥有者
    public void SetFather(TankBaseObj obj)
    {
        fatherObj = obj;
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏