玩家操作宇宙飞船在外太空飞行,随时会有流星下落,玩家在游戏过程中要设法存活下来。
游戏规则:
玩家直到被流星击中则游戏结束。
玩家通过发射子弹来摧毁流星,每摧毁一颗流星记 1 分。
流星持续不断且越来越快地出现,直到击中宇宙飞船,游戏结束。
游戏素材:
外太空背景:StarSky.png
宇宙飞船模型:SpaceShooter.fbx
宇宙飞船纹理:BodyTXTR.jpg
流星模型:Meteor.fbx
流星纹理:MeteorTXTR.png
子弹:在 Unity 设计
游戏效果如下图所示:
11.2 游戏世界这款游戏的游戏世界实现起来比较简单,游戏以接近 2D 状态来呈现,将贴图在玩家背后垂直移动,看上去好像玩家在前进。
1.创建新项目,将场景保存为 MainScene,设置 Game 视图为 5:4。
2.将摄像机位置调整为(0,0,-10),设置 Projection 属性为 Orthographic,Size 为 6。
11.2.1 背景使用两个背景图像在屏幕上向下滚动,一旦底部的对象离开屏幕,就把它放在屏幕上方。
1.向场景中添加一个立方体,重命名为 Background,置于(0,0,0) 处,缩放为 (15,15,0.1)。
2.在 Project 视图中 Assets 文件夹中创建 Textures 文件夹,将 StarSky.png 文件拖拽到该文件夹中,然后将 StarSky 纹理推拽到立方体上。
3.在 Project 视图中 Assets 文件夹中创建 Scripts 文件夹,在该文件夹中创建脚本 BackgroundController,并挂载到 Background 立方体上。编写代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BackgroundController : MonoBehaviour
{
public float speed = -2f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.Translate(0f, speed * Time.deltaTime, 0f);
if (transform.position.y <= -15)
{
transform.Translate(0f, 30f, 0f);
}
}
}
4.复制背景立方体,置于 (0,15,0) 处。运行游戏,会发现背景无缝地连续滚动。
11.2.2 游戏实体在该游戏中,游戏实体主要为玩家、流星和子弹。其交互为玩家发射子弹,子弹摧毁流星,流星摧毁玩家。
1.玩家
玩家就是宇宙飞船。
1.在 Assets 文件夹中创建 Meshes 文件夹,将文件 SpaceShooter.fbx 拖拽到该文件夹中。
2.将 Project 视图中的 SpaceShooter.fbx 拖拽到场景中,位置为 (0,-4,-5),旋转设置为 (270,0,0),缩放为 (10,10,10)。
3.将 BodyTXTR.jpg 文件拖拽到 Textures 文件夹下,然后将该纹理推拽到场景中的宇宙飞船上。
4.给宇宙飞船添加一个胶囊碰撞器,选中 Is Trigger,把半径设置为 0.1,高度设置为 0.02,方向为 Z-Axis。
2.流星
1.将 Meteor.fbx 模型拖拽到 Meshes 文件夹中,并将 Project 视图中的 Meteor 拖拽到场景中。设置位置为 (0,0,-5),旋转为 (0,0,0),缩放为 (1,1,1)。
2.将 MeteorTXTR.png 文件拖拽到 Textures 文件夹中,并把纹理 MeteorTXTR 拖拽到流星上。
3.给流星添加一个刚体组件,取消选中 Use Gravity。
4.给流星添加一个胶囊碰撞器。
5.在 Assets 下建立 Prefabs 文件夹,将场景中的流星拖拽到 Prefabs 文件夹中,删除场景中的流星
3.子弹
1.向场景中添加一个胶囊体,位置(0,0,0),缩放(0.1,0.1,0.1)。给胶囊体添加刚体,并取消选中 Use Gravity。
2.在 Materials 文件夹中创建新材质 BulletMaterial,设置颜色为明亮的绿色,并拖拽到胶囊体上。
3.将胶囊体拖拽到 Prefabs 文件夹中,重命名为 Bullet,删除场景中的胶囊体。
4.触发器
触发器用于当子弹和流星移动到游戏舞台外面后,通过触发器可以捕获并销毁。
1.在场景中添加一个立方体,重命名为 Trigger,位置为(0,9,-5),缩放为(15,0.1,1)。
2.在 Inspector 视图中选中 Box Collider 的 Is Trigger。
3.复制该立方体,位置为(0,-9,-5)。
11.3 控制
玩家需要移动飞船和发射子弹,子弹和流星需要自由移动,流星需要不断的生成,触发器需要检测碰撞并清理对象。另外还需要一个游戏控制器来跟踪所有动作。
11.3.1游戏控制器游戏控制器主要用于显示玩家的积分。所以需要添加 UI 对象。
游戏控制器的另外一个作用是用于控制游戏是否结束。
1.在场景中添加一个 Text UI 元素,设置锚点为右上角,设置位置为(-100,-30,0),对齐方式为居中,将文本内容清空,文本颜色为白色。
2.在 Scripts 文件夹下创建脚本文件 GameController,并在场景中添加空物体,将该脚本挂载到这个空物体上。编写脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameController : MonoBehaviour
{
private int score = 0;
private Text txt;
// Start is called before the first frame update
void Start()
{
txt = GameObject.Find("Text").GetComponent<Text>();
}
public void AddScroe()
{
score ;
txt.text = "Score : " score.ToString();
}
public void EndGame()
{
// 加载游戏结束场景
}
// Update is called once per frame
void Update()
{
}
}
在上面的代码中,通过 Start() 方法中的语句在游戏开始后获取用于显示积分的 Text 元素,当需要加分时,其他脚本可以调用 public 方法 AddScore()。
11.3.2 流星控制流星是从屏幕顶部往下落,在流星下落时,需要旋转流星模型以使其看起来比较真实。
在 Scripts 文件夹下创建脚本 MeteorController,在 Prefabs 下双击 Meteor,将脚本挂载到 Meteor 上。编写脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeteorController : MonoBehaviour
{
private float speed;
private float rotation;
// Start is called before the first frame update
void Start()
{
speed = Random.Range(-10, -3);
rotation = Random.Range(-40, 40);
}
// Update is called once per frame
void Update()
{
transform.Translate(0f, speed * Time.deltaTime, 0f);
transform.Rotate(0f, rotation * Time.deltaTime, 0f);
}
}
11.3.3 流星生成器
在 Scripts 下创建一个脚本 MeteorBuilder,在场景中创建一个空物体 MeteorBuilder,位置为(0,7,-5),将脚本挂载到该空物体,编写代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeteorBuilder : MonoBehaviour
{
public GameObject meteor;
private float buildSpeed = 100;
private float buildStep = 0.1f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Random.Range(0, buildSpeed) < 1)
{
Vector3 pos = transform.position;
Instantiate(meteor, new Vector3(pos.x Random.Range(-6, 6), pos.y, pos.z), Quaternion.identity);
buildSpeed -= buildStep;
if (buildSpeed < 10) buildSpeed = 10;
}
}
}
上面的代码中,GameObject 是流星的预设,另外两个变量是用于管理流星的时间。在 Update() 方法中,当产生的随机数小于 1 时就会实例化一个流星,实例化的流星与挂载的空物体具有相同的 y 坐标和 z 坐标,而 x 坐标会随机在 -6 ~ 6 之间。最后时减少 buildSpeed 的值,如果 buildSpeed 的值小于 10 则保持为 10 不变,这样将会随着时间的推移使流星的生成越来越快。
在 Inspector 视图中,将预设 Meteor 拖拽到 MeteorBuilder 的脚本上。
11.3.4 触发器脚本触发器脚本很简单,就是将碰撞的物体销毁。
在 Scripts 下创建脚本 TriggerController,并挂载到两个触发器立方体上。编写代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TriggerController : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)
{
Destroy(other.gameObject);
}
}
11.3.5 玩家脚本
玩家脚本实现的功能是通过左右按键来移动宇宙飞船,通过空格键来发射子弹,当被流星碰撞后结束游戏。
在 Scripts 下创建脚本 PlayerController,挂载到宇宙飞船上,编写代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public GameObject bullet;
private GameController game;
// Start is called before the first frame update
void Start()
{
game = GameObject.Find("GameController").GetComponent<GameController>();
}
// Update is called once per frame
void Update()
{
transform.Translate(Input.GetAxis("Horizontal") * 10f * Time.deltaTime, 0f, 0f);
if (Input.GetButtonDown("Jump"))
{
Instantiate(bullet, new Vector3(transform.position.x, transform.position.y 1.2f, -5f),
Quaternion.identity);
}
}
private void OnTriggerEnter(Collider other)
{
Destroy(other.gameObject);
Destroy(this.gameObject);
game.EndGame();
}
}
将子弹预设拖拽到宇宙飞船的脚本上。
11.3.6 子弹脚本子弹脚本实现的功能是子弹的快速飞行,当与流星发生碰撞后加分,并且销毁流星和自己。
在 Scripts 下创建脚本 BulletController,双击打开预设 Bullet,将脚本挂载预设上,编写代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletController : MonoBehaviour
{
private float speed = 10.0f;
private GameController game;
// Start is called before the first frame update
void Start()
{
game = GameObject.Find("GameController").GetComponent<GameController>();
}
// Update is called once per frame
void Update()
{
transform.Translate(0f, speed * Time.deltaTime, 0f);
}
private void OnCollisionEnter(Collision collision)
{
Destroy(collision.gameObject);
Destroy(this.gameObject);
game.AddScroe();
}
}
11.4 结束场景
至此,游戏功能基本开发完成,只需要修改游戏控制器的 EndGame() 方法切换到结束场景即可。游戏结束的显示可以通过增加结束场景来实现。在结束场景中还可以添加一个重新开始的按钮让画面回到舞台。
1.新建一个场景 EndScene,并在其中添加 UI -> Text 和 Button。
2.设置 Text 的文字为 Game Over,字号为 72,宽度 600,高度 200,居中显示。
3.设置 Button 的文字为 Restart。
4.在 Scripts 中创建脚本 RestartButton,并挂载到 Button 上,编写脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class RestartButton : MonoBehaviour
{
private Button restartButton;
// Start is called before the first frame update
void Start()
{
restartButton = GameObject.Find("Button").GetComponent<Button>();
restartButton.onClick.AddListener(RestartButtonClicked);
}
// Update is called once per frame
void Update()
{
}
void RestartButtonClicked()
{
SceneManager.LoadScene("Scenes/MainScene");
}
}
5.修改 GameController 脚本的 EndGame() 方法如下:
public void EndGame()
{
// 加载游戏结束场景
SceneManager.LoadScene("Scenes/EndScene");
}
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved