Unity3D游戏开发从零单排(七) - NetworkView的Demo

提要

今天做了一个移动设备的网络通信demo,分两个部分,一个是网络连接,一个是数据通信。

需要两台Android设备A,B。A作客户端,B作服务端。

最终的效果是玩家控制设备A中的方块,B中的方块也一起动,同时在A的加速度传感器的信息在B中也实时更新。

网络连接

首先两台设备要联网,且IP在同一个网段,比如连接在同一个路由上,或者通过笔记本发出wifi信号,然后把设备连在上面。

在Unity3d中创建一个新工程,在场景中创建两个空物体,一个Client,一个Server。

在client创建一个脚本client.cs

using UnityEngine;
using System.Collections;

public class client : MonoBehaviour {

    private string IP = "10.66.208.191";
    private string clientIp;
    private string clientIpSplite;
    private Vector3 acceleration;
    public GameObject cube;
    private bool cubeInitialed = false;
    //Connet port
    private int Port = 10000;

    void Awake()
    {
        clientIp = Network.player.ipAddress;
        string[] tmpArray = clientIp.Split(‘.‘);
        clientIpSplite = tmpArray[0] + "." + tmpArray[1] + "." + tmpArray[2] + ".";
    }

    void OnGUI()
    {
        switch (Network.peerType)
        {
            case NetworkPeerType.Disconnected:
                StartConnect();
                break;
            case NetworkPeerType.Server:
                break;
            case NetworkPeerType.Client:
                OnConnect();
                break;
            case NetworkPeerType.Connecting:
                break;
        }
    }

    void StartConnect()
    {
        if (GUILayout.Button("Connect Server"))
        {
            NetworkConnectionError error = Network.Connect(IP, Port);
            Debug.Log("connect status:" + error);
        }
    }

    void OnConnect()
    {
        if(!cubeInitialed)
        {
            Network.Instantiate(cube, transform.position, transform.rotation, 0);
            cubeInitialed = true;
        }
    }
}

客户端根据当前当前的状态来执行相应的动作。StartConnect负责连接,用到了

static NetworkConnectionError Connect(string[] IPs, int remotePort)

第一个参数是Ip,第二个参数是端口。

连接上之后调用OnConnect函数初始化一个方块。注意这个方块是在客户端初始化的,属于这个客户端,创建成功之后会在其他的一桶连接的设备上都实例化一个cube出来,但是只有在这个client上NetworkView.isMine才为true。

接下来是服务端的代码。

using UnityEngine;
using System.Collections;

public class server : MonoBehaviour {
    private int serverPort;
    public GUIText status;

    void Awake()
    {
        serverPort = 10000;
    }

  //OnGUI方法,所有GUI的绘制都需要在这个方法中实现
    void OnGUI()
    {
        //Network.peerType是端类型的状态:
        //即disconnected, connecting, server 或 client四种
        switch (Network.peerType)
        {
            //禁止客户端连接运行, 服务器未初始化
            case NetworkPeerType.Disconnected:
                StartServer();
                break;
            //运行于服务器端
            case NetworkPeerType.Server:
                OnServer();
                break;
            //运行于客户端
            case NetworkPeerType.Client:
                break;
            //正在尝试连接到服务器
            case NetworkPeerType.Connecting:
                break;
        }
        GUILayout.Label(Network.player.ipAddress);
    }

    void StartServer()
    {
        //当用户点击按钮的时候为true
        if (GUILayout.Button("创建服务器"))
        {
            //初始化本机服务器端口,第一个参数就是本机接收多少连接
            NetworkConnectionError error = Network.InitializeServer(12, serverPort, false);
            Debug.Log("错误日志" + error);
        }
    }

    void OnServer()
    {
        GUILayout.Label("服务端已经运行,等待客户端连接");
        int length = Network.connections.Length;

        for(int i = 0; i < length; i++)
        {
            GUILayout.Label("客户端" + i);
            GUILayout.Label("客户端ip" + Network.connections[i].ipAddress);
            GUILayout.Label("客户端端口" + Network.connections[i].port);
        }
    }

    void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
{
    // Always send transform (depending on reliability of the network view)
    if (stream.isWriting)
    {
        Vector3 pos = transform.localPosition;
        Quaternion rot = transform.localRotation;
        stream.Serialize(ref pos);
        stream.Serialize(ref rot);
    }
    // When receiving, buffer the information
    else {
        // Receive latest state information
        Vector3 pos = Vector3.zero;
        Quaternion rot = Quaternion.identity;
        stream.Serialize(ref pos);
        stream.Serialize(ref rot);
    }
}
}

