【Unity3D游戏开发】—— 太空大战打飞机游戏详解

大家好我是Kaven,今天给大家带来的是一个Unity3D的打飞机的小项目。俗话说“眼看千变,不如手过一边”,学了差不多两星期Unity3D了,是时候找个小项目练练手了。于是就翻出了cocos2d-x的一个例子,模仿着写了一个飞机大战的游戏,虽然有一些功能没有实现,但总体上是完成了。闲话少说,下面开始吧。

由于这个用的是Unity3d自带的原生的2D插件native 2d,所以创建项目时左下角选择2d。

这个小游戏我分了三个场景,菜单场景,游戏场景,结束场景。由于菜单场景与结束场景都比较简单,所以主要就说说游戏主场景。源码在文章结尾处。

1.创建游戏场景

由于创建的是2d项目,则将图片拖入Scene中,该图片自动成为一个精灵,所以将图片信息拖入摆放即可。

下面创建一个GameManager文件,其绑定在摄像机中,主要负责飞机生命,玩家得分,背景播放等的显示功能。而生命,得分的显示需要我们创建GUIText来摆放。

代码如下:

using UnityEngine;
using System.Collections;

public class GameManager : MonoBehaviour {

    //显示控件位置
    private Transform life;
    private Transform score;

    //游戏主角对象
    private GameObject player;

	void Start () {

        //得到显示控件位置
        life = transform.Find("Life");
        score = transform.Find("Score");
        //获取主角飞机对象
        player = GameObject.FindGameObjectWithTag("Player");
	}

	void Update () {
        if (player != null)
        {
            life.guiText.text = "生命:" + player.GetComponent<Player>().max_life.ToString();
            score.guiText.text = "分数:" + player.GetComponent<Player>().grade.ToString();
        }
        if (life.guiText.text == "生命:0")
        {
            //跳转到游戏结束场景
            Application.LoadLevel(2);
        }
	}
}

然后我们来实现背景的滚动。首先创建两个一样的背景图片上下摆放,如下图所示,这里切换到3d模式,更加形象

下面创建用于绑定在背景上的脚本BGControll.cs,代码如下

using UnityEngine;
using System.Collections;

public class BGControll : MonoBehaviour {

    //背景滚动速度
    public float speed = 1.5f;

	void Update () {
        transform.Translate(Vector3.down * Time.deltaTime * speed);
        if (transform.position.y <= -5.6f)
        {
            transform.position = new Vector3(0, 5.7f, 0);
        }

	}
}

然后将脚本绑定在两张背景图上即可。

2.创建主角飞机

主角创建与背景创建基本一样,也是可以用一张2d贴图,就不多说了。主角脚本主要处理移动,发射子弹,处理碰撞等,代码如下:

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {

    //飞机生命值
    public int max_life = 5;
    //子弹飞行速度
    public float m_speed;
    //子弹对象
    public GameObject bullet;
    //子弹发射位置
    private Transform bulletLeft;
    private Transform bulletRight;
    //发射子弹频率
    private float bulletRate = 0;
    private Transform m_transform;

    //声音资源
    private AudioSource audio;
    [HideInInspector]
    //分数
    public int grade = 0;

	//初始化变量
	void Start () {
        bulletLeft = this.transform.Find("bulletL");
        bulletRight = this.transform.Find("bulletR");
        m_transform = this.transform;
        audio = GetComponent<AudioSource>();
	}

	void Update () {
        //上方向键
	    if (Input.GetKey(KeyCode.UpArrow))
	    {
            m_transform.Translate(Vector3.up * Time.deltaTime * m_speed);
	    }
        //左方向键
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            m_transform.Translate(Vector3.left * Time.deltaTime * m_speed);
        }
        //下方向键
        if (Input.GetKey(KeyCode.DownArrow))
        {
            m_transform.Translate(Vector3.up * Time.deltaTime * (-m_speed));
        }
        //右方向键
        if (Input.GetKey(KeyCode.RightArrow))
        {
            m_transform.Translate(Vector3.left * Time.deltaTime * (-m_speed));
        }

        bulletRate -= Time.deltaTime;
        if (bulletRate <= 0)
        {
            bulletRate = 0.1f;
            //按下空格键,发射子弹
            if (Input.GetKey(KeyCode.Space))
            {

                Instantiate(bullet, bulletLeft.transform.position, Quaternion.Euler(new Vector3(0, 1, 0)));
                Instantiate(bullet, bulletRight.transform.position, Quaternion.identity);
                //播放射击声音
                audio.Play();
            }
        }

        check();
	}

    //检测边界,使飞机不飞出摄像机
    void check()
    {
        if (m_transform.position.x <= -1.3f)
        {
            m_transform.position = new Vector3(-1.3f, m_transform.position.y, 0);
        }
        if (m_transform.position.x >= 1.3f)
        {
            m_transform.position = new Vector3(1.3f, m_transform.position.y, 0);
        }
        if (m_transform.position.y >= 2.5f)
        {
            m_transform.position = new Vector3(m_transform.position.x, 2.5f, 0);
        }
        if (m_transform.position.y <= -2.5f)
        {
            m_transform.position = new Vector3(m_transform.position.x, -2.5f, 0);
        }
    }

    //碰撞时调用该方法,飞机减血
    public void Hit(int Value)
    {
        if (max_life > 0)
        {
            max_life -= Value;
        }
        else
        {
            Destroy(this.gameObject);
            //Application.LoadLevel(2);
        }
    }

    //增加分数
    public void Add(int score)
    {
        grade += score;
    }
}

