[初學Unity]Space Shooter Tutorial Extension

Part 4 Extending Space Shooter

EXTENDING SPACE SHOOTER: ENEMIES, MORE HAZARDS, SCROLLING BG…

We will be covering how to add enemies with very basic manoeuvring and shooting, additional hazards of different types and scrolling the background.

  1. 通過複製Asteroid GameObject和替換子GameObject,添加另外兩種類型的隕石,更改他們的Collider以適應各自的形狀。

  2. Update Scripts : GameController.cs

using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;

public class GameController : MonoBehaviour
{
    public GameObject[] hazards;    // 數組,用來存放 各種小行星
    public Vector3 spawnValues;     // 通過Inspector來設置spawnValues,繼而在SpawnWaves中設置spawnPosition
    public int hazardCount;         // 每一波的小行星數量
    public float spawnWait;         // 相鄰兩個小行星的生成時間間隔
    public float startWait;         // a short pause after the game starts for the player to get ready
    public float waveWait;          // 相鄰兩波之間的時間間隔

    public GUIText scoreText;       // We will feed information to these labels as the game progresses.
    public GUIText restartText;
    public GUIText gameOverText;

    private bool gameOver;
    private bool restart;
    private int score;

    void Start()
    {
        gameOver = false;
        restart = false;
        gameOverText.text = "";
        restartText.text = "";
        score = 0;      // starting value
        UpdateScore();
        StartCoroutine(SpawnWaves());
    }

    void Update()
    {
        if(restart)
        {
            if(Input.GetKeyDown(KeyCode.R))
            {
            //    Application.LoadLevel(Application.loadedLevel);     // restart the game
                SceneManager.LoadScene("_Scenes/main");         // 重新加載這個 Scene     Loads the scene by its name or index in Build Settings.
            }
        }
    }

    IEnumerator SpawnWaves()
    {
        yield return new WaitForSeconds(startWait);
        while(true)
        {
            for (int i = 0; i < hazardCount; i++)
            {
                GameObject hazard = hazards[Random.Range(0, hazards.Length)];   // 隨機從數組 hazards 中選取一個元素 hazard,NICE
                Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
                Quaternion spawnRotation = Quaternion.identity;
                Instantiate(hazard, spawnPosition, spawnRotation);
                yield return new WaitForSeconds(spawnWait);
            }
            yield return new WaitForSeconds(waveWait);
            if(gameOver)            // 遊戲結束的時候,詢問是否重來
            {
                restartText.text = "Press 'R' for Restart";
                restart = true;     
                break;              // 結束這個 spawnwaves 循環
            }
        }
    }

    public void AddScore(int scoreValue)
    {
        score += scoreValue;
        UpdateScore();
    }   

    void UpdateScore()
    {
        scoreText.text = "Score: " + score;
    }

    public void GameOver()      // 如同 AddScore 一樣,此函數可以由別的GameObject調用。
    {
        gameOverText.text = "Game Over!";
        gameOver = true;
    }
}

[

// declares and instantiates arrays
// arrays.cs
using System;
class DeclareArraysSample
{
    public static void Main()
    {
        // Single-dimensional array
        int[] numbers = new int[5];

        // Multidimensional array
        string[,] names = new string[5,4];

        // Array-of-arrays (jagged array)
        byte[][] scores = new byte[5][];

        // Create the jagged array
        for (int i = 0; i < scores.Length; i++)
        {
            scores[i] = new byte[i+3];
        }

        // Print length of each row
        for (int i = 0; i < scores.Length; i++)
        {
            Console.WriteLine("Length of row {0} is {1}", i, scores[i].Length);
        }
    }
}

//Output
//Length of row 0 is 3
//Length of row 1 is 4
//Length of row 2 is 5
//Length of row 3 is 6
//Length of row 4 is 7

  1. scrolling the background

兩個部分:a scrolling texture and two particle systems

  1. drag StarField(contains two particle systems) prefab on to Hierarchy.
  2. duplicate the Background and drag it on to Background, make it a child game object.
  3. In the scene view, select Background (1) and hold down “K” and drag it to move it. And we get that

  1. use script to control the scrolling of the background.
// BGScroller.cs
using UnityEngine;
using System.Collections;

public class BGScroller : 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);   // 類似於 模 操作,但可以作用於浮點數
        transform.position = startPosition + Vector3.forward * newPosition;     // 沿着z軸方向移動
    }
}
  1. Add Enemys!!!!!!!!!!!!

    • Create an empty gameobect named Enemy Ship to set the logic stuff(set the position.z to 9, so we can see it in the game view), and drag model vehicle_enemyShip on to it to be it’s child gameobject.
    • turn the vehicle_enemyShip 180 around y axies ,not the Enemy Ship gameobject.
    • add engines_enemy to Enemy Ship GameObject to be it’s child.
    • add RigidBody and Collider components ,drag DestroyByContact.cs on to Enemy Ship.
    • set the Enemy Ship to shoot.
    • create Spot Spawn as a child gameobject of Enemy Ship and drag Bolt prefab on to it.
    • Shot Spawn need to rotation 180. 這樣子彈的方向就是向下的,不會向上飛。
    • 複製 material fx_bolt_orange,修改之,得到 material fx_bolt_cyan。用 fx_bolt_cyan 修改 VFX的 material,方便的是 Bolt中的邏輯設置適用於此。
    • drag DestroyByContact.cs to Bolt Enemy, modify it.
        if(other.CompareTag("Boundary") || other.CompareTag("Enemy")) // 當 other 的 tag 是 Boundary 的時候,跳過,是 Enemy 的時候也跳過,因爲 DestroyByContact.cs 只附加到了 Enemy 類型的 GameObject 上。
        {
            return;
        }

        if(explosion != null)       // 當我們有一個 explosion 的時候,explosion。沒有的時候,不 explosion。
        {
            Instantiate(explosion, transform.position, transform.rotation);
        }
  • drag Bolt Enemy to Prefabs
  • drag Mover.cs to Enemy Ship to move it.
  • add EvasiveManeuver.cs to Enemy Ship, edit it