点击屏幕上的创建服务器之后就在设备上创建了一个服务端,监听对应的端口,当有其他设备连接上来的时间,客户端的信息就会打印出来,可以支持多个设备的连接。

还要创建一个cube的prefab,用于动态创建。

CubeController用于控制方块的运动,NetWorkView用于数据通信。

数据通信

需要进行数据通信的GameObject都要添加一个NetworkView 组件,数据通信有两种方式,状态同步和RPC(远程过程调用)。在CubeController.cs中,两种方法都有用到。

using UnityEngine;
using System.Collections;

public class CubeController : MonoBehaviour {
    private GUIText accelText;

    void Start()
    {
        accelText = GameObject.FindGameObjectWithTag("AccelTip").GetComponent<GUIText>() as GUIText;
        accelText.text = "";
    }

    void Update()
    {
        if(Network.isClient)
        {
            Vector3 acceleration = Input.acceleration;
            accelText.text = "" + acceleration;
            networkView.RPC("UpdateAcceleration", RPCMode.Others, acceleration);
        }

        Vector3 moveDir = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
        Vector3 cubescreenPos =  Camera.main.WorldToScreenPoint(transform.position);
        if (Input.GetMouseButton(0))
        {
            moveDir = new Vector3(Input.mousePosition.x - cubescreenPos.x, Input.mousePosition.y - cubescreenPos.y, 0f).normalized;
        }
        Debug.Log("moveDir: " + moveDir);
        float speed = 5;
        transform.Translate(speed * moveDir * Time.deltaTime);
    }

    void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
    {
        if (stream.isWriting)
        {
            Vector3 pos = transform.position;
            stream.Serialize(ref pos);
        }
        else
        {
            Vector3 receivedPosition = Vector3.zero;
            stream.Serialize(ref receivedPosition);
            transform.position = receivedPosition;
        }
    }

    [RPC]
    void UpdateAcceleration(Vector3 acceleration)
    {
        accelText.text = "" + acceleration;
    }

}

function OnSerializeNetworkView(stream : BitStream, info : NetworkMessageInfo) {}
这是在Network class中提供的一个func. 主要负责message sent / receive,他会同步被network view所关注的script中的对象,也就是当你写了一个script内含OnSerializeNetworkView(){},并且丢到observed属性中,则OnSerializeNetworkView()裡的code就会开始运作。基本上他透过BitStream物件收发网路上的资讯,使用上不需要了解封包的问题,也不需要知道如何切割封包。在这的demo中,服务端只负责接收信息,所以只执行else后面的代码,客户端发送信息,执行if后面的代码。

这里cube的state synchronization选的是Unreliable,对应的通讯协议是UDP,特点是无连接,比较快。

RPC典型的应用场景就是聊天室,使用也非常简单,首先定义一个rpc函数在(在上面加上[RPC]),然后通过NetWork.RPC来调用就可以了。这里是把客户端重力传感器的数据传了出去,在界面上更新。

参考

unity3D的網路資料傳輸 & 角色控制 - http://ppb440219.blogspot.com/2011/12/unity3d.html

网络视图 Network View - http://game.ceeger.com/Components/class-NetworkView.html

远程过程调用的细节 RPC Details - http://game.ceeger.com/Components/net-RPCDetails.html

状态同步的细节 State Synchronization Detailshttp://game.ceeger.com/Components/net-StateSynchronization.html

Unity Networking Tutorial - http://www.palladiumgames.net/tutorials/unity-networking-tutorial/

Unity3D游戏开发从零单排(七) - NetworkView的Demo

时间: 2024-10-12 18:35:15

Unity3D游戏开发从零单排(七) - NetworkView的Demo的相关文章

Unity3D游戏开发从零单排(六) - 人物运动及攻击连击

提要 今天要实现的是一个简单人物控制器.包括用w,a,s,d来控制人物上下左右跑动,鼠标左击发出连招,都是基于老的lagacy的动画.虽然unity3d自带有charactorcontroller,但是并不是很好用,所以人物控制相关的全部自己来实现.先上效果图: 场景搭建 首先下载这个package,里面包含了人物的动作还有地面的模型.将人物和地面都拖进场景中.这里的模型默认的动画模式是lagacy,不用修改.模型有点偏小,改变模型的scale值为10.最好不要改源文件的scale的scale

Unity3D游戏开发从零单排(五) - 导入CS模型到Unity3D

游戏动画基础 Animation组件 Animation组件是对于老的动画系统来说的. 老的动画形同对应的动画就是clip,每个运动都是一段单独的动画,使用Play()或CrossFade(),直接播放动画 或淡入淡出播放动画. animation.Play("name"); animation.CrossFade("name"); 下面的是它的几个属性 Animation:默认的动画片段: Aniamtions:包含的动画片段: Play Automaticall

Unity3D游戏开发从零单排(四) - 制作一个iOS游戏

提要 此篇是一个国外教程的翻译,虽然有点老,但是适合新手入门.自己去写代码,debug,布置场景,可以收获到很多.游戏邦上已经有前面两部分的译文,这里翻译的是游戏的最后一个部分. 欢迎回来 在第一篇中,我们学会了怎么在Unity中搭建游戏的场景,并且设置模型的物理属性. 在第二篇中,我们学会了怎么在unity中使用脚本,并且创建了大部分的游戏逻辑,包括投球和得分! 在这最后一节中,我们将会为用户创建一个菜单系统,并且和GameController进行交互,我们开始吧. 在设备上测试 到目前为止,

Unity3D游戏开发从零单排(九) - 进击的Shader

提要 今天要学习的是一些Shader 的例子,从简单到难.Let's go. 一大波例子来袭 还是用上一篇用到的工程.点我下载 红色的螃蟹 Test1.shader Shader "Custom/Test1" { SubShader { Tags { "RenderType" = "Opaque" } CGPROGRAM #pragma surface surf Lambert struct Input { float4 color : COLO

Unity3D游戏开发从零单排(三) - 极速创建狂拽酷炫的游戏地形

提要 在Unity工作流程内,地形是一个必不可少的重要元素.不论是游戏或虚拟现实都会使用到各种类型的地形效果,在这个教学中我们须要了解到地形的制作基本概念与,当中对于Unity的地形操作部分须要大量的操作练习.熟悉这些功能操作之后,相信对于游戏地形的制作与运用将会更得心应手. 先看终于效果: 环境:windows7 64bit Unity3d4.2.1 所需资源:terrain.raw 创建project File  ->  New project 选择project存放的位置,同一时候导入 S

Unity3D游戏开发从零单排(八) - Shader基础

提要 今天要说的是Unity3D中shader相关的一些知识.不会做非常细致的讲解(东西实在太多!- -),但是看完之后会知道shader是怎么用的. 一些术语 在shader编程中,有一些术语,有时候不明白的话容易被整懵圈,所以这里就简单提一下. Shading Shading最开始指的在素描中给物体画明暗调子,在图形学中,其实就是给Mesh上色(Mesh就是一堆三角面片,包含顶点左边,法线坐标,uv坐标之类的),wiki中说的是根据物体相对于光线的角度及其距离光源距离改变物体颜色生成phot

Unity3D游戏开发从零单排(十) - 进击的Shader续

自定义光照模型 在这之前首先来了解一下SurfaceOutput这个结构体,它是一个包含大多数描述一个物体表面渲染特征的结构,具体结构如下: struct SurfaceOutput { half3 Albedo;//纹理颜色 half3 Normal;//法线 half3 Emission;//自发光,不受照明的影响 half Specular;//高光指数 half Gloss;//光泽度 half Alpha;//Alpha通道 }; 基本上所有的Shader函数要处理的就是这个结构体.

零基础unity3d游戏开发系列目录

零基础Unity3D游戏开发系列 第一章:游戏开发与游戏引擎(一) 零基础Unity3D游戏开发系列 第一章:游戏开发与游戏引擎(二) 零基础Unity3D游戏开发系列 第二章:Unity3D概览(一)界面... 零基础Unity3D游戏开发系列 第二章:Unity3D概览(一)创建与打开项目I 零基础unity3d游戏开发系列 第二章:unity3d概览(一)创建与打开项目II 零基础Unity3D游戏开发系列 第二章:Unity3D概览(一)创建与打开项目III 零基础Unity3D游戏开发

Unity3D游戏开发初探—2.初步了解3D模型基础

一.什么是3D模型? 1.1 3D模型概述 简而言之,3D模型就是三维的.立体的模型,D是英文Dimensions的缩写. 3D模型也可以说是用3Ds MAX建造的立体模型,包括各种建筑.人物.植被.机械等等,比如一个大楼的3D模型图.3D模型也包括玩具和电脑模型领域. 互联网的形态一直以来都是2D模式的,但是随着3D技术的不断进步,在未来的时间里,将会有越来越多的互联网应用以3D的方式呈现给用户,包括网络视讯.电子阅读.网络游戏.虚拟社区.电子商务.远程教育等等.甚至对于旅游业,3D互联网也能