上面代码中我用了bulletLeft,bulletRight,这是我为主机添加的两个子对象,主要是用于发射子弹,相当于炮筒吧,而bullet则是定义的预设,其中绑定的脚本后面会说明。

下面是Bullet子弹预设绑定的脚本代码,子弹主要功能为与敌人发生碰撞,主角得分,敌人减血。

using UnityEngine;
using System.Collections;

public class Bullet : MonoBehaviour {

    //子弹的速度
    public float m_speed = 2f;
    //子弹存在时间
    public float lifeTime = 20f;
    //子弹碰撞到敌人伤害
    public int power = 2;
    //玩家飞机
    private GameObject player;

	void Start () {
        //根据Tag找到玩家飞机对象
	    player = GameObject.FindGameObjectWithTag("Player");
	}

	void Update () {
        //移动子弹
        transform.Translate(Vector3.up * Time.deltaTime * m_speed);
	}

    void OnTriggerEnter2D(Collider2D mCollider)
    {
        //如果碰撞的是敌人
        if (mCollider.gameObject.tag == "Enemy")
        {
            //敌人减血
            mCollider.gameObject.GetComponent<Enemy>().Hit(power);
            //得分
            player.GetComponent<Player>().Add(100);
            //销毁子弹
            Destroy(this.gameObject);
        }
    }

    //当离开摄像机范围时触发销毁事件
    void OnBecameInvisible()
    {
        Destroy(this.gameObject);
    }
}

期间犯了个非常2的错误就是将OnTriggerEnter2D写成了OnTriggerEnter导致一直没有碰撞,我竟然忘记我建的是2d项目了,函数名改了也不知道,查了些资料终于解决了,不仔细啊。

好了,通过以上的代码我们就可以按键盘的方向键移动飞机,按空格键发射子弹了,我已经等不及要打敌人了。

3.创建敌机

敌机也是先拖入敌机图片,然后绑定脚本,添加组件,然后保存为预设,我们以后还有个敌机生产器要生产敌机呢。

我创建了三种敌机预设

敌机主要是移动,碰撞。下面来看看敌机脚本:

using UnityEngine;
using System.Collections;

public class Enemy : MonoBehaviour {

    //敌机移动速度
    public float m_speed = 3;
    //生命值
    public int max_life = 5;
    //得到爆炸动画
    private Animator animator;

    //爆炸声音
    private AudioSource audio;

	void Start () {
        animator = GetComponent<Animator>();
        audio = GetComponent<AudioSource>();
	}

	void Update () {
        transform.Translate(Vector3.down * Time.deltaTime * m_speed);
	}

    void OnTriggerEnter2D(Collider2D mCollider)
    {
        //敌机与主机碰撞双方掉血
        if (mCollider.gameObject.tag == "Player")
        {
            //敌机掉血
            this.Hit(1);
            //主机掉血
            mCollider.gameObject.GetComponent<Player>().Hit(1);
        }
    }

    //减血
    public void Hit(int value)
    {
        //如果生命值大于0
        if (max_life > 0)
        {
            //生命值降低
            max_life -= value;
        }
        //如果等于0,则播放动画
        else
        {
            audio.Play();
            animator.SetBool("isLive", false);
            AnimatorStateInfo animatorState = animator.GetCurrentAnimatorStateInfo(0);
            //销毁敌机
            if (animatorState.IsName("Base Layer.explosion"))
            {
                Destroy(this.gameObject);
            }
        }
    }

    //离开摄像机视野时销毁对象
    void OnBecameInvisible()
    {
        Destroy(this.gameObject);
    }
}

