关于Unity的入门游戏飞机大战的开发(下)

2023-04-22,,

开发思路:

1: 修改测试模式,去掉开始按钮方便开发,加入敌机的资源
2: 创建敌机 添加刚体,碰撞器组件,添加帧动画播放组件;
3: 创建敌机出现的队形;
4: 根据队形随机 生成我们的敌机,调整敌机的速度,和敌机出去后,删除;
5: 碰撞配置分组,TAG 标记不同对象, 刚体加上trigger;
6: 玩家被敌人击中,爆炸与恢复;
7: 子弹打死敌人后删除自己,敌人也要做爆炸;
8: 加上玩家得分的情况;
9: 打开menu主页, 做好GUI 适配

步骤一>>>>>>修改测试模式,去掉开始按钮方便开发,加入敌机的资源

1.把menu_root节点隐藏起来,在game_scene脚本里面的Start函数里直接调用on_start_click()函数,这样游戏就不用菜单的开始按钮触发,而是自己触发开始了,比较好调试。

2.在Resources文件夹下面的tex文件夹中,添加进敌机的资源(9种)和敌机爆炸的动画资源文件夹dead

步骤二>>>>>>创建敌机 添加刚体,碰撞器组件,添加帧动画播放组件

1.创建一个叫enemy_root的敌机空节点,作为Canvas节点的子节点。节点大小设置为0。

2.给enemy_root创建一个叫e1的Image子节点,把敌机e1的贴图拖进去,set native size,缩放设置为X为2,Y为2。

3.由于有很多敌机(8种)要添加碰撞形状和物理刚体组件,所以可以手动添加组件,也可以用脚本代码实现组件的添加,比较轻松。

4.创建一个叫enemy的脚本用来对每个敌机添加刚体和碰撞组件,以及对他们进行一些初始化,记得是先写好脚本再挂载到e1到e8下面,不然先挂载再写脚本这里会出错。

using UnityEngine;
using System.Collections;
using System; //用代码添加刚体组件和形状碰撞组件
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(BoxCollider2D))] public class enemy : MonoBehaviour {
public int e_type; // 敌机的类型; private BoxCollider2D box;
private Rigidbody2D body; // Use this for initialization
void Start () { this.body = this.GetComponent<Rigidbody2D>();
this.box = this.GetComponent<BoxCollider2D>();      //设置敌机碰撞器的形状的大小
RectTransform r_trans = (RectTransform) this.transform;
r_trans.localScale = new Vector3(, , );//放大节点两倍
Vector2 size = r_trans.sizeDelta;//取出节点的大小 this.box.size = size;//设置好碰撞器大小
this.box.isTrigger = true; // 只做碰撞触发;只触发不产生碰撞效果
this.body.freezeRotation = true; // 不让他旋转;刚体不旋转
} // Update is called once per frame
void Update () { }
}

5.记得把Rigidbody2D组件的Is Trigger打钩,只做碰撞触发,其实不打钩也没事,在脚本里面有写。

6.给每个敌机创建一个节点,把自己的贴图拖进自己的贴图属性中,set native size,记得填写enemy脚本的公开属性E_type,第几个类型的就填第几编号。

7.由于等下要生成非常多的敌机,所以要把这些敌机设置成预制体,就在prefabs文件夹下面再创建一个叫enemies的文件夹,然后把e1到e8的敌机节点拖进enemies变成蓝色预制体,删除原来的e1到e8节点。

步骤三>>>>>>创建敌机出现的队形

1.开始排飞机的队形,在enemy_root下面创建一个group1的空子节点,然后把prefabs里面的前三个敌机预制体拖进group1,修改三个敌机的坐标位置,排成一排或者其他的。

2.排好之后先把这三台敌机取消预制体形态,还原成普通节点GameObject-->Break Prefab Instance,然后把整个group1拖进prefab文件夹里面当作一个预制体。

3.每次制作好预制体之后,都可以把原来的那个节点删除,这样重复制作组合大概5、6组就可以。

4.最后只剩一个enemy_root空节点,下面什么也没有。

步骤四>>>>>>根据队形随机 生成我们的敌机,调整敌机的速度,和敌机出去后,删除

我们首先是做了敌机的group,这个group下面可能有三驾敌机e1e2e3,每驾敌机都有相对于group相对偏移的位置pos1pos2pos3,接下来把所有的group都从一个很高很高的位置如(0,912,0)开始,当我们产生敌机的时候,把敌机的初始位置设置为(0,912,0)