using UnityEngine;
using System.Collections;

public class EvasiveManeuver : MonoBehaviour
{
    public float dodge;     // 中文釋義:躲避
    public float smoothing;
    public float tilt;
    public Vector2 startWait;
    public Vector2 maneuverTime;
    public Vector2 maneuverWait;
    public Boundary boundary;   

    private float targetManeuver;       // a point on the x axies. So the Enemy will move left or right
    private float currentSpeedZ;        // z方向的當前速度
    private Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        currentSpeedZ = rb.velocity.z;
        Debug.Log("currentSpeedZ = " + currentSpeedZ);
        StartCoroutine(Evade());
    }

    IEnumerator Evade()
    {
        yield return new WaitForSeconds(Random.Range(startWait.x, startWait.y)); // 等候一個隨機的時間

        while (true)
        {
            targetManeuver = Random.Range(1, dodge) * -Mathf.Sign(transform.position.x);    // 當Enemy在左側的時候會向右dodge,在右側的時候向左dodge
            yield return new WaitForSeconds(Random.Range(maneuverTime.x, maneuverTime.y));
            targetManeuver = 0;                 // set it back
            yield return new WaitForSeconds(Random.Range(maneuverWait.x, maneuverWait.y));
        }
    }

    void FixedUpdate()
    {
        float newManeuver = Mathf.MoveTowards(rb.velocity.x, targetManeuver, Time.deltaTime * smoothing);
        rb.velocity = new Vector3(newManeuver, 0.0f, currentSpeedZ);
        // Clamp the position of Enemy
        rb.position = new Vector3
        (
            Mathf.Clamp(rb.position.x, boundary.xMin, boundary.xMax),
            0.0f,
            Mathf.Clamp(rb.position.z, boundary.zMin, boundary.zMax)
        );
        // set tilt
        rb.rotation = Quaternion.Euler(0.0f, 0.0f, rb.velocity.x * -tilt);
    }
}

something else

添加了兩個新特性:

  • 讓 enemy 朝着 player 的方向走
  • 增加 player 的炮筒數目

MOBILE DEVELOPMENT: CONVERTING SPACE SHOOTER TO MOBILE

Link to the video
In this session we will be taking the Space Shooter tutorial and adding mobile devices to the possible build targets. We will cover touch and accelerometer input, build target defines, and more. Tutor - Adam Buckner

  • use unity remote apk to link your android device to computer, to use it to control, and you need to use USB to link both of them before.
  • 通過旋轉手機讓飛機上下飛行
// Done_PlayerController.cs
using UnityEngine;
using System.Collections;

[System.Serializable]
public class Done_Boundary 
{
    public float xMin, xMax, zMin, zMax;
}

public class Done_PlayerController : MonoBehaviour
{
    public float speed;
    public float tilt;
    public Done_Boundary boundary;

    public GameObject shot;
    public Transform shotSpawn;
    public float fireRate;

    private float nextFire;
    private Quaternion calibrationQuaternion;

    void Start()
    {
        CalibrateAccelerometer();
    }

    void Update()
    {
        if (Input.GetButton("Fire1") && Time.time > nextFire)
        {
            nextFire = Time.time + fireRate;
            Instantiate(shot, shotSpawn.position, shotSpawn.rotation);
            GetComponent<AudioSource>().Play();
        }
    }

    // Uesd to calibrate the Input.acceleration input           ??????????????
    void CalibrateAccelerometer()
    {
        Vector3 acceleratioinSnapshot = Input.acceleration;
        Quaternion rotationQuaternion = Quaternion.FromToRotation(new Vector3(0.0f, 0.0f, -1.0f), acceleratioinSnapshot);
        calibrationQuaternion = Quaternion.Inverse(rotationQuaternion);
    }

    // Get the 'calibrated' value from the Input
    Vector3 FixedAcceleration(Vector3 acceleration)
    {
        Vector3 fixedAcceleration = calibrationQuaternion * acceleration;
        return fixedAcceleration;
    }

    void FixedUpdate ()
    {
        //float moveHorizontal = Input.GetAxis ("Horizontal");
        //float moveVertical = Input.GetAxis ("Vertical");

        //Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
        Vector3 accelerationRaw = Input.acceleration;
        Vector3 acceleration = FixedAcceleration(accelerationRaw);
        Vector3 movement = new Vector3(acceleration.x, 0.0f, acceleration.y);
        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)
        );

        GetComponent<Rigidbody>().rotation = Quaternion.Euler (0.0f, 0.0f, GetComponent<Rigidbody>().velocity.x * -tilt);
    }


}
  • movement, add touch pad area.

    1. Create a UI/image GameObject. a Canvas object and a EventSystem GameObject has been created automatically.
    2. 我們要的效果是,在這塊【!!加圖】區域內,當你touch的時候,就可以接着根據你手指的方向來移動飛船,而不是添加joystick來完成。也就是用手指的相對最開始點的運動來設置飛船的運動方向。(和速度??)
    3. 當有第二個手指的時候,會跟着第二個手指的控制,這不好,。我們要在有一個手指的時候,忽略其他的touch。
  • fire, add touch pad area.

  • 編譯,運行

Finally 遊戲成功運行在我的小米上了。哈哈哈

有些代碼還不是很懂:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章