unity3d应用实例之太空大战

2015年01月18日 14:18 0 点赞 0 评论 更新于 2017-05-09 17:48

今天为大家详细介绍Unity3D应用实例——太空大战。这是我找到的一篇相关文章,感兴趣的朋友也可以自己动手尝试制作。

这是一个简单的太空大战DEMO,整个游戏包含两个部分:开始游戏界面和游戏主界面。游戏中的敌人分为两种,一种是简单敌人,只会触碰主角;另一种是复杂敌人,能够发射子弹。下面我们将逐步进行开发。

1. 导入相关资源

首先,我们需要导入相关资源。在Unity的Assets中单击弹出选择框,选择Import Package -> Custom Package

2. 创建开始游戏场景

2.1 创建新场景

点击菜单栏中的File -> New Scene来创建一个新场景,并将其命名为start

2.2 创建背景图

开始场景较为简单,包含一个标题、一个开始游戏按钮和一张背景图。我们先点击菜单栏的GameObject -> Create Other -> GUI Texture来创建背景图,将其命名为GameBg,并在Texture里选择mars.png作为背景图。

2.3 创建标题和按钮

接下来,我们在代码里创建标题和按钮。创建一个CS脚本,命名为TitleScreen,代码如下:

using UnityEngine;
using System.Collections;

[AddComponentMenu("MyGame/TitleScreen")]
public class TitleScreen : MonoBehaviour {
// Use this for initialization
void Start ()
{
}

// Update is called once per frame
void Update () {
}

void OnGUI()
{
GUI.skin.label.fontSize = 80;
GUI.skin.label.alignment = TextAnchor.LowerCenter;
GUI.Label(new Rect(0, 30 * 2, Screen.width, 100), "太空大战");
if(GUI.Button(new Rect(Screen.width * 0.5f - 100 * 2, Screen.height * 0.6f, 200 * 2, 30 * 2), "开始游戏"))
{
// 读取当前关卡
Application.LoadLevel("Level1");
}
}
}

将该脚本挂到摄像机上,点击按钮时会跳转到下一个场景。

3. 创建游戏主场景

3.1 创建新场景

创建第二个场景,步骤与创建第一个场景相同,将其命名为Level1

3.2 创建火星模型

新建一个Plane作为火星的模型,命名为XqPlane。然后新建一个材质,命名为Background,选择mars.png作为贴图,将shader属性设置为Transparent -> Cutout -> Diffuse,以去掉星球四周的黑框,最后为火星模型指定该材质。

3.3 创建星空模型

同样的方法创建一个星空的模型,命名为XkPlane,设置好材质属性和贴图。

3.4 让星空动画移动

目前星空是静止的,我们希望它能上下移动。点击菜单栏Window -> Animation打开动画选项,在Animation选项里点击Add Curve创建一个新动画,命名为XkAnimation。接着点击Mesh Renderer -> Material._Main Tex_ST选项,在Material._Main Tex_ST.w里将值从0到 -1,到30帧的时候改为 -1,并设置循环。运行后,星空背景会往下移动。

3.5 调整摄像机和添加光源

调整摄像机位置,使其向下对准星球,然后创建一个点光源来照亮星球,并设置光源的位置、范围等属性。

4. 创建主角飞船

4.1 导入飞船模型

Player.fbx直接拖到Hierarchy中,将Y轴坐标设为0,并旋转180°,使飞船头朝上。

4.2 编写控制脚本

创建一个CS脚本,命名为Player,代码如下:

public class Player : MonoBehaviour {
public float m_speed = 1;
protected Transform m_transform;

void Start ()
{
m_transform = this.transform;
}

// Update is called once per frame
void Update ()
{
// 纵向移动距离
float movev = 0;
// 横向移动距离
float moveh = 0;

// 向上键
if(Input.GetKey(KeyCode.UpArrow))
{
movev -= m_speed * Time.deltaTime;
}
// 向下键
if(Input.GetKey(KeyCode.DownArrow))
{
movev += m_speed * Time.deltaTime;
}

if(Input.GetKey(KeyCode.LeftArrow))
{
moveh += m_speed * Time.deltaTime;
}
if(Input.GetKey(KeyCode.RightArrow))
{
moveh -= m_speed * Time.deltaTime;
}
this.m_transform.Translate(new Vector3(moveh, 0, movev));
}
}

这样我们就可以通过方向键控制飞船移动了。

5. 让飞船发射子弹

5.1 创建子弹模型

在资源中找到rocket.fbx模型文件,拖到Hierarchy中创建子弹的游戏体。对于重复使用的游戏体,我们要做成预设体Prefab。打开菜单栏Assets -> Create -> Prefab,创建一个新的预设体,命名为Rocket

5.2 编写子弹脚本

创建一个CS脚本,命名为Rocket,代码如下:

using UnityEngine;
using System.Collections;

[AddComponentMenu("MyGame/Rocket")]
public class Rocket : MonoBehaviour {
// 子弹飞行速度
public float m_speed = 10;
// 生存时间
public float m_liveTime = 1;
// 威力
public float m_power = 1.0f;
protected Transform m_transform;

// Use this for initialization
void Start ()
{
m_transform = this.transform;
}

// Update is called once per frame
void Update ()
{
m_liveTime -= Time.deltaTime;
if(m_liveTime <= 0)
{
Destroy(this.gameObject);
}
this.m_transform.Translate(new Vector3(0, 0, -m_speed * Time.deltaTime));
}
}