保证了敌机可以从那个高度开始移动,接下来我们遍历每个group下面的孩子,有几个孩子就产生几个enemy,每个enemy的位置就是912+pos,这样再把新创建的enemy加到enemy_root空节点下面,这样我们就生成了一个group实例。所以我们在enemy_root下其实是不直接生成group实例,因为group里面的每一个enemy位置都是写死的,我们希望里面的每个敌机的位置是随机的。所以我们新产生一个enemy,位置等于grooup的初始位置912+每个敌机相对group的偏移位置pos。

1.有了队形之后就是怎么随机产生这些队形和移动这些队形,以及最后超出屏幕后删除的操作。

2.写一个脚本gen_enemy挂载在enemy_root节点下面实现第一点

3.打开gen_enemy脚本,其实里面对预制体的实例化并不是对group的实例化,而是对一个一个enemy敌机的实例化。

而且产生的飞机的位置也是随机的,队形是一个一个随机的,而且具体哪个位置哪台飞机是随机的。并不是我刚开始以为的对整个group进行实例化。如果那样的话位置和飞机就会对应,不灵活。

记得在enemy_root的Inspector面板里面把对应的属性绑定好,自己手动拖进去。

using UnityEngine;
using System.Collections;
using UnityEngine.UI; public class gen_enemy : MonoBehaviour {
public GameObject[] group_set; // 敌机组的集合
public GameObject[] enemy_set; // 敌机的集合 // Use this for initialization
void Start () {
}
public void start_gen_enemy() {
this.Invoke("gen_one_group", );
}
  void gen_one_group() {
// [0, this.group_set.Length) 随机数,生成一个0到敌机组总数-1的随机数
int group_index = Random.Range(, this.group_set.Length); //设置一个初始位置,敌机组从这里生成并开始移动
Vector3 start_pos = new Vector3(, , ); // 循环遍历group下面的孩子数目;遍历随机到的那一个敌机组,遍历里面的每一个敌机
for (int i = ; i < this.group_set[group_index].transform.childCount; i++) {        //生成一个0到敌机总数-1的随机数,随机取1到8敌机类型的一种类型
       int e_type = Random.Range(, this.enemy_set.Length);        //获得孩子的位置,获得当前指定敌机的位置
Transform group_enemy = this.group_set[group_index].transform.GetChild(i); // 随机的生成了一个敌人,开始随机生成一架敌机
GameObject e_item = GameObject.Instantiate(this.enemy_set[e_type]);
e_item.transform.SetParent(this.transform, false);
Vector3 pos = start_pos + group_enemy.localPosition;
e_item.transform.localPosition = pos;
} // [0.0, 3.0f]
this.Invoke("gen_one_group", + Random.Range(0.0f, 3.0f));
}   // Update is called once per frame
void Update () { }
}

4.在enemy脚本中,由于每一个敌机我们给它一个向下的初速度,这个速度的设置是写在原来的enemy脚本中的Start函数里面

this.body.velocity = new Vector2(0, -8);

还要写实现敌机飞出屏幕后删除的代码,这个和子弹删除的原理是一样的

void Start () {

  ...

  float scale = 640.0f / (float)Screen.width;
  this.dead_line_y = -(Screen.height * scale * 0.5f + 100);

}

void Update () {
  if (this.transform.localPosition.y < this.dead_line_y) {
  MonoBehaviour.Destroy(this.gameObject);
  }
}

5.在game_scene脚本中,为了开始生成敌机队列,首先要在里面的Start函数中获得enemy_root下的脚本

this.gen_enmey_ctrl = this.transform.Find("game_root/enemy_root").GetComponent<gen_enemy>();

然后在game_realy_started函数里面调用gen_enmey脚本里面的start_gen_enemy函数开始生成敌机

this.gen_enmey_ctrl.start_gen_enemy();//记得要在gen_enmey脚本中把start_gen_enemy函数的权限改为public才可以访问

步骤五>>>>>>碰撞配置分组,TAG 标记不同对象, 刚体加上trigger

1.给plane添加碰撞器形状组件,大小设置为飞机的大小128X128,为了准确也可以做一个多边形的Collider,那样就必须使用Polygon Collider 2D组件,然后编辑。

2.把Box Collider 2D的Is Trigger打钩,表示不发生碰撞效果,但是还是有碰撞响应。

