这是一个简单的太空大战DEMO,整个游戏两个部分,开始游戏界面跟游戏主界面,敌人分为两种,一种是简单的敌人,只会去触碰主角,还有一种是复杂点的敌人,可以发射子弹,,OK,下面我们一步步来。
首页我们导入相关的资源,在Assets里单击弹出选择框,选择Import Package->Custom Package,如下图:
接下来,我们要创建一个开始游戏场景,点击菜单栏中的File->New Scene来创建一个新场景,我们命名为start,如下图:
开始场景很简单,它包含一个标题,一个开始游戏按钮,一张背景图,我们先点击菜单栏,GameObject->Create Other->GUI Texture,创建一个背景图,如下图:
我们命名为GameBg,并在Texture里选择mars.png为背景图,如下图:
OK,接下来,我们在代码里创建标题,按钮,我们创建一个CS脚本,命名为TitleScreen,代码如下图:
[csharp]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");
}
}
}
这样,我们就创建了一个标题,跟一个按钮,并且点击按钮的时候,我们会跳转到下一个场景,我们把脚本挂到摄像机上,效果如下图:
接下来我们创建第二个场景,步骤跟上面新建第一个场景一样,我们命名为 Level1,我们新建一个Plane,作为火星的模型,如下图:
命名为XqPlane,然后我们新建一个材质,命名为Background,如下图:
选择mars.png作为贴图,将shader属性设置为Transparent->Cutout->Diffuse,来去掉星球四周的黑框,材质属性如下图:
然后我们为火星模型指定材质,如下图:
同样,我们创建一个星空的模型,跟前面创建星球一样,我们命名为XkPlane,材质属性,贴图,如下图:
运行,我们看下效果图:
现在星空是不动的,我们想让它上下移动,所以接下来,我们创建动画,我们点击菜单栏Window->Animation,打开动画选项,
然后在Animation选项里点击Add Curve创建一个新动画,并命名为XkAnimation,如下图:
然后我们点击Mesh Renderer->Material._Main Tex_ST选项,如下图:
然后我们在Material._Main Tex_ST.w里将值从0到-1,到30帧的时候,改为-1,并设置循环,如下图:
运行发现,星空背景在往下移动,接下来,我们调整摄像机位置,使其向下对准星球,然后我们创建一个点光源,来照亮星球,,如下图:
然后我们设置光源的位置,范围等属性,属性如下图:
接下来,我们就要创建主角啦。。。。我们的主角是一艘太空飞船,我们可以通过方向键来控制飞船移动,我们将Player.fbx直接拖到Hierarchy中,然后将Y轴坐标为0,并且旋转180°,使其头朝上,如下图:
[csharp]
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));
}
}
这样我们就可以移动飞船了,接下来,我们要使飞船能发射子弹,所以我们要创建子弹模型,在资源中找到rocket.fbx模型文件,拖到Hierarchy中,这样就创建了子弹的游戏体,当然对于重复使用的游戏体,我们要做成预设体Prefab,我们打开菜单栏Assets->Create->Prefab,来创建一个新的预设体,如下图:
我们命名为Rocket,
[csharp] view plaincopy
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上,然后我们再修改Player脚本,当我们按下空格或是鼠标左键的时候,就发射子弹,代码如下:
[csharp] view plaincopy
// if(Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0))
// {
//
//
//
// Instantiate(m_rocket,m_transform.position,m_transform.rotation);
//
//
// }
这样飞船就可以发射子弹了,但现在发射子弹的频率太快,所以我们定义一个变量来控制频率,每隔0.1秒发射一次,代码如下:
[csharp] view plaincopy
if(m_rocketRate<=0)
{
m_rocketRate=0.1f;
// if(Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0))
// {
//
//
//
// Instantiate(m_rocket,m_transform.position,m_transform.rotation);
//
//
// }
}
效果如下:
接下来我们创建简单的敌人,不能发射子弹,只能左右旋转沿弧线前进,跟前面创建子弹一样,我们找到Enemy.fbx文件拖到Hierarchy中,然后创建敌人Prefab,并命名为Enemy,如下图:
[csharp] view plaincopy
sing 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));
}
}
这里我们每隔3秒改变敌人一次旋转方向,我们把脚本挂到敌人prefab上,运行如下图:
不过现在飞船发射子弹也打不到敌人,飞船跟敌人之间也没任何交互,这里没有任何碰撞检测,所以接下来,我们添加物理碰撞,我们先给敌人添加碰撞体跟刚体,所有需要参与物理计算的游戏体都需要有一个刚体组件才能正常工作,
然后box Collider属性中,我们选中Is Trigger,使其具有触发作用,在rigidbody组件中,取消选中Use Gravity去掉重力影响,然后选中Is Kinematic使游戏体的运动不受物理模拟影响,如下图:
然后参考前面的方法给主角飞船跟子弹都添加物理组件,
最后,为了区别到这些组件,我们给它们设置Tag标示,选择Edit->Project Settings->Tag and Layers,
我们设置如下tag,
[csharp] view plaincopy
/ /生命
public float m_life = 10;
然后添加一个OnTriggerEnter函数,在碰撞体相互接触时会被触发,
[csharp] view plaincopy
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(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函数,如果子弹撞到敌人,销毁自身
[csharp] view plaincopy
void OnTriggerEnter(Collider other)
{
if (other.tag.CompareTo ("Enemy") == 0) {
Destroy (this.gameObject);
} else
{
return;
}
}
最好修改Player.cs,添加一个生命属性,然后也添加一个OnTriggerEnter函数,主角飞船与任何已方子弹以外的碰撞体相撞都会损失一点生命,生命为0时销毁自身,
[csharp] view plaincopy
//生命
public float m_life=3;
[csharp] view plaincopy
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);
}
}
}
运行,如下:
最后,我们判断下出界,当敌人出界时,就销毁自身,同上面一样,创建一个空的游戏体,命名为bound,添加一个bound的tag,和相关物理组件,
属性如下:
[csharp] view plaincopy
else if (other.tag.CompareTo ("bound") == 0)
{
m_life=0;
Destroy(this.gameObject);
Debug.Log("---destroy");
}