Unity制作SpaceShooter游戏

来源:互联网 发布:苹果6数据流量怎么开 编辑:程序博客网 时间:2024/05/20 04:15

在脚本里声明一个public的GameObject,只能从Project栏里将Object拖入Inspector中。
各种变量只能声明在类中各方法外。
在unity窗口上方的标题栏里依次显示场景名-项目名-发布平台,当场景未保存时场景名显示为untitled,场景只能保存在Asset文件夹下,一般建议在其中新建一个_scenes文件夹。
在Edit->Project Settings->Player的Resolution中设定Game视窗的宽高。然后不要忘了选择我们设置好的宽高!
设置Game视窗大小
MeshFilter获取我们的模型,MeshRenderer将其在场景中渲染。
在Camera的Inspector里设置背景。Skybox(天空盒)或SolidColor(单色背景板)。
这里写图片描述
保留原图大小和比例:因为Unity默认将导入的图片按照2的N次方的比例进行压缩,因此要想保留原尺寸,需要设定Type为EditGUI。
保留原图的色彩:设定Shader为Unlit->Texture。
控制飞船移动的代码(注意这里让飞船匀速移动,这与前面用力控制小球的移动是不同的)(PlayerShip):

public float speed;/**因为public这个选项可以在player的Inspector中输入*/void FixedUpdate()/**与物理相关的代码写在这个方法里*/{    float moveHorizontal = Input.GetAxis("Horizontal");/**水平方向的移动输入,左右*/    float moveVertical = Input.GetAxis("Vertical");/**垂直方向上的移动输入,前后*/    Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);/**movement中存放了各方向上移动的数据*/    Rigidbody rigidbody = GetComponent<Rigidbody>();    rigidbody.velocity = movement*speed;}

限制飞船移动范围(PlayerShip):

rigidbody.position = new Vector3(Mathf.Clamp(rigidbody.position.x,(float)-2.5,(float)2.5),0.0f, Mathf.Clamp(rigidbody.position.z, (float)-1.7, (float)5.7));

添加激光弹Object:创建一个Quad作为载体,将Material(材质)和Texture(纹理)拖入其中,将Shader设为Additive即可消去Quad中黑色部分同时将激光弹highlight。
让子弹向前移动的代码(AFX):

public float speed;void Start(){    Vector3 movement = new Vector3(0.0f, 0.0f, speed);    Rigidbody rigidbody;    rigidbody = GetComponent<Rigidbody>();    rigidbody.velocity =movement;}

各个子Object的Transform都是相对于父Object的相对值!
这里写图片描述
实现按下空格发射子弹的代码(PlayerShip):

public GameObject shoot;public Transform shootSpawn;private GameObject newProjectile;void Shoot(){    if (Input.GetKey(KeyCode.Space) )    {        newProjectile = Instantiate(shoot, shootSpawn.transform.position, shootSpawn.transform.rotation) as GameObject;/**用shootspawn的position和rotation实例化shoot,一个as GameObject意为实例化一个shoot*/    }}private void Start(){    InvokeRepeating("Shoot", 0.0F, 0.1F);/**(要调用的方法,开始时间,每隔多久调用)*/}

设置游戏边界(利用Plane的Collider),删除触发边界的Object(Edge):

void OnTriggerEnter(Collider other){    Destroy(other.gameObject);/**删除碰撞到的object*/}

在Planet撞击playerShip时制造爆炸效果并将player和自己删除(同时实现飞船的复活):
Planet(Planet):

public GameObject BoomLight;public Transform Boom;private GameObject newProjectile1;public GameObject planet;public GameObject reborn;public GameObject player;private GameObject newProjectile2;IEnumerator MyMethod()/**要想实现停留若干秒,必须写这样一个方法,再通过协程调用这个方法完成停留若干秒后执行某操作*/{    Debug.Log("Before Waiting 1 seconds");    newProjectile1 = Instantiate(BoomLight, Boom.transform.position, Boom.transform.rotation) as GameObject;    yield return new WaitForSeconds(1F);    Debug.Log("After Waiting 1 Seconds");    Destroy(newProjectile1);/**注意参数不是BoomLight*/}void OnTriggerEnter(Collider other){    if (other.gameObject.tag == "Player")    {        StartCoroutine(MyMethod());/**协程调用而非普通调用*/        Destroy(other.gameObject);        Destroy(planet);/**删除自己*/        newProjectile2 = Instantiate(player, reborn.transform.position, reborn.transform.rotation) as GameObject;    }}// Update is called once per framevoid Update () {    transform.Rotate(new Vector3(15, 30, 45) * Time.deltaTime);}