3.编辑右上角的层,把游戏内的物体分成3个层,plane,plane_bullet,enemy,给每个节点这里设置plane节点及其子节点和resources/prefabs/enemies里面所以预制体和resources/prefabs/plane_bullet预制体都设置对应的层。

4.对每个层的碰撞情况进行编辑,Edit-->project Settings-->Physics 2D,在Layer Collision Matris碰撞矩阵里面编写打钩碰撞的情况,不打钩的意思是连碰撞响应都不发生。

5.编辑左上角的标记,把游戏内的物体进行标记,这里分成3个标记plane,plane_bullet,enemy,给每个节点和预制体都设置对应的标记,有了标记后面才能知道是谁和谁在碰撞。

步骤六>>>>>>玩家被敌人击中,爆炸与恢复

1.由于plane,plane_bullet,enemy的碰撞类型都是trigger,所以我们要在相应的脚本里面写Trigger的响应函数。

2.我们还需要一个帧动画的组件,在第22的文件里面,里面的frame_anim.cs,把它拷贝到项目的scripts文件夹下面

3.在飞机plane节点下面添加frame_anim.cs组件,因为飞机爆炸有7张图,属性size就写7,并把每一张爆炸图都拖进去。

4.在OnTriggerEnter2D函数里面调用frame_anim.cs的play_once函数,记得把play_once改成public才能调用,而且我们还要改写一下frame_anim.cs的函数play_once,使得它变成一个回调函数,这样爆炸结束的时候还能自动调用别的函数。

改写的frame_anim.cs

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System; // 我们当前代码强制要求要加入一个Image组件,
// 如果没有Image组件,那么自动加上,如果有就使用;
// 如果你的代码要求这个节点必须挂某个组件,那么
// 使用RequireComponent
[RequireComponent(typeof(Image))] public class frame_anim : MonoBehaviour {
// 我们这个动画所需要的画面;
public Sprite[] sprite_frames;
// 帧动画的间隔时间
public float duration = 0.1f;
// 是否循环播放
public bool is_loop = false;
// 是否在加载的时候开始播放;
public bool play_onload = false; private float played_time;
private bool is_playing = false; private Image img;
Action end_func = null;//----补充----加一个结束的动作 // Use this for initialization
void Start () {
this.img = this.GetComponent<Image>();
if (this.play_onload) {
if (this.is_loop) {
this.play_loop();
}
else {
this.play_once(null);//----补充----改写成传递参数的调用
}
}
} // 只播放一次
public void play_once(Action end_func) {//----补充----改写成传递参数的调用
if (this.sprite_frames.Length <= ) {
return;
} this.end_func = end_func;//----补充----赋值 this.played_time = ;
this.is_playing = true;
this.is_loop = false;
} // 循环播放
void play_loop() {
if (this.sprite_frames.Length <= ) {
return;
}
this.played_time = ;
this.is_playing = true;
this.is_loop = true;
}
// 停止当前的动画播放
void stop_anim() {
this.is_playing = false;
}
// Update is called once per frame
void Update () {
if (this.is_playing == false) {
return;
} //
float dt = Time.deltaTime;
this.played_time += dt;
// 向下取整;
int index = (int)(this.played_time / this.duration);
if (this.is_loop == false) {
// 结束了
if (index >= this.sprite_frames.Length) { // 停止播放
this.is_playing = false;
this.played_time = ;
if (this.end_func != null) {//----补充----停止播放的时候执行结束函数
this.end_func();
}
}
else {
this.img.sprite = this.sprite_frames[index];
}
}
else {
// 超过了范围,减掉一个周期
while (index >= this.sprite_frames.Length) {
this.played_time -= (this.duration * this.sprite_frames.Length);
index -= this.sprite_frames.Length;
} this.img.sprite = this.sprite_frames[index];
}
// end
}
}

改写的plane.cs

