2014-12-10 16:33:53 operhero1990 阅读数 3804
  • VR局域网对战【捕鱼猎手】实战视频教程(上)

    这是一个项目工程实现全过程的细致讲解,按功能划分成单元,每一个单元逐一完成,老师细致的讲解和分析,学员和老师同步完成这个项目工程。这个项目工程包含VR、数据库、注册用户、声望系统、拍卖行系统等等,还有充值系统, 本课程中的游戏项目采用新的Unity3D 2017版本制作。

    857 人正在学习 去看看 杨显峰

Unity3d局域网PVP系统主要用来实现局域网对战功能,玩家可以建立自己的主机,其他玩家可以访问到该主机并使用RPC进行数据传输。

建立LANPVPMng.cs脚本来实现以下功能:

1、玩家建立局域网主机;

2、玩家搜索局域网其他玩家建立的主机;

3、玩家与玩家建立连接,进行数据传递。

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

public class LANPVPMng : MonoBehaviour
{

    /// <summary>
    /// 最大连接数,默认为1
    /// </summary>
    public int MaxConnetions = 1;

    /// <summary>
    /// 端口号,默认为25002
    /// </summary>
    public int Port = 25002;

    /// <summary>
    /// 接受的数据
    /// </summary>
    public byte[] RecievedMsg
    {
        get
        {
            return m_recvMsg;
        }
    }

    /// <summary>
    /// 新消息事件
    /// </summary>
    public event NewMessageHandle NewMsgEvent;

    private byte[] m_recvMsg = new byte[0];
    Dictionary<string, HostData> m_host = new Dictionary<string, HostData>();
    List<string> m_hostName = new List<string>();
    HostData m_connectedHost = null;
    bool m_isfresh = true;
    bool m_isConnected = false;

    void Awake()
    {
        gameObject.AddComponent<NetworkView>();
    }

    void LateUpdate()
    {
        if (MasterServer.PollHostList().Length != 0 && m_isfresh == true)
        {
            HostData[] hostData = MasterServer.PollHostList();
            m_hostName.Clear();
            m_host = new Dictionary<string, HostData>();

            foreach (HostData h in hostData)
            {
                if (h.connectedPlayers == 1)
                {
                    m_host.Add(h.gameName, h);
                    m_hostName.Add(h.gameName);
                }
            }
            m_isfresh = false;
        }
    }

    //从列表中清除已经连接的主机
    //void FixedUpdate()
    //{
    //    //只有在没连接的时候才更新
    //    if (!m_isConnected)
    //    {
    //        for (int i = 0; i < m_hostName.Count; )
    //        {
    //            if (m_host[m_hostName[i]].connectedPlayers > 1)
    //            {
    //                m_host.Remove(m_hostName[i]);
    //                m_hostName.Remove(m_hostName[i]);
    //            }
    //            else
    //            {
    //                i++;
    //            }
    //        }
    //    }
    //}

    /// <summary>
    /// 创建主机
    /// </summary>
    /// <param name="hostName">创建的主机名</param>
    public bool CreateHostWithName(string hostName)
    {
        if (Network.peerType == NetworkPeerType.Server)
        {
            Disconnect();
        }

        if (Network.peerType == NetworkPeerType.Disconnected)
        {
            bool useNat = !Network.HavePublicAddress();
            Network.InitializeServer(MaxConnetions, Port, useNat);
            MasterServer.RegisterHost("battle", hostName, "");
            return true;
        }
        return false;
    }
  
    /// <summary>
    /// 刷新主机列表
    /// </summary>
    public void Refresh()
    {
        MasterServer.ClearHostList();
        MasterServer.RequestHostList("battle");
        m_host = null;
        m_isfresh = true;

    }

    /// <summary>
    /// 获得主机名序列,如果要获得最新的,需要调用ReFresh函数刷新
    /// </summary>
    public List<string> GetHostName()
    {
        return m_hostName;
    }

    /// <summary>
    /// 连接主机
    /// </summary>
    /// <param name="hostName">要连接的主机名</param>
    public void ConnectToHost(string hostName)
    {
        if (m_host.ContainsKey(hostName) && m_host[hostName].connectedPlayers == 1)
        {
            Network.Connect(m_host[hostName]);
            m_connectedHost = m_host[hostName];
            m_isConnected = true;
        }
    }

    /// <summary>
    /// 断线重连
    /// </summary>
    public void ReConnectToLastHost()
    {
        if (m_connectedHost != null)
        {
            Network.Connect(m_connectedHost);
        }
    }

    /// <summary>
    /// 发送数据
    /// </summary>
    /// <param name="msg">byte数组</param>
    public void SendData(byte[] data)
    {
        networkView.RPC("SomeoneSay", RPCMode.Others, data);
    }

    /// <summary>
    /// 断开连接
    /// </summary>
    public void Disconnect()
    {
        Network.Disconnect(200);
        m_isConnected = false;
    }

    /// <summary>
    /// 判断是否连接到其他主机
    /// </summary>
    public bool IsConnected()
    {
        if (Network.isClient||Network.isServer)
        {
            return true;
        }
        return false;
    }

    /// <summary>
    /// 新消息事件委托函数
    /// </summary>
    /// <param name="msg"></param>
    public delegate void NewMessageHandle(byte[] msg);

    //RPC function to receive your message!
    [RPC]
    void SomeoneSay(byte[] data, NetworkMessageInfo info)
    {
        m_recvMsg = data;
        NewMsgEvent(m_recvMsg);
    }
}

Awake()函数将绑定端口监听组件,注意:

1、玩家建立的主机名必须唯一,主机名以参数形式传入,可使用玩家ID或玩家IP地址等等;
2、每个主机只允许一个玩家连入;
3、搜索局域网主机时,要及时调用Refresh()函数,否则无法显示最新主机列表;
4、LANPVPMng.RecievedMsg只保留最新传递的数据,目前没有提供历史记录功能。RPC接收到新的消息时,会触发事件NewMsgEvent,上层可通过加载NewMsgEvent事件来获得及时消息更新。

成员变量与成员函数说明列表:

成员变量:
public int MaxConnetions = 1; 主机最大连接数,默认为1,只允许一个其他玩家连接
public int Port = 25002; 端口号,默认为25002
public byte[] RecievedMsg; 接收到的数据,只读
public bool IsConnected 是否连接到其他主机
public event NewMessageHandle NewMsgEvent; 消息事件,每次RPC函数调用时触发

成员函数:
public bool CreateHostWithName(string hostName) 创建主机
public void Refresh() 刷新主机列表
public List<string> GetHostName() 获得主机名序列
public void ConnectToHost(string hostName) 连接到主机
public void ReConnectToLastHost() 断线重连
public void SendData(byte[] data) 发送数据
public void Disconnect() 断开连接
public bool IsConnected() 是否连接到其他主机
public delegate void NewMessageHandle(byte[] msg) 消息处理委托函数


2017-07-16 10:55:33 qq_34185630 阅读数 3715
  • VR局域网对战【捕鱼猎手】实战视频教程(上)

    这是一个项目工程实现全过程的细致讲解,按功能划分成单元,每一个单元逐一完成,老师细致的讲解和分析,学员和老师同步完成这个项目工程。这个项目工程包含VR、数据库、注册用户、声望系统、拍卖行系统等等,还有充值系统, 本课程中的游戏项目采用新的Unity3D 2017版本制作。

    857 人正在学习 去看看 杨显峰

今天看了SIKI老师的局域网多人联机小游戏,记录下:

首先新建GameObject,添加NetworkManager组件和NetworkManagerHUD组件。

1.NetworkManager:Spawn Info->PlayerPrefab可放置prefab,在客户端运行时自动生成玩家。可以添加在Server生成的prefab,如敌人,子弹等。

NetworkManagerHUD:为相关GUI界面,新建客户端,链接客户端等。

2.新建Player预置物体:添加控制移动,和发射子弹的脚本

[Command]//客户端调用,服务器端生成。
private void CmdFire()//方法要以Cmd开头
{
	GameObject bullet = Instantite(bullt,bulttransform.position,bulttiansform.rotation) as GameObject;//在枪杆的位置生成子弹。
	bullet.GetCompoonent<Rigibody>().velocity = bullet.transform.forward*10;//让子弹的速度10m/s
	Destroy(bullet,2.0f);//2秒后销毁
	NetWorkServer.Spawn(bullet);//在所有客户端生成该物体
}
override void OnStartLocalPlayer()//用override重写方法
{
	GetComponent<Render>().material.color=Color.red;
}

Player预置物体需要添加,NetworkTransform组件,同步位移。子弹需要同步刚体。


3.给Player添加血量和血条

添加UI->slider,做血条,去掉handle,将值Slider.value改为1,background改为红色,fill改为绿色,用作满血状态。

