Camera.Main问题

camera.main是个静态属性,用起来好用,但是其中内部使用的是GameObject.FindGameObjectWithTag`

所以再Update或者经常使用这个函数的地方需要注意。

​ 这个问题也直接导致了UGUI相关的耗时,在Canvas Renderer modes使用Screen Space-Camera或者World Space的时候如果要获取相机使用内部函数也会导致一些问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace UnityEngine.UI
{
[AddComponentMenu("Event/Graphic Raycaster")]
[RequireComponent(typeof(Canvas))]
public class GraphicRaycaster : BaseRaycaster
{
//……
public override Camera eventCamera
{
get
{
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay || (canvas.renderMode == RenderMode.ScreenSpaceCamera && canvas.worldCamera == null))
return null;

return canvas.worldCamera != null ? canvas.worldCamera : Camera.main;
}
}
}
}

2021/12/19更新

官方2020.02版本更新了这个问题(不管他改不改 还是自己记录)

有史以来最快的Unity编辑器版本,Unity 2020.2 中的性能优化 (qq.com)

image-20211219203011654

参考

  1. https://www.cnblogs.com/murongxiaopifu/p/7823487.html
  2. https://blog.csdn.net/cyf649669121/article/details/83661023

Unity中 ?? ?.的使用问题

??是c#的一个语法糖,叫空合并运算符,如果左边不为空返回左边,否则返回右边

例子a=b??c,如果b不为空,则a=b,否则a=c

在unity中我们可能这样使用

1
T t=this.gameobject.GetComponent<T>()??this.gameobject.AddComponent<T>();

获取某个物体上面的Component,但是我们获取Unity中内置的组件的时候这个方法得到的结果是永远不会为null

比如我们获取一个物体上面的相机,假如这个物体上面没有添加相机组件

1
2
var camera = GetComponent<Camera>() ?? gameObject.AddComponent<Camera>();//Camera组件不会被添加
var custom = GetComponent<CustomScript>() ?? gameObject.AddComponent<CustomScript>(); //CustomScript组件正常被添加

原因是Unity底层是C++,而且C#源码?? ?.不能重载

image-20221217183624831

总结:不要使用?? ?.操作unity 对象

参考

  1. https://www.xuanyusong.com/archives/4713
  2. Unity 中的 .NET 概述 - Unity 手册 (unity3d.com)

UGUI 点击Bug

当UI中父物体实现了IPointerDownHandler接口,而子物体实行了IPointerClickHandler接口的时候 ,点击子物体时候不会触发 Click事件.

​ 原因是UI源码中鼠标按下的时候会寻找实现了IPointerDownHandler这个接口的物体,从子物体向上寻找,所以这里就找到了父物体,然后鼠标抬起,找到实现了Click接口的物体,然后通过判断两者是否一直来触发Click事件. 这里寻找到了父物体,而寻找到click物体是子物体,所以判断不一致无法触发

链接:https://www.cnblogs.com/msxh/p/10588783.html

http://www.sikiedu.com/course/468/task/35891/show

UnityWebRequest.UnEscapeURL和UnityWebRequest.EscapeURL

要想知道这两个参数是什么意思,需要理解Http中URL的特殊字符

Url参数中出现+、空格、=、%、&、#等字符的解决办法 - 云+社区 - 腾讯云 (tencent.com)

Url出现了有+,空格,/,?,%,#,&,=等特殊符号的时候,可能在服务器端无法获得正确的参数值,抑或是造成不能正常下载文件(作为Download Url时候),如何是好?解决办法:就是需要将这些字符转化成服务器可以识别的字符;但是为何Url中有这些字符就会出现问题呢?这就得涉及到URL编码与解码问题了

一般来说,URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号。Url的编码格式采用的是ASCII码,而不是Unicode,这也就是说你不能在Url中包含任何非ASCII字符,例如希腊字母or中文。比如,世界上有英文字母的网址http://www.abc.com,但是没有希腊字母的网址http://www.aβγ.com(读作阿尔法-贝塔-伽玛.com)。这是因为网络标准RFC 1738做了硬性规定

*只有字母和数字[0-9a-zA-Z]、一些特殊符号”$-_.+!’(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。

URL中有汉字,等特殊字符的时候,就必须编码后使用。而+,空格,/,?,%,#,&,=,这些字符(不安全),当把他们直接放在Url中的时候,可能会引起解析程序的歧义,因此也必须经过编码才能使用

除了那些无法显示的字符外(例如中文),还需要在URL中对那些保留(reserved)字符和不安全(unsafe)字符进行编码。

保留字符就是那些在URL中具有特定意义的字符。不安全字符是指那些在URL中没有特殊含义,但在URL所在的上下文中可能具有特殊意义的字符。例如双引号(“”)

部分保留字符和不安全字符及其URL编码
字符 描述 用法 编码
; 分号 保留 %3B
/ 斜线 保留 %2F
? 问号 保留 %3F
: 冒号 保留 %3A
@ “at”符号 保留 %4O
= 等号 保留 %3D
& “和”符号 保留 %26
< 小于号 不安全 %3C
> 大于号 不安全 %3E
双引号 不安全 %22
# 井号 不安全 %23
% 百分号 不安全 %25
{ 左大括号 不安全 %7B
} 右大括号 不安全 %7D
| 竖线 不安全 %7C
\ 反斜线 不安全 %5C
^ 加字号 不安全 %5E
~ 波浪 不安全 %7E
[ 左中括号 不安全 %5B
] 右中括号 不安全 %5D
` 反单引号 不安全 %60
空格 不安全 %20