using UnityEngine;
using System.Collections;
using UnityEngine.UI; //定义两个飞机的状态用来后面判断是否播放爆炸动画
enum State
{
NORMAL = ,
DEADED = ,
}; public class plane : MonoBehaviour
{
//播放帧动画要用的变量
private frame_anim bomb_anim;
public Sprite ship_idle;
private Image ship_icon;
private State state; //碰撞器
private BoxCollider2D box;
//飞机随着鼠标运动需要定义飞机坐标和鼠标坐标
Vector3 start_plane_pos; // 按钮按下的时候飞机的开始的坐标
Vector3 start_mouse_pos; // 鼠标开始的坐标; //子弹预制体
public GameObject bullet_prefab;//预制体子弹节点
public Transform bullet_root;//预制体子弹节点的父节点
public float shoot_rate = 0.2f; // 子弹发射的频率;我感觉是一个时间间隔,设定的子弹发射时间间隔
private float shoot_time = 0.0f; // 距离上一次发射过去的时间
private bool is_shooting = false;//是否处于发射子弹的状态 //-----优化-----
private bool is_touch = false;//是否点到飞机
private bool is_super = false;//是否处于无敌状态 // Use this for initialization
void Start()
{
//帧动画播放初始化
this.bomb_anim = this.transform.Find("anim").GetComponent<frame_anim>();
this.ship_icon = this.bomb_anim.GetComponent<Image>();
this.state = State.NORMAL; //获得碰撞器
this.box = this.GetComponent<BoxCollider2D>();
} public void start_game()
{
this.is_shooting = true; } void shoot_bullet()
{
//使用预制体生成一颗子弹
GameObject bullet = GameObject.Instantiate(this.bullet_prefab);
// 注意这个参数要使用false
bullet.transform.SetParent(this.bullet_root, false); //使用localPosition是因为子弹和plane都有相同的父节点,两者之间是相对坐标
Vector3 offset = new Vector3(, , );
bullet.transform.localPosition = this.transform.localPosition + offset;
} // 响应我们的鼠标事件,GetMouseButton(0)
void Update()
{
//鼠标按下的情况
if (Input.GetMouseButtonDown())
{
//-----修改-----
this.is_touch = false;//每次鼠标点下去,不管有没有点到飞机,初始化为没点到
Ray myRay = Camera.main.ScreenPointToRay(Input.mousePosition);//从摄像机发出一条射线
RaycastHit2D hit = Physics2D.Raycast(new Vector2(myRay.origin.x, myRay.origin.y), Vector2.zero);//射线从鼠标点击屏幕的那个点出发,射到以当前点击位置为原点的坐标系中的垂直于(0,0)的位置,
                                                        //如果从3D的视角看就是摄像机的射线垂直射到Canvas上
if (hit.collider)//如果碰到有Collider2D组件的物体,就做一些事情
{
if (hit.transform.gameObject.name == "plane")//如果碰到的是飞机
{
//Debug.Log(hit.transform.name);//打印出碰撞到的节点的名字
this.is_touch = true;//点到飞机
}
} if (is_touch)//如果点到飞机
{
//获得鼠标的初始点击位置
this.start_mouse_pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
//获得飞机的初始位置
this.start_plane_pos = this.transform.position;
}
} //鼠标滑动的情况
else if (Input.GetMouseButton() && this.is_touch)
{
Vector3 w_pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
//获得偏移量
Vector3 offset = w_pos - this.start_mouse_pos;
//设置飞机偏移后的位置
this.transform.position = this.start_plane_pos + offset;
} // 子弹发射逻辑控制,update里面嵌套自定义的update,自定义刷新函数
this.shoot_update(Time.deltaTime);
} void shoot_update(float dt)
{
if (!this.is_shooting)
{
return;
} this.shoot_time += dt;
if (this.shoot_time < this.shoot_rate)
{
return;
} this.shoot_time = ;
this.shoot_bullet();
} //写一个触发器来响应碰撞
void OnTriggerEnter2D(Collider2D c)
{
if (this.state == State.DEADED)
{
return;
} if (!is_super)//飞机不是超级状态
{
this.state = State.DEADED; this.box.enabled = false;// 把物理碰撞区域给隐藏,这样他就不会触发碰撞了。
this.is_shooting = false; // 不能发射子弹了 this.bomb_anim.play_once(this.on_bomb_anim_ended);//回调函数
}
} //写一个爆炸后调用的函数
void on_bomb_anim_ended()
{
//Debug.Log("on_bomb_anim_ended called");
this.bomb_anim.gameObject.SetActive(false);//把飞机的形状隐藏起来,不参与碰撞,也可以把刚体隐藏起来,也不参与碰撞
this.Invoke("plane_relive", 3.0f);
} //写一个爆炸后调用的函数的定时函数
void plane_relive()
{
this.state = State.NORMAL;
this.is_shooting = true;
this.shoot_time = ; this.ship_icon.sprite = this.ship_idle;//图像
this.bomb_anim.gameObject.SetActive(true);//把飞机的形状显示出来,参与碰撞
this.ship_icon.color = Color.red;//图像颜色变红
this.is_super = true;//设置为超级状态
this.box.enabled = true;//显示碰撞器
this.Invoke("enable_collider", 3.0f);// 允许3秒的无敌状态,3秒后再打开我们的碰撞无敌区域
} //写一个爆炸后调用的函数的定时函数的定时函数
void enable_collider()
{
this.is_super = false;//再设置回正常状态
this.ship_icon.color = Color.white;//图像颜色变原色
}
}

