Unity实例开发-太空射手
此案例学习自漠刀凡尘
传送门:
运行结果:
脚本:
BGScroll:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BGScroll : MonoBehaviour {
public float scrollSpeed; //背景图片滚动速度
public float tileSizeZ; //滚动长度
private Vector3 startPosition; //记录初始变量
void Start () {
startPosition = transform.position;
}
void Update () {
float newPosition = Mathf.Repeat (Time.time * scrollSpeed, tileSizeZ); //求Time.time * scrollSpeed % tileSizeZ
transform.position = startPosition + Vector3.forward * newPosition;
}
}
DestroyByBoundary:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DestroyByBoundary : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
private void OnTriggerExit(Collider other)
{
//与Boundary发生碰撞的直接销毁
Destroy (other.gameObject);
}
}
DestroyByContact:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DestroyByContact : MonoBehaviour {
public GameObject explosion; //小行星爆炸特效
public GameObject explosion_player; //玩家飞船爆炸特效
public int scoreValue; //击毁获得的分值
private GameController gameController;
void Start()
{
GameObject gameControllerObj = GameObject.FindGameObjectWithTag ("GameController");
if (gameControllerObj)
gameController = gameControllerObj.GetComponent<GameController> ();
else
Debug.Log ("Not find 'GameController' script");
}
//碰撞检测的回调函数,需要勾选 is Trigger选项
void OnTriggerEnter(Collider other)
{
//当是敌人或者边界时,不计算碰撞
if (other.tag == "Enemy" || other.tag == "Boundary")
return;
if (explosion)
Instantiate (explosion, transform.position, transform.rotation); //实例化特效
if (other.tag == "Player" && explosion_player) {
Instantiate (explosion_player, transform.position, transform.rotation);
gameController.GameOver ();
}
//分数递增
gameController.AddScore (scoreValue);
//销毁特效
Destroy (other.gameObject);
Destroy (gameObject);
}
}
DestroyByTime:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DestroyByTime : MonoBehaviour {
public float lifeTime; //延续多少秒后销毁
// Use this for initialization
void Start () {
Destroy (gameObject, lifeTime);
}
// Update is called once per frame
void Update () {
}
}
EvasiveManeuver:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EvasiveManeuver : MonoBehaviour {
public Boundary boundary; //边界
public float tilt; //翻转度
public float dodge;
public float smoothing; //平滑度
public Vector2 StartWait; //刚开始等待时间
public Vector2 ManeuverTime; //规避时间
public Vector2 ManeuverWait; //距离下次规避需要等待时间
private float currentSpeed; //记录z轴的速度
private float targetManeuver; //获得x轴目标速度
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody> ();
currentSpeed = rb.velocity.z;
StartCoroutine (Evade());
}
//规避
IEnumerator Evade()
{
//首先等待一段时间
yield return new WaitForSeconds (Random.Range (StartWait.x, StartWait.y));
while (true) {
targetManeuver = Random.Range (1, dodge) * -Mathf.Sign (rb.position.x);
yield return new WaitForSeconds (Random.Range (ManeuverTime.x, ManeuverTime.y));
//目标速度归0
targetManeuver = 0;
yield return new WaitForSeconds (Random.Range (ManeuverWait.x, ManeuverWait.y));
}
}
void FixedUpdate()
{
//改变rb.velocity.x向targetManeuver靠近 smoothing * Time.deltaTime为应用到该值的最大变化
float newManeuver = Mathf.MoveTowards (rb.velocity.x, targetManeuver, smoothing * Time.deltaTime);
rb.velocity = new Vector3 (newManeuver, 0.0f, currentSpeed);
rb.position = new Vector3
(
Mathf.Clamp(rb.position.x, boundary.xMin, boundary.xMax),
0.0f,
Mathf.Clamp(rb.position.z, boundary.zMin, boundary.zMax)
);
rb.rotation = Quaternion.Euler (0.0f, 0.0f, rb.velocity.x * -tilt);
}
}
GameController:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GameController : MonoBehaviour {
public GameObject[] hazards; //敌人预制体
public Vector3 spawnValue; //产生敌人位置最大值
public long hazardCnt; //每波敌人的数目
public float startWait; //生成敌人之前需要等待的时间
public float waveWait; //每个敌人生成之间的时间间隔
public float spawnWait; //每波敌人的间隔
public Text gameOverText; //结束文本
public Text scoreText; //分数文本
public Text restartText; //重新开始文本
private int score; //分数
private bool gameOver; //是否游戏结束
private bool restart; //是否出现重新开始
// Use this for initialization
void Start () {
StartCoroutine (SpawnWaves());
score = 0;
gameOver = false;
restart = false;
gameOverText.text = "";
restartText.text = "";
UpdateScore ();
}
// Update is called once per frame
void Update () {
//按下R键重新加载场景
if (restart && Input.GetKeyDown (KeyCode.R))
SceneManager.LoadScene (SceneManager.GetActiveScene ().buildIndex);
}
//敌人的生成
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds (startWait);
while (true) {
for (int i = 0; i < hazardCnt; ++i) {
GameObject hazard = hazards [Random.Range (0, hazards.Length)];
Vector3 spawnPosition = new Vector3 (
Random.Range (-spawnValue.x, spawnValue.x),
spawnValue.y,
spawnValue.z
);
Instantiate (hazard, spawnPosition, Quaternion.identity);
yield return new WaitForSeconds (spawnWait);
}
if (gameOver) {
restart = true;
restartText.text = "Press 'R' for respart.";
break;
}
yield return new WaitForSeconds (waveWait);
}
}
//分数更新
private void UpdateScore()
{
scoreText.text = "Score:" + score.ToString ();
}
//分数增加
public void AddScore(int newScore)
{
score += newScore;
UpdateScore();
}
//游戏结束
public void GameOver()
{
gameOver = true;
gameOverText.text = "Game Over!";
}
}
Mover:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Mover : MonoBehaviour {
public float speed; //速度
private Rigidbody rb;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody> ();
rb.velocity = Vector3.forward * speed;
}
// Update is called once per frame
void Update () {
}
}
PlayerControl:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
//边界
public class Boundary
{
public float xMin, xMax, zMin, zMax;
}
public class PlayerControl : MonoBehaviour {
public float speed; //移动速度
public Boundary boundary;
public float tilt; //倾斜量
public GameObject shot; //子弹
public Transform shotSpawn; //获取子弹挂载点的位置信息
public float fireRate; //子弹发射速率
private float nextFire; //判断是否可以进行下一颗子弹发射
private AudioSource audioSrc; //音乐组件
// Use this for initialization
void Start () {
audioSrc = GetComponent<AudioSource> ();
}
// Update is called once per frame
void Update () {
if (Input.GetButton ("Fire1") && Time.time >= nextFire) {
nextFire = Time.time + fireRate;
Instantiate (shot, shotSpawn.position, shotSpawn.rotation);
//音乐播放
audioSrc.Play ();
}
}
void FixedUpdate()
{
//获取下列默认轴: “Horizontal” 和“Vertical” 映射于控制杆、A、W、S、D和箭头键(方向键)。
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
//设定刚体速度
GetComponent<Rigidbody>().velocity = movement * speed;
//限制运动范围
GetComponent<Rigidbody> ().position = new Vector3 (
Mathf.Clamp(GetComponent<Rigidbody>().position.x, boundary.xMin, boundary.xMax),
0.0f,
Mathf.Clamp(GetComponent<Rigidbody>().position.z, boundary.zMin, boundary.zMax)
);
//返回一个旋转角,绕x轴旋转x度,绕y轴旋转y度,绕z轴旋转z度。
GetComponent<Rigidbody>().rotation = Quaternion.Euler (0.0f, 0.0f, GetComponent<Rigidbody>().velocity.x * -tilt);
}
}
RandomRotator:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RandomRotator : MonoBehaviour {
public float tumble; //翻滚速度
private Rigidbody rb;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody> ();
//改变刚体的角速度变量
rb.angularVelocity = Random.insideUnitSphere * tumble; //随机返回单位球内任意一点
}
// Update is called once per frame
void Update () {
}
}
WeaponController:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponController : MonoBehaviour {
public GameObject shot;
public Transform shotSpawn;
public float shotRate;
public float delay; //实例化敌机后多久发射子弹
private AudioSource audioSrc;
// Use this for initialization
void Start () {
//在delay秒调用Fire方法,以后每过shotRate秒重新调用Fire方法
InvokeRepeating ("Fire", delay, shotRate);
audioSrc = GetComponent<AudioSource> ();
}
// Update is called once per frame
void Update () {
}
//发射子弹
private void Fire()
{
Instantiate (shot, shotSpawn.position, shotSpawn.rotation);
audioSrc.Play ();
}
}