【坦克大戰】Unity3D多人在線游戲(泰課的坦克大戰--旋轉的螺絲釘)


 

【坦克大戰】Unity3D多人在線游戲

http://www.taikr.com/my/course/937

1.NetworkManager的介紹:

 

說明:選擇固定生成時會自動尋找有StartPosition組件的位置

2.NetWorkDiscovery組件的介紹:

使用在局域網中的一個組件,在英特網上不能使用

官方文檔:

 

說明:NetWorkDiscovery與Network managerHUD相似:

Network managerHUD介紹:就是顯示Network manager的,如下圖:

 

 

3.框架部分,開始界面的5個按鈕

 

IndexUI

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public class IndexUI : MonoBehaviour {

 

    public void SingleBtn()

    {

 

    }

    public void MutiplayBtn()

    {

 

    }

    public void LanBtn()

    {

 

    }

}

4.LanGame局域網對戰功能的實現

 

放在NetWorkManagerCustom中的代碼:

public static void LanGame()

    {

        //轉換一下再調用

        singleton.StartCoroutine((singleton as NetWorkManagerCustom).DiscoveryNetWork());

    }

 

    public IEnumerator DiscoveryNetWork()

    {

        //取得Discovery組件

        NetworkDiscoverCustom discovery = GetComponent<NetworkDiscoverCustom>();

        discovery.Initialize();//組件初始化

        discovery.StartAsClient();//掃描局域網的服務器

        yield return new WaitForSeconds(2);

 

        //沒有找到局域網中的服務器的話就建立服務器

        if (discovery.running)

        {

            discovery.StopBroadcast();//停掉廣播包

            yield return new WaitForSeconds(0.5f);

 

            discovery.StartAsServer();//作為服務器發射廣播包

            StartHost();//作為服務器和客戶端同時啟動

            //StartClient();//作為客戶端啟動

            //StartServer();//只作為服務器啟動

        }

}

放在NetworkDiscoverCustom中的代碼:

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.Networking;

 

public class NetworkDiscoverCustom : NetworkDiscovery {

 

    public override void OnReceivedBroadcast(string fromAddress,string data)

    {

        StopBroadcast();

 

        NetWorkManagerCustom.singleton.networkAddress = fromAddress;

        NetWorkManagerCustom.singleton.StartClient();

    }

}

 

5.NetGame,英特網的在線對戰:

 

 

public static void NetGame()

    {

        singleton.StartMatchMaker();//表示啟用Unet網絡對戰功能

        singleton.matchMaker.ListMatches(0, 20, "", false, 0, 0, singleton.OnMatchList);

            //第1個參數:startpagenumber:表示第幾頁的list

            //第2個參數:表示每一頁有多少個

            //第3個參數:表示需要找到的房間名稱

            //第4個參數:表示是否返回帶有密鑰的房間

            //第5個參數:表示的是競賽方面的設置

            //第6個參數:表示的是一個域,只能從這個域上面返回房間

            //第7個參數:是一個回調的函數

    }

 

    public override void OnMatchList(bool success, string extendedInfo, List<MatchInfoSnapshot> matchList)

    {

        if (!success) return;

 

        if (matchList != null)

        {

            List<MatchInfoSnapshot> availableMatches = new List<MatchInfoSnapshot>();

            foreach (MatchInfoSnapshot match in matchList)

            {

                if (match.currentSize < match.maxSize)

                {

                    availableMatches.Add(match); //保存房間玩家沒有滿的情況

                }

 

            }

 

            //列表的數量是否為0,為0創建服務器,不為0的話就加入服務器

            if (availableMatches.Count == 0)

            {

                //創建服務器

                CreateMatch();

            }

            else

            {

                //加入服務器

                matchMaker.JoinMatch(availableMatches[Random.Range(0, availableMatches.Count - 1)].networkId, "", "", "", 0, 0, OnMatchJoined);

            }

 

        }

    }

 

    void CreateMatch() //告訴Unet創建網絡服務器

    {

        matchMaker.CreateMatch("", matchSize, true, "", "", "", 0, 0, OnMatchCreate);

        //第1個參數:房間名稱

        //第2個參數:房間可玩家數

        //第3個參數:

        //第4個參數:口令

        //第5個參數:Client Ip地址(公網)

        //第6個參數:私網地址

    }

 

    public override void OnMatchCreate(bool success, string extendedInfo, MatchInfo matchInfo)

    {

        if (!success) return;

        StartHost(matchInfo);//利用Unet返回的matchinfo創建服務器

    }

 

    public override void OnMatchJoined(bool success, string extendedInfo, MatchInfo matchInfo)

    {

        if (!success)

        {

            int currentScene = SceneManager.GetActiveScene().buildIndex;

            SceneManager.LoadScene(currentScene);

            return;

        }

        StartClient(matchInfo); //利用Unet傳回的matchinfo啟動客戶端

    }

 

6.單人模式:

public static void SimpleGame()

    {

        singleton.StartHost(singleton.connectionConfig, 1);

 }

 

7.NetWorkTransform

8、角色的移動

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

public class Player : NetworkBehaviour {

    private Rigidbody rb;

    public float MoveSpeed = 8f;

    void Awake () {
        rb = transform.GetComponent<Rigidbody>();
    }
    
    void FixedUpdate () {
        if (!isLocalPlayer) return;//保證只對本地角色進行控制

        Vector2 moveDir;
        if (Input.GetAxisRaw("Horizontal") == 0 && Input.GetAxisRaw("Vertical") == 0)
        {
            moveDir.x = 0;
            moveDir.y = 0;

        }
        else
        {
            //可以移動
            moveDir.x = Input.GetAxis("Horizontal");
            moveDir.y = Input.GetAxis("Vertical");
            Move(moveDir);
        }

    }
    private void Move(Vector2 direction=default(Vector2))
    {
        if (direction != Vector2.zero)
        {
            //轉方向
            transform.rotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.y));
            //計算前方的點
            Vector3 movementDir = transform.forward * MoveSpeed * Time.deltaTime;
            //移動到這個點
            rb.MovePosition(rb.position + movementDir);
        }
    }
}
9.攝像機跟隨

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

public class CameraFollow : MonoBehaviour {

    public Transform target;
    public float distance = 10f;
    public float height = 5f;

    void Update()
    {
        if (!target) return;

        Quaternion currentRotation = Quaternion.Euler(0, transform.eulerAngles.y, 0);
        Vector3 pos = target.position;//target的坐標
        pos -= currentRotation * Vector3.forward * Mathf.Abs(distance);//距離
        pos.y = target.position.y + Mathf.Abs(height);//高度
        transform.position = pos;

        transform.LookAt(target);
        //下面這一句其實要不要無所謂,只是為了精確
        transform.position = target.position - (transform.forward * Mathf.Abs(distance));
    }
}
在player中重寫生成本地物體時調用的方法,把坦克設置為攝像機的target

 //把攝像機的target用代碼設置為坦克的--這里挺重要的,在OnStartLocalPlayer()方法里面寫
    public override void OnStartLocalPlayer()
    {
        Camera.main.GetComponent<CameraFollow>().target = transform;
    }

 10.炮台的轉動及炮台轉動的同步

 

 [HideInInspector]   //在面板上隱藏公有值
    [SyncVar(hook = "OnTurretRotation")]//turretRotation同步到所有客戶端,並調用OnTurretRotation()方法   
    public int turretRotation;

 l

//把輸入的屏幕坐標轉為ray射線
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        Plane plane = new Plane(Vector3.up, Vector3.up);//虛構的平面
        float distance = 0f;//屏幕寬度
        Vector3 hitPos = Vector3.zero;//設置打擊點,取默認值

        if(plane.Raycast(ray,out distance))
        {
            hitPos = ray.GetPoint(distance) - transform.position;
        }
        RotateTurret(new Vector2(hitPos.x, hitPos.z));

/// <summary>
    /// 炮台旋轉
    /// </summary>
    /// <param name="direction"></param>
    void RotateTurret(Vector2 direction = default(Vector2))
    {
        if (direction == Vector2.zero) return;

        int newRotation = (int)(Quaternion.LookRotation(new Vector3(direction.x, 0, direction.y)).eulerAngles.y);
        turret.rotation = Quaternion.Euler(0, newRotation, 0);

        turretRotation = newRotation;
        
    }

    [Command]
    void CmdRotateTurret(int value)
    {
        turretRotation = value;//調用服務器這個值得改變
    }

    void OnTurretRotation(int value)
    {
        if (isLocalPlayer) return;

        turretRotation = value;
        turret.rotation = Quaternion.Euler(0, turretRotation, 0);//進行旋轉
    }

11.鼠標右鍵轉向

 


免責聲明!

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



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