步骤七>>>>>>子弹打死敌人后删除自己,敌人也要做爆炸

1.由于子弹要在碰到敌机后马上删除,所以它自己也要写一个OnTriggerEnter2D的函数,在发生碰撞的时候调用,在plane_bullet.cs里面写OnTriggerEnter2D函数并直接Destroy自己的节点。

    // 子弹如果碰到了敌机,那么马上删除;
void OnTriggerEnter2D(Collider2D c) {
MonoBehaviour.Destroy(this.gameObject);
}

2.由于敌机要在碰到子弹后自爆,所以它自己也要写一个OnTriggerEnter2D的函数,在发生碰撞的时候调用。

3.在敌机e1到e8预制节点下面分别添加frame_anim.cs组件,因为敌机爆炸有7张图,属性size就写7,并把每一张爆炸图都拖进去。

改写后的enemy.cs

using UnityEngine;
using System.Collections;
using System; //用代码添加刚体组件和形状碰撞组件
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(BoxCollider2D))] public class enemy : MonoBehaviour {
//敌机爆炸所需要的变量
private frame_anim bomb_anim;
//委托
public event Action dead_event;     //敌机的类型
  public int e_type; private BoxCollider2D box;
private Rigidbody2D body;
private float dead_line_y;   // Use this for initialization
void Start () { this.body = this.GetComponent<Rigidbody2D>();
this.box = this.GetComponent<BoxCollider2D>();       //设置敌机碰撞器的形状的大小
      RectTransform r_trans = (RectTransform)this.transform;
      r_trans.localScale = new Vector3(, , );//放大节点两倍
      Vector2 size = r_trans.sizeDelta;//取出节点的大小       this.box.size = size;//设置好碰撞器大小
      this.box.isTrigger = true;//只触发不产生碰撞效果
      this.body.freezeRotation = true;//刚体不旋转
      this.body.velocity = new Vector2(, -);//给敌机一个初始向下的速度       //敌机飞出屏幕后删除
      float scale = 640.0f / (float)Screen.width;
      this.dead_line_y = -(Screen.height * scale * 0.5f + );       //获得播放动画的组件
      this.bomb_anim=this.GetComponent<frame_anim>(); } // Update is called once per frame
void Update () {
if (this.transform.localPosition.y < this.dead_line_y) {
MonoBehaviour.Destroy(this.gameObject);
}
} //写一个触发器来响应碰撞,碰到子弹后自爆,碰到飞机一点事情都没有
   void OnTriggerEnter2D(Collider2D c) {
// 敌人碰到玩家的子弹,敌人碰到玩家,敌人不爆炸,玩家爆炸,敌人碰到子弹,敌人爆炸
if (!c.gameObject.tag.Equals("plane_bullet")) { // 飞机碰到玩家,玩家爆炸;
return;
}
// 敌机就不能有碰撞区域
this.box.enabled = false;
// 子弹打到敌人
this.bomb_anim.play_once(this.on_bomb_anim_end);
// end
}   //写一个回调函数来等触发函数执行后来调用
void on_bomb_anim_end() {
this.dead_event(); // 触发事件
MonoBehaviour.Destroy(this.gameObject);
}
}

步骤八>>>>>>加上玩家得分的情况

1.我们需要一个统计分数的节点,我们在Canvas节点下面再创建一个空节点叫game_ui,Hierarchy视图中要放在game_root和menu_root之间。

2.把game_ui的节点大小设置为640X960,同时把菊花分开,让父亲有多大,孩子就有多大。

3.在tex文件夹下面创建一个美术字资源create-->Custom Font,把它的名字命名地和我们的字体资源一样的名字,是win_score.fontsettings。这个资源需要有个材质属性。于是我们创建一个字体材质create-->Material,名字命名地和字体资源的名字是一样的,叫win_score.mat。把材质的Shader设置为Mobile/Diffuse,然后把我们的原始字体资源win_score.png文件拖进去,再把材质球win_score.mat拖进刚才创建的Custom Font字体资源win_score.fontsettings。

4.我们还需要导入字模,在第24的文件夹里面,在Resources文件夹下面创建一个叫做Editor的文件夹,表示里面的东西是对Unity编辑器的扩展。然后把24里面的CreateFontEditor.cs脚本拷贝进去。

5.对win_score.fnt文件右键-->create-->CreateFBMFont,然后字模就导入进刚才的字体资源文件了,注意这里的文件是那个全是字的文件,不是我们刚才创建的win_score.fontsettings文件。

6.在game_ui节点下,创建一个Text类型的叫score的UI节点,把它的菊花设置为左上角对齐,然后设置具体坐标位置让它在左上角x,y(32,-32)

7.在enemy_root节点下的gen_enemy脚本里面写一个public的score对象属性,然后把刚才的score节点拖进去绑定。(绑定我的理解是:绑定不是赋值,而是引用,所以会同步发生变化)

8.字体颜色设置为白色,字体居中,把刚才我们创建的那个字体资源文件win_score.fontsettings拖进去Text组件的Character的Font属性中。

8.写一个事件委托,在enemy里面敌机爆炸的那个函数里面,触发事件,然后在gen_enemy脚本里面对事件进行响应,调用add_score函数,每次有事件发生就调用add_score函数。

改写后的gen_enemy脚本

using UnityEngine;
using System.Collections;
using UnityEngine.UI; public class gen_enemy : MonoBehaviour {
public GameObject[] group_set; // 分组的集合
public GameObject[] enemy_set; // 敌人的集合 //分数统计
public Text score;
int score_value; // Use this for initialization
void Start () {
this.score.text = "";
this.score_value = ;
} //开始生成敌机的函数
public void start_gen_enemy() {
this.score.text = "";
this.score_value = ;
this.Invoke("gen_one_group", );
}
  void gen_one_group() {
// [0, this.group_set.Length) 随机数,生成一个0到敌机组总数-1的随机数
int group_index = Random.Range(, this.group_set.Length); //设置一个初始位置,敌机组从这里生成并开始移动
Vector3 start_pos = new Vector3(, , ); // 循环遍历group下面的孩子数目;遍历随机到的那一个敌机组,遍历里面的每一个敌机
for (int i = ; i < this.group_set[group_index].transform.childCount; i++) {        //生成一个0到敌机总数-1的随机数,随机取1到8敌机类型的一种类型
       int e_type = Random.Range(, this.enemy_set.Length);        //获得孩子的位置,获得当前指定敌机的位置
Transform group_enemy = this.group_set[group_index].transform.GetChild(i); // 随机的生成了一个敌人,开始随机生成一架敌机
GameObject e_item = GameObject.Instantiate(this.enemy_set[e_type]);
e_item.transform.SetParent(this.transform, false);
Vector3 pos = start_pos + group_enemy.localPosition;
e_item.transform.localPosition = pos;
     
       //-----非常重要的一句话-----这句话就是把委托和响应函数进行了关联
       e_item.GetComponent<enemy>().dead_event += this.add_score; } // [0.0, 3.0f]
this.Invoke("gen_one_group", + Random.Range(0.0f, 3.0f));
} //增加分数的函数
void add_score() {
this.score_value ++;
this.score.text = "" + this.score_value;
}   // Update is called once per frame
void Update () { }
}

改写后的enemy脚本在步骤7里面,上次写的超前了

步骤九>>>>>>打开menu主页, 做好GUI 适配

1.把步骤1里面的对menu_root的隐藏显示出来,打钩。再注释掉game_scene里面的Start函数的this.on_game_start_click();这样只有按了按钮之后才会真正地开始游戏。

2.把menu_root节点的菊花也是设置为最右下角那个图案,使得父节点怎么变化,子节点就怎么变化。

3.把menu_root节点下面的menu_bg背景图节点的菊花设置为正下方那个图案,使得它可以随着分辨率的变化而上下拉伸。

4.屏幕适配完成。

关于Unity的入门游戏飞机大战的开发(下)的相关教程结束。

《关于Unity的入门游戏飞机大战的开发(下).doc》

下载本文的Word格式文档,以方便收藏与打印。