需求来自一个同事的朋友的英国博士课题研究
最终的形态希望是一个在线的网站,3d展厅,用户可以在里面自由探索,分不同的区域,区域中会因为人数的不同导致bgm速度的变化,探索建筑中声音对人的影响
项目由三个部分构成
- unity前端
- dotnet服务端
- 后台监控前端
unity前端
这是模型效果,甲方从商店购买的
用透明的cube来做区域的划分,通过给cube加上脚本识别OnTriggerStay和OnTriggerExit来做此区域声音的控制
给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

