需求来自一个同事的朋友的英国博士课题研究
最终的形态希望是一个在线的网站,3d展厅,用户可以在里面自由探索,分不同的区域,区域中会因为人数的不同导致bgm速度的变化,探索建筑中声音对人的影响
项目由三个部分构成

  • unity前端
  • dotnet服务端
  • 后台监控前端

unity前端

image.png
这是模型效果,甲方从商店购买的
屏幕截图 20210918 153250.png
用透明的cube来做区域的划分,通过给cube加上脚本识别OnTriggerStay和OnTriggerExit来做此区域声音的控制
image.png
image.png
给npc和玩家增加collider
主角控制用到了unity的Standard Assets里的FPSController
用了bestHTTP库的websocket来做和服务端的通信,在update里每一秒向server发送一次自身位置旋转以及id之类的信息

    public class PlayerInfo
    {
        public string id { set; get; }
        public string name { set; get; }
        public string x { set; get; }
        public string y { set; get; }
        public string z { set; get; }
        
        public string diffVector2 { set; get; }
        
        public string rotationX { set; get; }
        public string rotationY { set; get; }
        public string rotationZ { set; get; }
        
    }

在webgl环境中LitJson不能解析浮点型属性,所以都用string来做属性类型
同时会读取由websocket传过来的所有玩家的信息集合缓存,并操作场景中对应的其他玩家,如果有新的玩家数据会创建相应的玩家,如果有玩家离线会做相应的销毁,并更新场景中玩家的位置和方向

血条展示

一开始用的是在模型的预制体里增加头顶的文字,要做方向朝向,非常麻烦,性能也很差,后来用Canvas方案来做

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

public class NameBar : MonoBehaviour {

    public Canvas Canvas;
    private GameObject FollowTarget; // 血条跟踪的对象
    private RectTransform textRectTransform;
    private float m_ObjectHeight;
    public GameObject bar;
    private Text _text;
    public string ShowName = string.Empty;

    void Start()
    {
        Debug.Log($"namebarStart {Canvas == null}");
        if (Canvas == null) Debug.LogError("Please set a canvas for health bar.");
        FollowTarget = gameObject;
        bar = Instantiate(bar, Canvas.transform, true);
        // bar = Instantiate(Resources.Load<GameObject>("Prefabs/nameText"), Canvas.transform, true);
        Debug.Log($"setname:");
        _text = bar.GetComponent<Text>();
        _text.text = ShowName;
        textRectTransform = _text.transform as RectTransform;
        // 获取物体高度 https://blog.csdn.net/haobaworenle/article/details/53898221
        m_ObjectHeight = FollowTarget.GetComponent<MeshRenderer>().bounds.size.y;
        Debug.Log("object height." + m_ObjectHeight);
    }

    void Update()
    {
        UpdateHealthBarPosition();
    }

    private void LateUpdate()
    {
    }

    void UpdateHealthBarPosition()
    {
        Vector3 worldPosition = new Vector3(FollowTarget.transform.position.x, 
            FollowTarget.transform.position.y + m_ObjectHeight, FollowTarget.transform.position.z);
        // 根据NPC头顶的3D坐标换算成它在2D屏幕中的坐标
        Vector2 position = Camera.main.WorldToScreenPoint(worldPosition);
        position.y += 185;
        Debug.Log($"UpdateHealthBarPosition {position}");
        textRectTransform.position = position;
    }

    private void OnBecameInvisible()
    {
        Debug.Log("OnBecameInvisible");
        bar.SetActive(false);
    }

    private void OnBecameVisible()
    {
        Debug.Log("OnBecameVisible");
        bar.SetActive(true);
    }
}

一开始没有优化模型贴图的概念,导致打出来的webgl包特别大,每次打包也非常久,降低了贴图的质量,并在光线的处理上有了新的心得,接受光源的物体上可以设置接受光源的参数,还有光源也可以一起来设置阴影,可以控制影子的出现,然后就是collider的使用了

dotnet服务端

主业务Server

用了Fleck这个库做websocket server
websocket会在每一条json数据的第一位增加一个协议位,收到client上线后会分配一个id并下发,收到client的update消息后会放到player缓存中,并通过DBServer插入mongodb,每一秒有一个定时任务做广播所有玩家信息。

DBServer

主要就一个插入和查询,通过提供方法给DashboardServer间接提供数据给后台

DashboardServer

单独令起一个websocket server 用来实时刷新后台web上的数据

后台监控前端

比较简单,就一个实时展示各个区域的人数和玩家进出区域的日志
用g2.js展示了图表

docker-compose file

version: '3'

services:
  unity-webgl-httpd:
    image: httpd
    privileged: true
    container_name: unity-webgl-httpd
    ports:
     - "8089:80"
    volumes:
     - /root/lam/work/unity-webgl-httpd/website/:/usr/local/apache2/htdocs/
  unity-webgl-dotnet:
    image: mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim
    privileged: true
    container_name: unity-webgl-dotnet
    ports:
     - "8171:8181"
     - "8172:8182"
    volumes:
     - /root/lam/work/unity-webgl-dotnet/:/root/works/
    command: /bin/bash -c "dotnet /root/works/server.dll"
    tty: true
  unity-webgl-mongodb:
    image: mongo:3.2.20
    #-------------------------------------------------------------------------------------
    container_name: unity-webgl-mongodb
    #restart: always
    command: mongod --smallfiles --oplogSize 128
    environment:
       - MONGO_INITDB_ROOT_USERNAME=root
       - MONGO_INITDB_ROOT_PASSWORD=lam
    ports:
      - 27017:27017
    expose:
      - 27017
    volumes:
      - /root/lam/work/unity-webgl-mongodb/data:/data/db
      - /root/lam/work/unity-webgl-mongodb/dump:/dump
打赏
支付宝 微信
上一篇 下一篇