综上所述所研究所得:

  • URL都是ASCll码,其他字符需要转义
  • URL编码其实是字符ASCll码的十六进制然后在前面加上%号,对应ASCII表格

20220616230611ASCII

关于Unity中帧率过高导致update计算过快的影响

背景

unity程序发布如果没有设置Dont Vsync+Application.targetFrame=xx,且电脑关闭了垂直同步,电脑会以极高的帧率运行程序,如果设置了Dont Vsync 有可能会出现画面撕裂状况

image-20230705120604480

代码中有如下示例代码:

1
2
3
4
5
6
7
8
9
10
void Update()
{
var currMousePos=Input.MousePosition;
//计算移动距离
if((currMousePos-lastMousePos).sqrMagnitude>10000)
{
//do
}
lastMousePos=currMousePos;
}

如果在编辑下帧率只要60的话,也许10000这个数值是可以,但是如果帧率很高的话,会导致结果偏小也许就100

原因是帧率搞运行快,检测的两帧移动距离就会偏小

解决方案

要解决上面问题,就要是计算结果与帧率无关,这个其实就是在update中移动物体一样,使用Time.deltaTime

帧率越大,Time.deltaTime越小

帧率越小,Time.deltaTime越大

改进后代码:

1
2
3
4
5
6
7
8
9
10
11
void Update()
{
var currMousePos=Input.MousePosition;
//计算移动距离 可以在Time.deltaTime*一个固定倍数,防止数值过大
var detlaDis=(currMousePos-lastMousePos).sqrMagnitude/(Time.deltaTime);
if(detlaDis>100)
{
//do
}
lastMousePos=currMousePos;
}

关于Unity的Playersetting->OtherSetting->Stack Track

image-20230715185315689

这个是关于Unity中发布之后的日志堆栈信息,打包勾选development build,然后查看console->open log file如下

  • None

    image-20230715190544740

  • ScriptOnly

    image-20230715190639540

  • Full

    image-20230715190740710

优化记录

image-20230715191152056

关于为什么使用Animation(Legacy)动画系统不能制作序列帧动画

Legacy doesn’t support any PPtr Animation, you can animate any property of the Components, but you can not animate the reference to another object like the Sprite reference.

Legacy Animation doesn’t work… - Questions & Answers - Unity Discussions

legacy动画只能改变动画值属性,像spriterender.sprite属于引用类型不支持,PPtr 是 Unity 内部使用的术语,全称是 Pointer to Unity Object(指向 Unity 引用对象的指针)。