上面使用到了一个动画,就是敌机爆炸时的动画。那么如何创建动画呢?首先资源中可以拖动一组连续的爆炸图片到场景中,系统会自动提醒创建动画,命名为explosion即可。然后Project视图中就出现了一个animation和一个animator。在菜单栏找到Windows -> Animation和 Winodws -> Animator可以打开如下窗口。

具体的动画编辑可以看看雨松MOMO的关于动画的文章.

下面是敌机生产器,在主界面的左右两边的顶部分别放上两个空物体用来创建敌机。敌机创建时间为1~3秒不等,然后绑定创建脚本即可。

using UnityEngine;
using System.Collections;

public class SpawnEnemy : MonoBehaviour {

    //生成敌人速度
    public float spawnTime = 1.0f;
    //敌人对象数组
    public GameObject[] enemys;

	void Start () {
        StartCoroutine("spawn");
	}

    void Update()
    {
        //生成敌人速度在1~3秒之间变化
        spawnTime = Random.Range(1.0f, 3.0f);
    }

    IEnumerator spawn()
    {
        //等待
        yield return new WaitForSeconds(spawnTime);
        //克隆对象
        Instantiate(enemys[Random.Range(0, 3)], new Vector3(transform.position.x * Random.Range(-1.2f, 1.2f), transform.position.y, 0), Quaternion.Euler(0, 0, 0));
        StartCoroutine("spawn");
    }
}

4.关于碰撞检测

子弹:

    void OnTriggerEnter2D(Collider2D mCollider)
    {
        //如果碰撞的是敌人
        if (mCollider.gameObject.tag == "Enemy")
        {
            //敌人减血
            mCollider.gameObject.GetComponent<Enemy>().Hit(power);
            //得分
            player.GetComponent<Player>().Add(100);
            //销毁子弹
            Destroy(this.gameObject);
        }
    }

敌机:

    void OnTriggerEnter2D(Collider2D mCollider)
    {
        //敌机与主机碰撞双方掉血
        if (mCollider.gameObject.tag == "Player")
        {
            //敌机掉血
            this.Hit(1);
            //主机掉血
            mCollider.gameObject.GetComponent<Player>().Hit(1);
        }
    }

碰撞检测需要添加2d刚体组件和2d碰撞器组件,在Physics 2D中,不要选错了。关于碰撞检测的比较可以看看我的这篇文章【Unity3D游戏开发】—— 碰撞检测

最后就运行一下感受一下打飞机的快感吧(遮面)

  

基本上这个一个小游戏也就完成了,关于其他的一些功能可以随便加嘛,多几个关卡就多创建几个场景,还能加上BOSS战什么的。

由于无法导出我就打包了,源代码:https://github.com/GeeKaven/MoonPlane

最后说下我的想法吧, 今天早上一大早起来就去图书馆了,然后就坐在电脑前一直做到下午晚饭时才搞定。虽然这对于一个大牛来说不难,可能一会儿就解决了。但对于我一个新手还是蛮有挑战性的(哈哈)。有些事是不做永远不知道难度有多大,有些事是做了才会明白会有这么多的问题,还有些事是做了会觉得也不过如此嘛,总之一点理论的基础上多实践,熟能生巧慢慢的也就会了。

最后附上一句话共勉:

             每一个成功者都是一位苦行僧,只有他们自己才知道,通往成功的道路上,到底有多少寂寞与不解。

文章作者:wxk_bigkang(Kaven)

转帖注明:http://blog.csdn.net/wxk_bigworld/article/details/25565325

【Unity3D游戏开发】—— 太空大战打飞机游戏详解

时间: 2024-10-05 02:34:30

【Unity3D游戏开发】—— 太空大战打飞机游戏详解的相关文章

最大的幻术-游戏开发-到底是先学游戏引擎还是先学游戏编程