子弹(AFX)(在子弹击中planet后制造爆炸效果并将自己和planet删除):

public GameObject BoomLight;/**要创建的实例*/public Transform Boom;/**参照物挂靠在子弹上*/public GameObject Afx;private GameObject newProjectile;IEnumerator MyMethod()/**要想实现停留若干秒,必须写这样一个方法,再通过协程调用这个方法完成停留若干秒后执行某操作*/{    Debug.Log("Before Waiting 1 seconds");           newProjectile = Instantiate(BoomLight, Boom.transform.position, Boom.transform.rotation) as GameObject;            yield return new WaitForSeconds(1F);    Debug.Log("After Waiting 1 Seconds");    Destroy(newProjectile);/**注意参数不是BoomLight*/    Destroy(Afx);/**删除自己*/}void OnTriggerEnter(Collider other){    if (other.gameObject.tag == "Enemy")    {        StartCoroutine(MyMethod());/**协程调用而非普通调用*/        Destroy(other.gameObject);               }}

生成Planet波(GameContoller):

public GameObject hazard1;public GameObject hazard2;public GameObject hazard3;public Vector3 spawnValues;public int hazardCount;public float spawnWait;public float startWait;void Start () {    StartCoroutine (SpawnWaves());/**协程调用*/}// Update is called once per frameIEnumerator SpawnWaves () {/**函数要成为协同程序,必须返回IEnumerator,且在调用时要协程调用*/    yield return new WaitForSeconds(startWait);/**暂停代码而不暂停游戏,这个方法只有在协同程序中可用*/    for (int i = 0; i < hazardCount; i++)    {        //创建三个位置使得一个循环里的Planet不在同一处生成        Vector3 spawnPosition1 = new Vector3(UnityEngine.Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);        Vector3 spawnPosition2 = new Vector3(UnityEngine.Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);        Vector3 spawnPosition3 = new Vector3(UnityEngine.Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);        Quaternion spawnRotation = Quaternion.identity;        Instantiate(hazard1, spawnPosition1, spawnRotation);/**实例化hazard1*/        yield return new WaitForSeconds(0.5F);/**实例化不同Planet间隔一段时间,这样它们就不可能重叠了*/        Instantiate(hazard2, spawnPosition2, spawnRotation);/**实例化hazard1*/        yield return new WaitForSeconds(0.5F);        Instantiate(hazard3, spawnPosition3, spawnRotation);/**实例化hazard1*/        yield return new WaitForSeconds(spawnWait);    }}

给爆炸、发射子弹添加音效:
在explosion里添加AudioSource组件,将对应音效拖入Clip项;AFX也如此。这样一来在生成这些Object的同时就会播放音效,Object删除,音效随之消失。
制作计分器:
新建一个3DText,在其脚本(text)中写:

public static int count;/**一定要声明为静态域,所有text类实例都将共用一个count*/void Start() {    count = 0;/**初始化,不能放在AFX里!*/    GetComponent<TextMesh>().text = "Count:"+count;/**在脚本中控制3Dtext的输出*/}public void Add(){    count = count + 10;}IEnumerator MyMethod(){    Debug.Log("Before Waiting 2 seconds");    GetComponent<TextMesh>().text = "Win!";/**在停留2s前执行的操作*/    yield return new WaitForSeconds(2);    Debug.Log("After Waiting 2 Seconds");    Application.Quit();/**在停留2s后执行的操作*/}// Update is called once per framevoid Update () {    if (count>150)    {        StartCoroutine(MyMethod());/**又忘了协程调用*/    }    else    {        GetComponent<TextMesh>().text = "Count:" + count;    }                    }

然后要通过AFX的脚本实时改变count变量的值:

public text Text;/**直接用想要改变脚本所从属的类名来创建实例,通过这个实例调用其中方法*/void OnTriggerEnter(Collider other){    if (other.gameObject.tag == "Enemy")    {                StartCoroutine(MyMethod());/**协程调用而非普通调用*/        Destroy(other.gameObject);        Text.Add();/**只能通过调用另一个脚本的方法来改变其中的变量*/    }}