public class ctrl : MonoBehaviour
{
[SerializeField]
PostProcessVolume m_postpVol;
[SerializeField]
Camera m_Cam;
DepthOfField m_Df;
void Awake()
{
m_postpVol.profile.TryGetSettings(out m_Df);
}
//焦距设置为摄像机和玩家的位置
void Update()
{
m_Df.focusDistance.value = Vector3.Distance(Player.position, m_Cam.transform.position);
}
}
将unity缓存三个文件夹
C:\Users\你用户名\AppData\Local\Unity
C:\Users\你用户名\AppData\LocalLow\Unity
C:\Users\你用户名\AppData\Roaming\Unity
分别拷贝到 别的盘符,如
F:\UnityCache\LocalUnity
F:\UnityCache\LocalLowUnity
F:\UnityCache\RoaMingUnity
删除源文件夹,添加软链接
mklink /j C:\Users\你用户名\AppData\Local\Unity F:\UnityCache\LocalUnity
mklink /j C:\Users\你用户名\AppData\LocalLow\Unity F:\UnityCache\LocalLowUnity
mklink /j C:\Users\你用户名\AppData\Roaming\Unity F:\UnityCache\RoaMingUnity
管理员身份运行CMD,并执行, 结果:
Microsoft Windows [版本 10.0.19044.1706]
(c) Microsoft Corporation。保留所有权利。
C:\Users\Admin>mklink /j C:\Users\Admin\AppData\Local\Unity F:\UnityCache\LocalUnity
为 C:\Users\Admin\AppData\Local\Unity <<===>> F:\UnityCache\LocalUnity 创建的联接
C:\Users\Admin>mklink /j C:\Users\Admin\AppData\LocalLow\Unity F:\UnityCache\LocalLowUnity
为 C:\Users\Admin\AppData\LocalLow\Unity <<===>> F:\UnityCache\LocalLowUnity 创建的联接
C:\Users\Admin>mklink /j C:\Users\Admin\AppData\Roaming\Unity F:\UnityCache\RoaMingUnity
为 C:\Users\Admin\AppData\Roaming\Unity <<===>> F:\UnityCac
我写一个简单明了的范例
比如我们要同步一个V3类型的数据,
数据来源:客户端操作
目标:同步所有客户端的 Vector3 V3FromNetwork 变量值
本地客户端客户端(isLocalPlayer为true)进行操作
↓↓↓
调用[Command]修饰的方法SetTestV3,(SetTestV3就具备了往服务器上报的特性)
↓↓↓
服务器执行SetTestV3函数内容
↓↓↓
服务器修改TestV3值时,由于具备标识[SyncVar(hook = nameof(ChangeTestV3))],通知所有客户端的该对象脚本中调用ChangeTestV3
↓↓↓
客户端调用ChangeTestV3,最终成功修改到值。
代码如下
using UnityEngine;
using Mirror;
public class Player : NetworkBehaviour
{
void Update()
{
if (!isLocalPlayer) return;//只操作本地客户端
Vector3 V3SendData = new Vector3(Input.GetAxis("Vertical") * Time.deltaTime, 0, Input.GetAxis("Horizontal") * Time.deltaTime);
SetTestV3(V3SendData);
}
[Command]//客户端上行标识
public void SetTestV3(Vector3 v)
{
//服务端执行内容
TestV3 = v;
}
[SyncVar(hook = nameof(ChangeTestV3))]//服务端修改触发客户端调用hook函数
public Vector3 TestV3 = Vector3.zero;
public void ChangeTestV3(Vector3 oldv, Vector3 newc)
{
//客户端执行内容
标签: Command 从客户端发送到服务器,服务器执行
[Command]
void ABC(){}
注意点
1,方法可以带参数,但需要序列化
2,客户端只能发送属于自己的对象的方法
如果都允许,则设置为不验证:
[Command(requiresAuthority = false)]
标签: ClientRpc 从服务器发送到,客户端执行
[ClientRpc]
void ABC(){}
标签: TargetRpc 从服务器发送到,指定的客户端执行
[TargetRpc]
void TargetRemoteDamaged(NetworkConnection target, int damage){}
PS:第一个参数可忽略,默认发给自己,也就是调用此方法的客户端实体
PS:如果第一个参数有,则发给指定,目标
[Command] 由客户端调用,内容服务器执行;
[ClientRpc]和[TargetRpc]由服务器调用,内容客户端执行;
但[TargetRpc]是指定目标发送,[ClientRpc]是都发送。
一,用SyncVar进行同步
函数标签[SyncVar]
用标签来标记变量,被改变时时,同步给其他客户端;
可指定Hook指定回调函数,并返回旧值和新值
如:
[SyncVar(hook = nameof(ChangeColor))]
Color pcolor = Color.white;
void ChangeColor(Color oldc, Color newc)
{
}
即pcolor发生变化时,客户端都调用ChangeColor
PS:使用此特性标注的变量,只应该在服务器上对此变量进行更改,而通过hook在客户端作用此更改
然后hook,仅会再客户端调用,如果服务器是OnlyServer模式则不会调用
使用脚本让服务器控制所有客户端颜色变化的代码
using UnityEngine;
using Mirror;
public class PlayerController : NetworkBehaviour
{
[SyncVar(hook = nameof(ChangeColor))]
Color pcolor = Color.white;
Rigidbody rb;
MaterialPropertyBlock prop;
/// <summary>
/// 客户端收到同步时调用
/// </summary>
/// <param name="oldc"></param>
/// <param name="newc"></param>
void ChangeColor(Color oldc, Color newc)
{
Debug.Log("更新为新颜色");
prop.SetColor("_Color", newc);
GetComponent<Renderer>().SetPropertyBlock(prop);
}
private void Awake()
{
rb = GetComponent<Rigidbody>();
prop = new MaterialPropert
个人理解的两种方式
Offline,Room,GamePlay
作用:区分Online和非Online模式
通过create->mirror 创建如下脚本
[NetworkRoomManager]
作用:房间管理,有房间创建,连接,等房间相关的回调
基于房间补充相关逻辑
[NetworkRoomPlayer]
作用:包含房间里的玩家状态和回调
[NetworkBehaviour]
创建多个NetworkBehaviour :
如,NetworkBehaviour 改为 myPlayer
NetworkBehaviour 改为 myItem
作用: 有了本脚本,才会标记告知服务器需要同步本对象
继承了MonoBehaviour的Network脚本,
可以衔接Update等函数书写自己的逻辑,
取到玩家网络状态,如
isServer
如果是此对象是在服务器上运行的(包括服务器+客户端一体的主机),则返回true
isServerOnly
如果是此对象仅在服务器运行的(而非包含客户端的主机),则返回true
isClient
如果此对象已经存在,且处于客户端上(包括主机的客户端),则返回true
等等
创建空物体,命名为RoomPlayer,挂MyNetworkRoomPlayer
创建胶囊,命名为Player,挂MyPlayer
创建Cube, 命名为Item 挂myItem
客户端操作权限:
Player预制体上的挂NetworkTransform脚本的ClientAuthority 一定要勾选上,否则没有客户端操作其状态的权限。
在玩家或者我物体预制体上挂载,NetworkIdentity 脚本
(往往挂载其他Mirror脚本时,NetworkIdentity脚本会自动挂载)
1.在Offline场景空物体,挂MyNetworkRoomManager脚本
挂载好在线和离线对应的场景,Player预制体,以及房间相关的预制体和场景
2.同时
比起 Unity集成的Navigation中的OffMeshLink,扩展的NavMeshComponents中NavMeshLink,会强大好用许多,
·比起 Unity集成的Navigation ,扩展的NavMeshComponents,扩展了不少方便的功能
比如同一个场景,更方便的创建不同的烘培网格
拷贝Github克隆的Asset中NavMeshComponents目录到你的项目Asset
创建一个场景,
然后在场景根节点下 挂载脚本提供的NavMeshSurface.cs
而且可以挂载多个
打开Agent 设置
设置不同体型的宽高配置
然后回到地形对象的Inspector面板,选择不同的配置
分别点击Bake,进行烘培得到两个不同的结果
此外还可以选择渲染的layer层级,
或者你也可以选择渲染范围:
然后就是移动了
创建两个玩家胶囊提
分别创建寻路导航代理组件
挂载移动脚本到两个player胶囊提上
public class Player : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
private NavMeshAgent agent;
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
agent.SetDestination(hit.point);
}
}
}
}
鼠标控制移动,两个角色则会走对应体型配置的烘培寻路
unity各类压缩方式性能探究,陈皓2020-12-24
版本:2019.2.6
打包对象:角色“白民“预制体
相关记录:
打包时间:包含依赖资源自动查找时间,(性能差异应关注秒级以下时间!)
读取时间包含:AssetBundleCreateRequest,AssetBundle,AssetBundleRequest 流程的时间
Unity读取机制:不压缩或者LZMA格式,在unity加载后内存中会处理成LZ4
压缩方式 大小 打包处理时间(s) 读取时间(x)
————————————————————————————
不压缩 1622k 13.3640811 0.5399647
13.5700311 0.5609903
13.5495395 0.6687141
unity-LZ4 948k 13.7928144 0.5434550
13.6893117 0.5586369
13.7192026 0.5431827
unity-LZMA 689k 14.7435645 0.8226537
14.0434290 0.7473594
14.9094666 0.8506351
外部压缩方式,7zip,zip待测
抛开Unity本身流程,打包时间减去10秒左右,读取减去0.4秒左右,分析,
得:
1,一般场景:
直接使用LZ4比较合适,不明显影响加载速度的情况下,容量还是可以减少40%。
2,网络下载场景:
使用LZMA文件更小,减少传输量,提升下载速度。影响加载速度。
3,思考,同时兼顾传输量小和加载速度的方案:
AB包不使用Unity内部压缩,或者仅使用LZ4。保证加载速度。
AB包打包后使用外部类库(7zip),进行进行高压。传至文件服务器。文件传输显著减少。
由更新器下载后在缓存中解压高压文件,释放出压缩率底的文件到StreamA