using UnityEngine.Networking;
public class Health:NetworkBeHaviour{
	public const maxhealth=100;
	[SyncVar (hook="onChangehealth")]//添加特性,同步变量,利用hook属性,当currenthealth值发生变化时,执行onChangehealth
	public int currunthealth = maxhealth;
    	public Slider healthslider;
    	public bool destrotondeth=false;
   	 // Use this for initialization
   	 public void takedamage(int damage)
    	{
    	    if (isServer == false) return;
    	    if (currunthealth <= 0)
       	 {
     	       if (destrotondeth)//敌人为真,如果为真,则销毁物体,返回
        	   {
          	      Destroy(gameObject);
        	        return;
         	   }
        	    currunthealth = 100;
            Debug.Log("Death");
            Rpcrebirth();
        }
        
        currunthealth -= damage;


    }
    void onChangehealth(int health)
    {
        healthslider.value = (float)health / maxhealth;//控制血条
    }
    [ClientRpc]//在所有客户端调用,方法名字用Rpc做前缀
    void Rpcrebirth()
    {
        if (isLocalPlayer == false) return;//如果不是本地的角色,ruturn
        transform.position = Vector3.zero;
    }
}
}


2015-03-07 20:36:41 u013825128 阅读数 1479
  • VR局域网对战【捕鱼猎手】实战视频教程(上)

    这是一个项目工程实现全过程的细致讲解,按功能划分成单元,每一个单元逐一完成,老师细致的讲解和分析,学员和老师同步完成这个项目工程。这个项目工程包含VR、数据库、注册用户、声望系统、拍卖行系统等等,还有充值系统, 本课程中的游戏项目采用新的Unity3D 2017版本制作。

    857 人正在学习 去看看 杨显峰
network使用示例


public int connections = 10;
    public int listenPort = 8899;
    public bool useNat = false;
    public string ip = "127.0.0.1";
    public GameObject playerPrefab;


    void OnGUI()
    {
        if (Network.peerType == NetworkPeerType.Disconnected)
        {
            if (GUILayout.Button("创建服务器"))
            {
                NetworkConnectionError error = Network.InitializeServer(connections, listenPort, useNat);


            }
            if (GUILayout.Button("连接服务器"))
            {
                NetworkConnectionError error = Network.Connect(ip, listenPort);
            }
        }
        else if(Network.peerType==NetworkPeerType.Server)
        {
            GUILayout.Label("服务器创建完成");
        }
        else if (Network.peerType == NetworkPeerType.Client)
        {
            GUILayout.Label("客户端已接入");
        }
    }


    void OnServerInitialized()
    {
        print("服务器完成初始化");
        int group= int.Parse(Network.player+"");
        Network.Instantiate(playerPrefab, new Vector3(0, 2, 0), Quaternion.identity, group);
    }


    void OnPlayerConnected(NetworkPlayer player)
    {
        print("一个客户端连接过来,Index:"+player);
    }


    void OnConnectedToServer()
    {
        print("我成功连接到服务器");
        int group = int.Parse(Network.player + "");
        Network.Instantiate(playerPrefab, new Vector3(0, 2, 0), Quaternion.identity, group);
    }

