Unity3D_(游戲)雙人3D坦克_簡易版


 

 

雙人3D坦克實現

  

  player1: WSAD控制上下左右   空格鍵發射炮彈

  player2: IKJL可控制上下左右  B鍵發射炮彈 

  每個坦克只有100hp,子彈擊中1次扣30hp,hp時時顯示在坦克上

    當一輛坦克hp低於0時,游戲結束

  Main Camera聚焦兩輛坦克中心點   

 

  游戲項目已托管到github上(里面有個32bit可執行文件)  傳送門

    (官方demo 素材包有點大。。)

 

游戲界面

 

     (覺得子彈射程短,可以適當提高游戲子彈速度)

 

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

public class FollowCamera : MonoBehaviour {

    public GameObject tank1;
    public GameObject tank2;
    public float size= 0.58f;

    Vector3 p;

    // Use this for initialization
    void Start () {
        Vector3 target=(tank1.transform.position + tank2.transform.position) / 2;
        p = target - transform.position;
     }
    
    // Update is called once per frame
    void Update () {
        if (tank2 != null&&tank1!=null)
        {
            //計算出兩個坦克之間的距離
            transform.position = (tank1.transform.position + tank2.transform.position) / 2 - p;

            //找到兩個坦克的中點
            //讓攝像機對准中心點
            //根據兩點之間的距離,調整攝像機的尺寸
            float distance = Vector3.Distance(tank1.transform.position, tank2.transform.position);
            GetComponent<Camera>().orthographicSize = distance * size + 2f;
        }

        if(tank2 == null || tank1 == null)
        {
            SceneManager.LoadScene("SampleScene");
        }

    }
}
FollowCamera.cs 初始化游戲腳本

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TankHealth : MonoBehaviour {

    public int hp = 100;
    public GameObject ex;
    public Slider slider;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        
    }

    public void TakeDamage()
    {
        hp -= 30;
        if (hp < 0)
        {
            Destroy(gameObject);
            GameObject go = Instantiate(ex, transform.position, transform.rotation);
        }
        slider.value = hp;

    }

}
TankHealth.cs 坦克血量腳本

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DestroyForTime : MonoBehaviour {

    // Use this for initialization
    void Start () {
        Destroy(gameObject,2);
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}
DestroyForTime.cs 粒子動畫銷毀腳本

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shell : MonoBehaviour {

    public GameObject ex;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        
    }

    private void OnCollisionEnter(Collision collision)
    {
        Destroy(gameObject);
        GameObject go = Instantiate(ex,transform.position,transform.rotation);
        //判斷是否打中坦克
        if(collision.gameObject.tag == "Tank")
        {
            collision.gameObject.GetComponent<TankHealth>().TakeDamage();
        }
        //扣除坦克的血量

    }
}
Shell.cs 判斷是否打中坦克腳本

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shoot : MonoBehaviour {

    public GameObject shell;
    Transform pos;

    public KeyCode key = KeyCode.Space;

    public float speed = 180;

    // Use this for initialization
    void Start () {
        //找到子對象
        pos = transform.Find("FirstPosition");
    }
    
    // Update is called once per frame
    void Update () {
        //按下一個按鍵
        if (Input.GetKeyDown(key))
        {
            GameObject go = Instantiate(shell,pos.position,pos.rotation);
            go.GetComponent<Rigidbody>().velocity = go.transform.forward * speed;
            //go.GetComponent<Rigidbody>().velocity = Vector3.forward * speed;
        }
    }
}
Shoot.cs 子彈軌跡腳本

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Movement : MonoBehaviour {

    public float speed = 10;
    public float angularSpeed = 5;

    public string player = "1";

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        //獲得玩家的鍵盤輸入
        float v = Input.GetAxis("Vertical"+player);
        float h = Input.GetAxis("Horizontal"+ player);
       
        //讓坦克前后移動
        GetComponent<Rigidbody>().velocity = transform.forward * v * speed;
        GetComponent<Rigidbody>().angularVelocity = transform.up * h * angularSpeed;

    }
}
Movement.cs 控制坦克方向腳本

 

 

實現過程

  

 

創建場景

 

  導入坦克資源場景

  

  

    Lightmapping光照貼圖技術是一種增強靜態場景光照效果的技術,其優點是可以通過較少的性能消耗使靜態場景看上去更加真實,豐富,更加具有立體感;缺點是不能用來實時地處理動態光照。當游戲場景包含了大量的多邊形時,實時光源和陰影對游戲的性能的影響會很大。這時使用Lightmapping技術,將光線效果預渲染成貼圖使用到多邊形上模擬光影效果。
光照貼圖

  加載光照貼圖有時候會造成場景卡頓

    Auto Generate  :設置成不自動生成

    Generate Lighting  :生成一次場景光照

 

 

坦克的前后移動

 

  添加坦克預設體進入游戲場景,DustTrail粒子特效預設體放到坦克上

  (GameObject ->Align  With View 將Game視圖對准當前Scene視圖)

 

  給坦克添加碰撞器和剛體

  (碰撞器慢慢移,拖動數值調整到剛好包圍完坦克)

 

 

  添加移動坦克腳本

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Movement : MonoBehaviour {

    public float speed = 5;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {

        //獲得玩家的鍵盤輸入
        float v = Input.GetAxis("Vertical");
        //讓坦克前后移動
        GetComponent<Rigidbody>().velocity = transform.forward * v * speed;


    }
}
Movement.cs

 

  設置坦克移動速度

  public float speed = 5;

 

  獲得玩家的鍵盤輸入

float v = Input.GetAxis("Vertical");

 

  讓坦克前后移動

GetComponent<Rigidbody>().velocity = transform.forward * v * speed;

 

  (將相機放到坦克里面,實現相機和坦克一起移動)

 

 

坦克的旋轉

 

  查看Unity輸入按鍵值

  水平移動:Vertical

  左右移動:Horizontal

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Movement : MonoBehaviour {

    public float speed = 10;
    public float angularSpeed = 5;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        //獲得玩家的鍵盤輸入
        float v = Input.GetAxis("Vertical");
        float h = Input.GetAxis("Horizontal");
       
        //讓坦克前后移動
        GetComponent<Rigidbody>().velocity = transform.forward * v * speed;
        GetComponent<Rigidbody>().angularVelocity = transform.up * h * angularSpeed;

    }
}
Movement.cs

 

  設置坦克移動轉動角速度

  public float angularSpeed = 5;

 

  獲得玩家的鍵盤輸入

 float h = Input.GetAxis("Horizontal");

 

  讓坦克前后移動

GetComponent<Rigidbody>().angularVelocity = transform.up * h * angularSpeed;

 

 

  為實現雙人坦克效果,提高按鍵靈活性,在InputManager管理器中添加兩個Axes

  修改Axes值Horizontal1、Horizontal2、Vertical1、Vertical2

    

 

我把玩家二上下左右WSAD按鍵修改為IKJL,實現雙人笑游戲效果

 

  默認角色是1號玩家

       public string player = "1";

        //獲得玩家的鍵盤輸入
        float v = Input.GetAxis("Vertical"+player);
        float h = Input.GetAxis("Horizontal"+ player);
           

 

  新建雙人坦克修改Player值

 

 

 

 

坦克子彈

 

  給子彈添加剛體和碰撞器

  (將子彈設置為預設體,保存到Gary文件夾中)

 

  給坦克添加一個空物體,每次坦克都是從這個點動態生成子彈發射出去的

 

  添加Shoot腳本,掛載到坦克物體上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shoot : MonoBehaviour {

    public GameObject shell;
    Transform pos;

    // Use this for initialization
    void Start () {
        //找到子對象
        pos = transform.Find("FirstPosition");
    }
    
    // Update is called once per frame
    void Update () {
        //按下一個按鍵
        if (Input.GetKeyDown(KeyCode.Space))
        {
            //發射子彈 實例化
            Instantiate(shell,pos.position,pos.rotation);
        }
     

    }
}
Shoot.cs

 

  引用子彈實例化

 public GameObject shell;

 

  找到子彈發射的位置

 pos = transform.Find("FirstPosition");

 

  按下一個按鍵,,將子彈實例化

        if (Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(shell,pos.position,pos.rotation);
        }

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shoot : MonoBehaviour {

    public GameObject shell;
    Transform pos;

    public KeyCode key = KeyCode.Space;

    // Use this for initialization
    void Start () {
        //找到子對象
        pos = transform.Find("FirstPosition");
    }
    
    // Update is called once per frame
    void Update () {
        //按下一個按鍵
        if (Input.GetKeyDown(key))
        {
            Instantiate(shell,pos.position,pos.rotation);
        }

    }
}
Shoot.cs

 

  在外添加一個key,按任意鍵可以射出子彈

     public KeyCode key = KeyCode.Space;

        //按下一個按鍵
        if (Input.GetKeyDown(key))
        {
            Instantiate(shell,pos.position,pos.rotation);
        }    

 

 

  定義子彈發射速度

 public float speed = 180;

 

  按下一個按鍵,子彈發射出去

        if (Input.GetKeyDown(key))
        {
            GameObject go = Instantiate(shell,pos.position,pos.rotation);
            go.GetComponent<Rigidbody>().velocity = go.transform.forward * speed;
            go.GetComponent<Rigidbody>().velocity = Vector3.forward * speed;
        }

 

 

子彈爆炸動畫

 

  添加腳本shell,掛載到子彈物體對象上

 

    private void OnCollisionEnter(Collision collision)
    {
        Destroy(gameObject);
    }

 

  當子彈碰到剛體時銷毀自己

 

  添加子彈碰到物體觸發爆炸效果

 

  引用粒子特效

public GameObject ex;

 

   private void OnCollisionEnter(Collision collision)
    {
        Destroy(gameObject);
        GameObject go = Instantiate(ex,transform.position,transform.rotation);
    }

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shell : MonoBehaviour {

    public GameObject ex;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        
    }

    private void OnCollisionEnter(Collision collision)
    {
        Destroy(gameObject);
        GameObject go = Instantiate(ex,transform.position,transform.rotation);
    }
}
Shell.cs

 

 

子彈血量的減少

 

  給坦克添加標簽

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TankHealth : MonoBehaviour {

    public int hp = 100;
    public GameObject ex;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        
    }

     public void TakeDamage()
    {
        hp -= 30;
        if (hp < 0)
        {
            Destroy(gameObject);
            GameObject go = Instantiate(ex, transform.position, transform.rotation);
        }
    }

}
View Code

 

  初始化血量hp=100

 public int hp = 100;

 

  設置坦克爆炸粒子效果

  public GameObject ex;

 

  當血量低於0時,坦克銷毀,爆炸粒子效果出現

    public void TakeDamage()
    {
        hp -= 30;
        if (hp < 0)
        {
            Destroy(gameObject);
            GameObject go = Instantiate(ex, transform.position, transform.rotation);
        }
    }

 

 

 

相機跟隨

 

  將照相機改為正交

 

  在攝像機中添加並掛載FollowCameral腳本

 

  兩個坦克的引用

    public GameObject tank1;
    public GameObject tank2;

 

  兩個坦克之間的中點

    Vector3 p;

   Vector3 target=(tank1.transform.position + tank2.transform.position) / 2;
    p = target - transform.position;

 

  計算出兩個坦克之間的距離

 transform .position= (tank1.transform.position + tank2.transform.position) / 2 - p;

 

  找到兩個坦克的中點並讓攝像機對准中心點,根據兩點之間的距離,調整攝像機的尺寸

        float distance = Vector3.Distance(tank1.transform.position,tank2.transform.position);
        GetComponent<Camera>().orthographicSize = distance * size+ 2f;

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FollowCamera : MonoBehaviour {

    public GameObject tank1;
    public GameObject tank2;
    public float size= 0.58f;

    Vector3 p;

    // Use this for initialization
    void Start () {
        Vector3 target=(tank1.transform.position + tank2.transform.position) / 2;
        p = target - transform.position;
     }
    
    // Update is called once per frame
    void Update () {
        //計算出兩個坦克之間的距離
        transform .position= (tank1.transform.position + tank2.transform.position) / 2 - p;

        //找到兩個坦克的中點
        //讓攝像機對准中心點
        //根據兩點之間的距離,調整攝像機的尺寸
        float distance = Vector3.Distance(tank1.transform.position,tank2.transform.position);
        GetComponent<Camera>().orthographicSize = distance * size+ 2f;


    }
}
FollowCamera.cs

 

 

添加音效

 

  在Main Camera上綁定Audio Source音樂播放器

 

 

血條

 

  創建一個Slider,把Canvas移動到坦克上

  設置Slider控件的 PosX=0 PosX=0 PosZ=0

 

 

  參數下如下配置

 

 

 

  設置完成后效果如下

 

  設置成垂直

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TankHealth : MonoBehaviour {

    public int hp = 100;
    public GameObject ex;
    public Slider slider;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        
    }

    public void TakeDamage()
    {
        hp -= 30;
        if (hp < 0)
        {
            Destroy(gameObject);
            GameObject go = Instantiate(ex, transform.position, transform.rotation);
        }
        slider.value = hp;

    }

}
TankHealth.cs

 

  添加Slider控件

 public Slider slider;

 

  坦克攻擊時,時時刷新slider.value值

    public void TakeDamage()
    {
        hp -= 30;
        if (hp < 0)
        {
            Destroy(gameObject);
            GameObject go = Instantiate(ex, transform.position, transform.rotation);
        }
        slider.value = hp;

    }

 

 

完結!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM