首页 > 代码库 > 【跟我一起学Unity3D】做一个2D的90坦克大战之导演以及道具系统

【跟我一起学Unity3D】做一个2D的90坦克大战之导演以及道具系统

做游戏我还是习惯用一个导演类来控制游戏的进程,比如游戏的开始和结束,游戏的AI的产生,游戏的地图的绘制等等都放置在这么一个导演类里面。然后这个导演类我把它放在MainCamera里面,作为它的组件。

首先在Start里面,需要初始化一些游戏的数据,例如读取地图,初始化AI等

    void Start()
    {
		//初始化数据
        m_iAICurTankCount = 0;
        m_iAITankCount = 1;
        m_iKillAICount = 0;
        m_iDirection = 0;
        m_iMyLife = 3;
        m_bIsLose = false;
        m_vInstPosition = new Vector3(0, 4.2f, 1);
		
		//读取地图
        m_sXmlPath = Application.dataPath + "/Map/map_1.xml";

        //read map from xml
        ReadFromXml();
        m_gMyTank.GetComponent<CMyTank>().m_fMoveSpeed = m_iMyMoveSpeed;

		//创建AI
        while (m_iAICurTankCount < m_iAITankCount)
        {
            StartCoroutine(CreateAI(1.0f));
        }

        //每隔30秒开放置一次道具
        InvokeRepeating("CreateProp", 15, 30);
    }

这里的重点就是StartCoroutine函数 ,这个函数是用于开始一段协同程序,什么是协同程序呢,在我的理解下,协同程序就是这一段函数是立即执行的,不会阻塞线程,但是,如果这一段函数中有yield关键字的话,yield下面的函数将会在保证yield这句语句执行结束后才能继续执行。下面是例子,也是CreateAI这个函数的实现:

    IEnumerator CreateAI(float waitTime)
    {
        Vector3 temp_position = m_vInstPosition + RandDirection();
        GameObject CreateAIAnimation = Instantiate(m_CreateAIAnimation, temp_position, Quaternion.identity) as GameObject;
        Destroy(CreateAIAnimation, waitTime);

        ++m_iAICurTankCount;

        yield return new WaitForSeconds(waitTime);
		
<span style="white-space:pre">	</span>//start:这一段语句将在延迟waitTime秒后执行
        GameObject temp_AI = Instantiate(m_gAITank, temp_position, Quaternion.identity) as GameObject;
        temp_AI.GetComponent<CAITank>().m_fMoveSpeed = m_iAIMoveSpeed;
	//end:这一段语句将在延迟waitTime秒后执行
    }
AI产生的初始位置是伪随机的,在地图最上方的三个地方轮流产生AI,其中的RandDirection函数的实现如下:
    // 随机生成一个方向
    Vector3 RandDirection()
    {
        m_iDirection = ++m_iDirection % 3;
        Vector3 vec = Vector3.left * 0;
        switch (m_iDirection)
        {
            case 0:
                vec = Vector3.right * 4.2f;
                break;
            case 1:
                vec = Vector3.left * 4.2f;
                break;
            case 2:
                vec = Vector3.left * 0;
                break;
        }
        return vec;
    }
然后是创建道具,创建道具的方法与前面的发射子弹是一样的,开始后15秒创建第一个道具,后面每隔30秒创建后面的道具。而创建道具的函数CreateProp的具体实现如下:

    void CreateProp()
    {
        GameObject Temp = Instantiate(m_gProp, RandPosition(), Quaternion.identity) as GameObject;
        Destroy(Temp, 20.0f);
    }
功能就是随机生成一个道具,道具的位置是在地图上随机的,道具会在生成后20秒自动消除,在地图上随机的函数RandPosition的实现如下:

    Vector3 RandPosition()
    {
        int temp_x = UnityEngine.Random.Range(-7, 7);
        int temp_y = UnityEngine.Random.Range(-7, 7);
        return new Vector3(temp_x * 0.6f, temp_y * 0.6f, -2.0f);
    }

整个地图的大小是 8.4x8.4 然后每个格子是0.6,地图的中心就是坐标的原点,为什么要Z轴设定为-2.0f呢,是因为这样可以保证道具永远漂浮在地图上面(草丛的Z轴是-1.0f)。

道具我只做了一个道具,就是炸弹,得到道具之后,所有AI会爆炸。这个道具的实现我单独做了一个脚本,具体实现如下:

using UnityEngine;
using System.Collections;

public class CProp : MonoBehaviour {

	void Start () {
	
	}
	
	void Update () {
	
	}

    void OnCollisionEnter2D(Collision2D coll)
    {
        Debug.Log(" OnCollisionEnter2D : " + coll.gameObject.name);
        //玩家吃到了道具
        if(coll.gameObject.name == "MyTank")
        {
            Destroy(this.gameObject);
            GameObject[] ais = GameObject.FindGameObjectsWithTag("AITank");
            foreach(GameObject ai in ais)
            {
                Destroy(ai);
                Camera.main.GetComponent<CCamera>().Boom();
            }
        }
    }
}

以后可以在道具上增加属性。


读取地图这一块已经在上上篇博客中讲过了,就不说了。

【跟我一起学Unity3D】做一个2D的90坦克大战之导演以及道具系统