角色在局域网下的控制
判断NetWorkPlayer 控制自己的角色
通过networkview.RPC("方法名”,RPCMode,network.player)远程调用通知游戏体
判断是否可控,并控制游戏体





network view 组件用来在局域网之内去同步一个游戏物体的组件属性

network view 会把创建出来的它的客户端作为主人

说白了就是谁创建的它 它就受谁控制

只有它的主人可以同步它的数据

2018-03-14 16:19:00 qq_30454411 阅读数 594
  • VR局域网对战【捕鱼猎手】实战视频教程(上)

    这是一个项目工程实现全过程的细致讲解,按功能划分成单元,每一个单元逐一完成,老师细致的讲解和分析,学员和老师同步完成这个项目工程。这个项目工程包含VR、数据库、注册用户、声望系统、拍卖行系统等等,还有充值系统, 本课程中的游戏项目采用新的Unity3D 2017版本制作。

    857 人正在学习 去看看 杨显峰

继续上篇博客,我们已经可以发射子弹并让角色受到伤害了。现在我们创建一些“炮灰”。使用Player进行修改外观, 
这里写图片描述 
取名为Enemy,做成Prefab。是不是有点小混混的感觉。。 
在场景中新建一个空物体,重命名为EnemySpawn,作为炮灰孵化器,用来生产炮灰。现在我们生产炮灰,这个炮灰需要在服务端生成,并且同步到客户端端。修改Network Manager 
这里写图片描述 
给EnemySpawn添加Network Identity组件,勾选Server Only表示只有服务端有权限。在给他添加EnemySpawn脚本并编辑:

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

public class EnemySpawn : NetworkBehaviour {
    public GameObject enemyPre;  //用来得到炮灰这个物体
    public int enemyCount = 6;   //定义要生成的炮灰的数量

    //NetworkBehaviour 的内置方法,当服务器启动时调用
    public override void OnStartServer()
    {
        for (int i = 0; i < enemyCount; i ++)
        {
            //给要生产的炮灰一个随机位置,高度不变
            Vector3 ePosition = new Vector3(Random.Range(-8f, 8f), 0, Random.Range(-8f, 8f));
            //给他一个方向,就是围绕Y轴旋转,其他不变
            //Quaternion.Euler:把一个旋转转成四元素
            Quaternion eRotation = Quaternion.Euler(0, Random.Range(0f, 360f), 0);
            //实例化出这个炮灰
            GameObject enemy = Instantiate(enemyPre, ePosition, eRotation) as GameObject;

            NetworkServer.Spawn(enemy);   //在每个客户端上都生成一个物体
        }
    }
}

效果: 
这里写图片描述 
如果看不清的话,可以修改一下摄像机的位置。。 
现在是能正常运行的,但是,攻击炮灰它并不会消失,现在就让他会消失。编辑Health类,这里要修改的代码比较少,我就直接贴图,大家修改对应的地方就行了: 
这里写图片描述

这里写图片描述

注意:这里需要选中Enemy这个Prefab勾选destroyOnDeath 
这里写图片描述

现在就可以正常消灭炮灰了 
这里写图片描述

最后,我们在场景中添加两个空物体,位置不要一样,分开一点。名字取为:Network Start Position1和Network Start Position2.都给他们添加Network Start Position这个组件。因为他们身上有这个组件,Network Manager会得到这两个东西。修改 Network Manager 
这里写图片描述 
就是挨着这两个位置依次生成,现在控制角色重生时随机在这两个点的位置上,修改Health类:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.Networking;

public class Health : NetworkBehaviour {
    public const int maxHealth = 100;   //最大血量
    //检测一个属性,当服务端改变值时,会同步到客户端
    //当值改变时,会调用一个方法 如:OnChangeHealth
    [SyncVar(hook = "OnChangeHealth")]   
    public int currentHealth = maxHealth;   //当前血量
    public Slider healthSlider;

    public bool destroyOnDeath = false;   //用来判断该不该销毁该物体
    private NetworkStartPosition[] spawnPoints;   //得到这个 NetworkStartPosition 组件

    void Start ()
    {
        if (isLocalPlayer)    //如果是客户端
        {
            spawnPoints = FindObjectsOfType<NetworkStartPosition>();
        }
    }

    //当玩家和子弹碰撞时调用的方法
    public void TakeDamage(int damage)
    {
        if (!isServer)   //如果不是服务端
        {
            return;
        }
        currentHealth -= damage;
        if (currentHealth <= 0)   //如果当前血量小于等于0   
        {
            if (destroyOnDeath)    //判断是不是可以销毁的对象
            {
                Destroy(gameObject);
                return;
            }
            currentHealth = maxHealth;    //就让他回复满血状态,方便后面我们让他重生时需要
            RpcRespawn();     //调用一个方法,设置重生的位置
        }

    }

    //当服务端检测的属性值改变时调用的方法
    //health:改变后的值
    void OnChangeHealth (int health)
    {
        healthSlider.value = (float)health / maxHealth;    //修改Slider的比例
    }

    //远程调用,表示调用这个方法时就会在客户端调用,方法名必须以Rpc开头
    [ClientRpc]   
    void RpcRespawn()
    {
        if (!isLocalPlayer)
        {
            return;
        }

        Vector3 spawnPosition = Vector3.zero;
        if (spawnPoints != null && spawnPoints.Length > 0)
        {
            //随机获取NetworkStartPosition数组中的一个,在得到它的位置
            spawnPosition = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
        }
        transform.position = spawnPosition;  
    }
}

现在运行就能获得效果了。当角色生成时会在设置的两个点上依次生成,而当它重生时,会随机在两个点上生成。 

https://pan.lanzou.com/i0ni09a
EXE文件
https://pan.lanzou.com/i0nnz1c



2013-02-24 10:40:36 shengfanger 阅读数 4279
  • VR局域网对战【捕鱼猎手】实战视频教程(上)

    这是一个项目工程实现全过程的细致讲解,按功能划分成单元,每一个单元逐一完成,老师细致的讲解和分析,学员和老师同步完成这个项目工程。这个项目工程包含VR、数据库、注册用户、声望系统、拍卖行系统等等,还有充值系统, 本课程中的游戏项目采用新的Unity3D 2017版本制作。

    857 人正在学习 去看看 杨显峰

1.log输出和unity3d Exception输出

打开Develpment Build和Script Debugging

可以精确到哪个文件哪一行

命令:adb logcat -s Unity


2.profiler

方法1:使用unity3d的profiler

adb forward tcp:54999 localabstract:Unity-<insert bundle identifier here>

    连接目标程序。

编译选项Development Build打开

adb devices:查看是否连接了目标设备。

方法2:使用logcat输出profiler

打开 Enable 'logcat' Profiler

没有更多推荐了,返回首页