学习游戏的目的 我们学习游戏制作,游戏开发,游戏编程,游戏XX,我们的目的只有一个,打造一个非常牛逼,非常屌,非常让人开心的虚拟体验.我们用自己的学识让玩家在虚拟世界征战,生活,一步一步的让玩家幸福!那么我们的目的只有一个,让玩家知道自己的幸福在哪里,并且学会追求自己的幸福.当然,每个人对幸福的定义不一样.那么,我们只好让玩家来体验我们所来表达的最通俗的,最普遍的幸福体验,然后慢慢引导玩家去寻找自己的幸福体验.可能,在最后玩家都会离开游戏,离开虚拟世界,(对,这是真的,玩家需要一步一步达到定点,

6、Cocos2dx 3.0游戏开发找小三之游戏的基本概念

重开发者的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27689713 郝萌主友情提示: 人是习惯的产物,当你习惯快乐时,记忆里的不愉快就消失了. 游戏开始之前 经过之前的学习,我们已经可以开发一个最基本的 Cocos2d-x 游戏了,这个游戏包括一张背景图片和一个退出游戏的按 钮,但是这距离完成一个完整.实用的游戏还很遥远.在这一章节中,我们将首先抛开 Cocos2d,介绍游戏开发的基本概念,然后结合 Co

JavaFX战旗类游戏开发 第三课 创建游戏角色

在上一节课程中,我们学习了在JavaFX中绘制游戏地图.这一节课,我们将会创建我们的游戏角色. 首先,同样的,我们创建一个简单的基类. import javafx.scene.canvas.GraphicsContext; /** * 游戏物体基类 * @author Wing Mei */ public abstract class BaseObject { protected double x, y; protected double width,height; protected bool

iOS开发——UI篇OC篇&amp;SpriteKit详解

SpriteKit详解 SpriteKit,iOS/Mac游戏制作的新纪元 这是我的WWDC2013系列笔记中的一篇,完整的笔记列表请参看这篇总览.本文仅作为个人记录使用,也欢迎在许可协议范围内转载或使用,但是还烦请保留原文链接,谢谢您的理解合作.如果您觉得本站对您能有帮助,您可以使用RSS或邮件方式订阅本站,这样您将能在第一时间获取本站信息. 本文涉及到的WWDC2013 Session有 Session 502 Introduction to Sprite Kit Session 503 D

使用 jQuery Mobile 与 HTML5 开发 Web App —— jQuery Mobile 事件详解

在前文<使用 jQuery Mobile 与 HTML5 开发 Web App —— jQuery Mobile 默认配置与事件基础>中,Kayo 对 jQuery Mobile 事件的基础作出了一些说明,建议在阅读本文前首先阅读前文,这里 Kayo 再引用前文的重要内容. “jQuery Mobile 在基于本地事件上,创建了一系列的自定义事件,大部分事件是基于触摸设备的使用情况开发的,当然这些事件对于桌面环境也会有适当的处理,开发者可以使用 bind() 函数绑定到需要的页面对象中. 值得

Unity3D研究之asset bundle 格式简析详解

Unity3D 的 asset bundle 的格式并没有公开.但为了做更好的差异更新,我们还是希望了解其打包格式.这样可以制作专门的差异比较合并工具,会比直接做二进制差异比较效果好的多.因为可以把 asset bundle 内的数据拆分为独立单元,只对变更的单元做差异比较即可. 网上能查到的资料并不是官方给出的,最为流行的是一个叫做 disunity 的开源工具.它是用 java 编写的,只有源代码,而没有给出格式说明(而后者比代码重要的多).通过阅读 disunity 的代码,我整理出如下记

Web开发典藏大系:Web性能测试实战详解 PDF扫描版

本书主要讲解了大数据背景下的Web性能测试的特点和方法,以及使用业内应用非常广泛的工具――LoadRunner 11进行性能测试的具体技术与技巧.本书理论结合实践,讲解图文并茂,并且将IT技术与生活场景结合起来,生动而又形象. 本书共17章,分为5篇.第1篇介绍软件测试的定义.方法和过程.Web应用开发与测试等内容:第2篇介绍Web应用技术.Web性能测试的基础.Web性能测试的方法和各操作系统性能计数器的获取等内容:第3篇介绍如何使用LoadRunner进行Web应用性能测试,包括LoadRu

Unity3D游戏开发之如何发布Android游戏

怎么在Unity3D游戏开发软件里,发布Android游戏?如果你感到有疑问,不如看看下面笔者的介绍. 新装的软件会自带一个demo,我们的讲解就是拿demo打不一款Android游戏,点击File -> build seting.如果你已经创建好一个场景需要发布,也可以加载进来跟着以下的步骤进行. 我们要发布到Android平台上,所以在这里就需要选择Android平台,再点击player settings.当然这里还需要你对游戏的部署信息进行写修改,值得注意的是:如果你使用的是破解版Unit

unity3d游戏开发之第一人称射击游戏

简介 这个教程中,我们详细了解下如何制作一个简单的第一人称射击游戏(FPS).其中将介绍一些基本的3D游戏编程的概念和一些关于怎样如游戏程序员般思考的技巧. 前提 这个教程假定你已经熟悉软件Unity基本操作,掌握了基本的脚本概念. 创建新工程 下载FPS_Tutorial.zip压缩文件,解压,在Unity中打开工程文件. 从Unity安装目录导入Standard Assets资源包. 导入工程后,你会在Unity工程面板中的"Standard Assets"文件夹下看见这些资源内容