将子弹脚本挂到子弹Prefab上。

5.3 修改Player脚本实现发射功能

修改Player脚本,当按下空格或是鼠标左键时发射子弹,同时为了控制发射频率,定义一个变量,每隔0.1秒发射一次,修改后的代码如下:

// 控制发射频率的变量
private float m_rocketRate = 0;

void Update ()
{
m_rocketRate -= Time.deltaTime;
if(m_rocketRate <= 0)
{
m_rocketRate = 0.1f;
if(Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0))
{
// 这里假设m_rocket是子弹预设体
Instantiate(m_rocket, m_transform.position, m_transform.rotation);
}
}
}

6. 创建简单敌人

6.1 导入敌人模型

找到Enemy.fbx文件拖到Hierarchy中,创建敌人Prefab,命名为Enemy

6.2 编写敌人脚本

创建一个CS脚本,命名为Enemy,代码如下:

using System.Collections;

[AddComponentMenu("MyGame/Enemy")]
public class Enemy : MonoBehaviour {
// 速度
public float m_speed = 1;
// 旋转速度
protected float m_rotspeed = 30;
// 变相间隔时间
protected float m_timer = 1.5f;
// 生命
public float m_life = 10;
protected Transform m_transform;
public int m_point = 10;

// Use this for initialization
void Start ()
{
m_transform = this.transform;
}

// Update is called once per frame
void Update ()
{
UpdateMove ();
}

protected virtual void UpdateMove()
{
m_timer -= Time.deltaTime;
if (m_timer <= 0)
{
m_timer = 3;
m_rotspeed = -m_rotspeed;
}
// 旋转方向
m_transform.Rotate (Vector3.up, m_rotspeed * Time.deltaTime, Space.World);
m_transform.Translate (new Vector3 (0, 0, -m_speed * Time.deltaTime));
}
}

将脚本挂到敌人Prefab上,敌人会每隔3秒改变一次旋转方向。

7. 添加物理碰撞检测

7.1 添加碰撞体和刚体

给敌人、主角飞船和子弹都添加碰撞体和刚体组件。在敌人的box Collider属性中,选中Is Trigger使其具有触发作用;在rigidbody组件中,取消选中Use Gravity去掉重力影响,选中Is Kinematic使游戏体的运动不受物理模拟影响。

7.2 设置Tag标示

选择Edit -> Project Settings -> Tag and Layers,设置相关的Tag,如PlayerRocketPlayerEnemy等。

7.3 修改脚本实现碰撞逻辑

修改Enemy.cs脚本

添加生命属性和OnTriggerEnter函数,当敌人与子弹或主角飞船碰撞时,根据情况减少生命并处理销毁逻辑:

// 生命
public float m_life = 10;
// 假设m_explosionFX是爆炸特效预设体
public GameObject m_explosionFX;

void OnTriggerEnter(Collider other)
{
if (other.tag.CompareTo ("PlayerRocket") == 0)
{
Rocket rocket = other.GetComponent<Rocket> ();
m_life -= rocket.m_power;
if (m_life <= 0) {
// 假设GameManager.Instance.AddScroe是添加分数的方法
GameManager.Instance.AddScroe(m_point);
Instantiate(m_explosionFX, m_transform.position, Quaternion.identity);
Destroy (this.gameObject);
}
}
else if (other.tag.CompareTo ("Player") == 0)
{
m_life = 0;
Instantiate(m_explosionFX, m_transform.position, Quaternion.identity);
Destroy(this.gameObject);
}
}

修改Rocket.cs脚本

添加OnTriggerEnter函数,当子弹撞到敌人时销毁自身:

void OnTriggerEnter(Collider other)
{
if (other.tag.CompareTo ("Enemy") == 0) {
Destroy (this.gameObject);
}
}

修改Player.cs脚本

添加生命属性和OnTriggerEnter函数,主角飞船与任何己方子弹以外的碰撞体相撞都会损失一点生命,生命为0时销毁自身:

// 生命
public float m_life = 3;
// 假设m_explosionFX是爆炸特效预设体
public GameObject m_explosionFX;

void OnTriggerEnter(Collider other)
{
if (other.tag.CompareTo ("PlayerRocket") != 0)
{
m_life -= 1;
if(m_life <= 0)
{
Instantiate(m_explosionFX, m_transform.position, Quaternion.identity);
Destroy(this.gameObject);
}
}
}

8. 处理敌人出界逻辑

创建一个空的游戏体,命名为bound,添加boundtag和相关物理组件。修改Enemy.cs脚本,当敌人与bound碰撞时,销毁自身:

void OnTriggerEnter(Collider other)
{
if (other.tag.CompareTo ("bound") == 0)
{
m_life = 0;
Destroy(this.gameObject);
Debug.Log("---destroy");
}
}

通过以上步骤,我们就完成了一个简单的太空大战DEMO。你可以根据自己的需求进一步扩展和优化该游戏。

作者信息

feifeila

feifeila

共发布了 570 篇文章