• 【坦克大战】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.鼠标右键转向

    我爱学习,学习使我快乐。
  • 相关阅读:
    (4.38)sql server中的事务控制及try cache错误处理
    (4.37)sql server中的系统函数
    【3.5】mysql常用开发规则30条
    Linux学习笔记(17)Linux防火墙配置详解
    (5.16)mysql高可用系列——keepalived+mysql双主ha
    mysql online DDL
    (5.3.8)sql server升级打补丁
    python request
    python 模块被引用多次但是里面的全局表达式总共只会执行一次
    Protocol Buffer Basics: Python
  • 原文地址:https://www.cnblogs.com/kerven/p/8325241.html
Copyright © 2020-2023  润新知