moba类游戏开发日志(七)子弹的创建-移动-攻击-销毁

本来一开始是想给角色做个子弹技能的,但是总觉得我一那斧子的战士创建子弹总不能扔斧头吧,感觉也没有对于的动画来匹配相关状态的跳转,做出来了也会显得很奇怪,所以这边的子弹技能就尝试做了个类塔防箭塔的攻击

对于子弹,首先肯定得整一个子弹抽象类然后自己整一个子弹prefab,我们在他该出现的时候给他实例化便实现了子弹的创建,这个很简单没什么好说的

难点在于如何寻找攻击对象并朝攻击对象移动,在攻击完成后再自行销毁

对于子弹来说,在需求上(箭塔的子弹)我们要求他只要有怪进入其射程,那么我们便会射出一发子弹对monster进行攻击

这么一想,子弹岂不是需要无限的在固定位置去生成?这么一想是不是和之前在固定位置生成monster一样了,我反正是这么想这么整的

给所有子弹的parent传一个stratPosition即可,与此同时我们还可以传进去target的position,但是target的position我们怎么获取呢?

这里又学习了一个新知识,Collider碰撞体

我们可以在对象上加一个碰撞体,具体形状视需求而定,当两个碰撞体发生碰撞时,我们便可以通过 OnTriggerEnter 来获取具体发生碰撞的那个对象的各种信息,如此一来我们便可以得到子弹要攻击的那个对象的位置,之后在update里更新子弹的位置即可,具体攻击触发该设置什么效果这个就看需求了,一般来说我们是对monster进行一个扣血操作,不过我不想在这里细说,等有空在之后的文章里写写吧

如果我们的子弹移动速度很慢,很可能会出现另一种情况,子弹还没有击中怪物怪物便已经离开了箭塔的射程,这显然是不满足我的需求的,如此一来在不改变子弹速度的前提下我们便需要对子弹的一个生存时间进行限制

具体api调用及传值没什么好说的,我觉得一段程序最重要的就是他的设计而不在于他的实现,所以一些操作具体如何实现便不细说了(多半再过几个月回看自己的代码就像看见shit一样……),下面挂个Tower及Bullet的代码

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

public class Tower : MonoBehaviour
{
    public List<GameObject> listSoldier = new List<GameObject>();
    // Start is called before the first frame update
    [SerializeField]
    private GameObject bulletPrefab;
    [SerializeField]
    private Transform bulletStart;

    [SerializeField]
    private Transform parent;

    private Health HP;
    void Start()
    {
        HP = GetComponent<Health>();
        InvokeRepeating("CreatBullet",0.1f,1f);
    }

    public void CreatBullet()
    {
        if(listSoldier.Count == 0)
        {
            return ;
        }
        GameObject bullet = (GameObject) Instantiate(bulletPrefab,bulletStart.position,Quaternion.identity);
        bullet.transform.parent = parent;
        BulletTarget(bullet);
    }


    public void BulletTarget(GameObject bullet)
    {
        if(listSoldier.Count > 0)
        {
            bullet.GetComponent<Bullet>().SetTarget(listSoldier[0]);
        }
    }
    // Update is called once per frame
    void OnTriggerEnter(Collider col) 
    {
        var tag = col.GetComponent<Collider>().tag;

        // Debug.Log("Name is " + name);
        if(tag == "Monster")
        {
            SmartSoldier soldier = col.GetComponent<SmartSoldier>();
        //  print(listSoldier.Count);
            listSoldier.Add(col.gameObject);
        }
    }
    void OnTriggerExit(Collider col) 
    {
        var tag = col.GetComponent<Collider>().tag;

        // Debug.Log("Name is " + name);
        if(tag == "Monster")
        {
            Debug.Log("TriggerExit");
            listSoldier.Remove(col.gameObject);  
        }
          
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullet : MonoBehaviour
{
    private GameObject target;
    public float speed = 20f;

    public Tower tw;
    // Start is called before the first frame update
    void Start()
    {
        tw = GetComponentInParent<Tower>();
        Destroy(this.gameObject, 1f);
    }

    void OnTriggerEnter(Collider col) 
    {
        if(col.tag == "Monster")
        {
            Health M_hp = col.GetComponent<Health>();
            M_hp.TakeDamage(0.1f);
            if(M_hp.hp.Value <= 0 && tw.listSoldier.Count >0)
            {
                tw.listSoldier.Remove(col.gameObject);
                Destroy(col.gameObject);
            }
            Destroy(this.gameObject);
        }
    }
    // Update is called once per frame
    void Update()
    {
        if(target)
        {
            Vector3 dir = target.transform.position - transform.position;
            GetComponent<Rigidbody>().velocity = dir.normalized * speed;
        }
        else
        {
            Destroy(this.gameObject);
        }
    }
    public void SetTarget(GameObject target)
    {
        this.target = target;
    }
}

Bullet中出现了一些之前的文章没提及的东西,比如说Health类,这个在后面的文章会解释的