赞
踩
把MeshType改成Full Rect
把 Filter Mode 改成 Point(no filter)
MeshType 也要改成 Full Rect
特效是沿直线发射粒子, 需求是用startLifetime控制特效的长度
这样, 长度不是瞬间达到目标长度, 而是会缓慢变化到目标长度
eff.main.startLifetime = 10
所以要将特效的时间前进1秒, 使其立即突变为目标长度
eff:Simulate(1)
eff:Play()
Input.multiTouchEnabled = false;
关闭之后Input.touches[n]就不好用了
[CustomEditor(typeof(Transform), true)] -- 行
[CustomEditor(typeof(Text), true)] -- 不行
解决方法:
自己写个脚本MyText继承Text, 然后再扩展
using UnityEditor; using UnityEngine; using UnityEngine.UI; [CustomEditor(typeof(MyText), true)] [CanEditMultipleObjects] public class AdaptiveTextEditor : UnityEditor.UI.TextEditor { Text txt; protected override void OnEnable() { base.OnEnable(); txt = target as Text; } public override void OnInspectorGUI() { serializedObject.Update(); base.OnInspectorGUI(); serializedObject.ApplyModifiedProperties(); GUILayout.BeginHorizontal(); if (GUILayout.Button("test")) { txt.text = "逼傻是念着倒"; txt.alignment = TextAnchor.MiddleCenter; txt.raycastTarget = false; } GUILayout.EndHorizontal(); } }
in传入参数, out传出参数, ref传入传出参数
ref与out 都是为了让函数有多个返回值
ref 必须在方法外赋值
out 必须在方法内赋值
in 必须在方法外赋值, 在方法内不可写入
开发安卓游戏, 用小米10做测试机, 拖拽大地图的时候, 画面轻微抖动
查了半天代码, 没找到原因
然后换了台小米8测试, 不抖了
之所以为什么会这样的原因竟然是因为屏幕刷新率的问题!
小米10的屏幕刷新率是90赫兹, 改为60赫兹, 就不抖了
构建:
把原始链表每间隔1个数据拿出来, 形成第一级索引表
把第一级索引表间隔1个数据拿出来, 形成第二级索引表
依次形成多级索引表, 最后形成树状结构
优点:
空间换时间, 二分查找, 速度快, 时间复杂度为O(logn)
用Enum.GetValues()
using System;
foreach (panelsDef panel in Enum.GetValues(typeof(panelsDef)))
{
DoSomething(panel);
}
一旦你同时提了多个功能, 然后又想分离出来, 会超级麻烦
所以
要分别改, 分开提, 不要同时提
开闭原则:实现热插拔,提高扩展性。
里氏代换原则:实现抽象的规范,实现子父类互相替换;
依赖倒转原则:针对接口编程,实现开闭原则的基础;
接口隔离原则:降低耦合度,接口单独设计,互相隔离;
迪米特法则,又称不知道原则:功能模块尽量独立;
合成复用原则:尽量使用聚合,组合,而不是继承;
摘自: https://www.runoob.com/design-pattern/design-pattern-intro.html
if elseif会执行多次判断
switch只判断一次,效率较高
foreach写起来比for方便
foreach是只读的, 不能增删改
foreach效率比for要高 (因为for要检查index是否有效)
但是foreach会产生更多GC (每遍历过一个元素就释放它)
ToUpper()和ToLower()会创建一个新的字符串
bool.Parse()和Compare(), 是忽略大小写的比较
众所周知: zh是中文, en是英文
下面这些你可能不知道:
zh-Hans 全宇宙通用简体中文
zh-Hans-CN 大陆简体中文
zh-Hans-TW 台湾简体中文
zh-Hant 全宇宙通用繁體中文
zh-Hant-CN 大陸繁體中文
zh-Hant-TW 臺灣繁體中文
为了区分是简体还是繁体, 会用到Hans或Hant
str.Length == 0; 速度最快, 但是要求str必不能为null
str == String.Empty; String.Empty的内部也是个""
str == ""; 速度最慢, 因为要新创建一个"", 再做对比
在安卓平台上也可以使用Input.GetMouseButton(0)来接收手指的点击事件
不过只能接收一个点击
如果你用多个手指点击的话, 会取多指之间的中点作为Input.mousePosition
列表的深拷贝可以用:
1.反射
2.先ToArray(), 再把这个array作为参数传入一个new List
3.ForEach()一个一个赋值到新列表
Vector3 dir = Quaternion.Euler(new Vector3(0, 0, angle)) * Vector3.right;
计算量很少, 渲染量也很少
但是, 帧数很低, WaitForTargetFPS开销很大
原因: 看你是不是设置了帧数: Application.targetFrameRate
Trail Renderer 在unity编辑器里可以动态修改材质球的颜色
但打包成安卓就不行了
解决方法:
写个可变色的shader, 改shader的颜色
不透明的东西, 不要用带透明通道的着色器
不需要写入的时候, 关闭纹理的"可写"选项
2D游戏里, 用不到mipmap, 3D游戏里大部分也用不到, mipmap和LOD一样是用内存换渲染
小音频用Decompress On Load, 在内存中不压缩, 快, 但是占内存多
大音频用Compressed In Memory, 在内存中压缩, 占内存小, 但是慢(因为需要一个解压的过程)
Streaming是I/O操作, 不占内存, 如果你项目中的音频占很多内存, 就用这个
先定义个接口
public interface ITest
{
void AFun();
}
如果, 既要静态方法又想要动态方法, 像这样↓写是不行的
public partial class TestInterface : ITest
{
public void AFun()
{
Debug.Log("动态 A");
}
public static void AFun()
{
Debug.Log("静态 A");
}
}
↑这样写的话, 以下2种调用方式都会报错:
调用不明确(你有2个AFun()方法, 我不知道调用哪一个)
void Start()
{
TestInterface t = new TestInterface();
t.AFun();
TestInterface.AFun();
}
所以应该怎么写呢? 嗯, ↓要这样写才行
public partial class TestInterface : ITest
{
//注意这里不能写public, 因为接口本来就是public
void ITest.AFun()
{
Debug.Log("动态 A");
}
public static void AFun()
{
Debug.Log("静态 A");
}
}
调用的时候这样调↓
void Start()
{
TestInterface t = new TestInterface();
//这里需要强转
((ITest)t).AFun();
TestInterface.AFun();
}
public class Structure
{
public Structure(int num) : this(new int[] { num })
{ }
public Structure(int[] nums)
{
Debug.Log("不管你传参是int还是int[], 都走这个方法, 参数为: " + nums[0]);
}
}
where字句后面有new()约束的话,T类型必须有public且没有参数的构造函数。
bit: 位, 即0或1
byte: 字节, 1个字节是8位, 即2^8, 即[0-255], 因为要分正负号, 就得再除以2, 即[-128, 127]
bool: 占1位
char: 占1个字节
short: 占2个字节, 即16位
int: 占4个字节, 即32位, 即2^32, 即[-2147483648, 2147483647]
(为什么负数比正数多一位呢, 因为多一个负0
正0的2进制为: 0000 0000 0000 0000
负0的2进制为: 1000 0000 0000 0000, 就用来表示-2147483648了
float是32位, int也是32位, 但float只能保证6-7位有效数字, 为什么:
1bit(符号位) 8bits(指数位) 23bits(尾数位)
精度是由尾数的位数来决定的
2^23 = 8388608,一共七位
这意味着最多能有7位有效数字,第7位是8, 保证不了, 所以绝对能保证的为6位
所以float的精度为6~7位有效数字;
C#里的long和Int64一样
我们说的视频1080p, 是指视频长宽1920×1080 = 2073600个像素, 也就是我们常说的: 手机拍照200万像素
2k 是 2560x1440
4k 是 3840x2160
注意: 以上, 表示在16:9的宽高比时的数值
bps: bits per second, 传的是bit, 就是位, 就是0101010111
注意: 在计算传输速率时是以1000进的, 即1M bps = 1000K bps
Bps: Byte per second, 字节, 1M Bps = 1024K Bps
2个G的葫芦娃动画片, 就是2G Byte
你家的网速是10M
10M就是说10 000 000位每秒, 而1个字节是8位, 10 000 000 ÷ 8 = 1 250 000字节
所以实际下载速度仅仅是每秒1.25M
那个10M是唬你的, 是10101000111000的传输速度
你真正关心的是2个多G的葫芦娃要下载多久, 这里的每秒1.25M才是你需要的
1KB (Kilobyte 千字节)=1024B,
1MB (Megabyte 兆字节 简称“兆”)=1024KB,
1GB (Gigabyte 吉字节 又称“千兆”)=1024MB,
1TB (Trillionbyte 万亿字节 太字节)=1024GB,其中1024=2^10 ( 2 的10次方),
1PB(Petabyte 千万亿字节 拍字节)=1024TB,
1EB(Exabyte 百亿亿字节 艾字节)=1024PB,
1ZB (Zettabyte 十万亿亿字节 泽字节)= 1024 EB,
1YB (Jottabyte 一亿亿亿字节 尧字节)= 1024 ZB,
1BB (Brontobyte 一千亿亿亿字节)= 1024 YB.
抄自: https://xuexi.zqnf.com/844056.html
readonly可以用构造函数赋值
string str = “戴拿”;
string.Format(“{0}”, str);
那如果我想拼一个"{“进去呢, 会报错怎么办?
那就得打上”{{", 就表示{
空格表示为%20, 双引号表示为%22
https://blog.csdn.net/superit401/article/details/78052965
List, 她里面有Sort, CopyTo, FindIndex, Reverse, Contains, ForEach, Add等等一堆方法
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable
{
//(方法太多就不贴了, 想看? 在List身上按F12进去看)
}
而IList, 她只有以下功能
public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
{
T this[int index] { get; set; }
int IndexOf(T item);
void Insert(int index, T item);
void RemoveAt(int index);
}
人家List会的本领: 排序, 翻转, 复制, 判断包含等, IList全都不会, 她只能用来存放数组, 只是一个可怜的容器
既然IList远不如List强大, 那什么情况下用IList而不用List呢?
答: 需要节省的时候
用全屏UI时, 禁用世界相机
非全屏UI时, 用世界相机截屏, 把截图铺在UI底下做背景, 然后禁用世界相机
(我记得生化危机5里, 一章结束后, 画面会定格, 然后出结算界面, 估计就是这样弄的)
不需要进行点击交互的组件,取消勾选Raycast Target
CullTransparentMesh: 新版本勾上这个, 图片的Alpha为0时不会Overdraw (比如做"点击屏幕任意位置"的时候)
一直占内存
你下次用的时候, 里面存的东西还在里面躺着
方法非常多
1.用JsonUtility
注意!
要用[System.Serializable]特性, 序列化才能转成Json;
因为是轻量型, 不能读存多维数组
用法: JsonUtility.FromJson();
2.用Newtonsoft.Json;
要下载dll
可解析多维数组, 形如List<List<int>>
using Newtonsoft.Json; //类存为Json public static void SaveJson(MapData mapData) { if (!File.Exists(JsonPath())) { File.Create(JsonPath()); } string json = JsonConvert.SerializeObject(mapData); File.WriteAllText(JsonPath(), json); //Debug.Log("保存成功"); } //读取Json public static MapData ReadJson() { if (!File.Exists(JsonPath())) { Debug.LogError("文件不存在"); return null; } string json = File.ReadAllText(JsonPath()); MapData mapData = JsonConvert.DeserializeObject<MapData>(json); return mapData; }
block.GetComponent<SpriteRenderer>().color = Color.red;
看相机的Layer有没有取消勾选
看相机有没有勾选OcclusionCulling(遮挡剔除)
很好的文章:
https://blog.csdn.net/qq_31967569/article/details/83305415
0 是生命周期方法
1 用了Invoke(“方法名”, 1f); 这时候Ctrl+F搜一下方法名就行了
2 直接把方法挂在物体上了, 找吧
3 方法挂在了动画的Event上, 今天遇到这个坑, 这时候Animation就变成了ReadOnly, 但是Event仍然可以在模型上找到那个动画的Event来改
//设置画质
int qualityLevel = 0;//即Very Low
QualitySettings.SetQualityLevel(qualityLevel, true);
//Get画质
QualitySettings.GetQualityLevel();
public List<GameObject> equips;
Hierarchy面板中就会显示这个list
你的做法: 在Size输入10, 然后把10个物体一个一个依次拖进来, 对吧?
简单方法: 先锁住这个Hierarchy, 直接选中多个物体, 一次性拖进list中
int a = 0;
switch (a)
{
case 0:
//这里不写break;
case 1:
//0和1都会执行Do();
Do();
break;
case 2:
break;
default:
break;
}
↓打开浏览器并打开百度页, 这个↓"http://"加不加都行
Application.OpenURL("http://www.baidu.com");
↓打开E盘
Application.OpenURL(@"file://E:\");
↓打开手机微信
Application.OpenURL("weixin://");
鼠标点击, 射线检测
OnVisible(); 判断是否在视野中
Vector3.Diatance(); 判断距离
Vector3.Angle(); 判断角度
Physics.BoxCastAll(); 发一个方形射线, 在打到的数组里遍历查找
你第2个断点打到 if 里去了, 而它走的 else
扣掉键盘上的"Caps Lock"和"Insert"键
由于是存在栈中, 所以比class快
小体积的玩意就用struct
比如Vector3就是个struct
static: 静态变量, 永久占内存, 存的数据可改
const: 常亮, 不可改
只有继承mono, 才能挂在场景里的物体上;
继承mono, 就不能用构造函数了;
为了性能, 能不继承就不继承;
继承mono的类, 类名 和 文件名 要同名
(比如, 你有一个Mgr.cs文件, 里面必须要写有 class Mgr : MonoBehaviour{})
什么时候需要继承:
需要用到Awake Update OnEnable OnTriggerEnter等方法时;
如果想录的动画包括子物体的移动旋转等, 要确保这个子物体身上没有Animator
把所有 “不是数字的字符” 都换成 “.”
string str = "1,2,的撒发三份122,提问2,4,为前提";
string result = Regex.Replace(str, @"[^0-9]+",".");
print(result);
//输出1.2.122.2.4
transform.SetPositionAndRotation(Vector3, Quaternion);
dotween.SetDelay(float);
transform.GetChild(string);
Undo.RecordObject(object, string);//Editor
list.IndexOf(T item)
Quaternion.Euler(Vector3);//传一个欧拉角进去
Physics2D.queriesStartInColliders = false;//2D射线不检测自身
//还有, 2D射线不需要Ray
dotween.SetUpdate(true);//使DOTween不受TimeScale的影响
dotween.OnUpdate( ()=>DoSomething() );//tween过程中每帧执行DoSomething();
CustomYieldInstruction //继承此类能实现自定义的yield
list.TrueForAll(x => x < 10);//返回bool
↓类型一致的转化, 比如数值 float, int, double, enum等, 也就是"强制转换"
float f = 1.2f;
int i = (int)f;//截取整数部分
↓类型不同的转化, 得用方法
string s = f.ToString();
int a = Convert.ToInt32(s);//基本上什么类型都能转成int
int b = int.Parse(s);//只能把string转成int
//↓像这样, 把其中一个数字强转成float就行啦
(float)1 / 2
1 / (float)2
//↓没必要2个数字都转
(float)1 / (float)2
注意: 1f和1.0f都是float, 而1.0是double, 不是float,
比for简洁
↓把string数组转化为int数组
string[] strings = { "1", " 2", "3" };
int[] ints = Array.ConvertAll(strings, int.Parse);
↓所有string, Trim();一下
string[] strings = { "1", " 2", "3" };
strings = Array.ConvertAll(strings, p => p.Trim());
会有类似LOD的效果, 离远了就看不到纹理了
内存会增加约1/3
为什么是1/3呢, 看这个视频, 第47分钟:
现代计算机图形学入门
项目要求是ABCD(可能还有EF)答题选项, 动态加载
↓要是都是这样的题型就简单了
口 A.我是选项A
口 B.我是选项B
口 C.我是选项C
口 D.我是选项D
先制作宽度一行的Toggle预制体
口 A.我是选项A
再弄个ScrollView在Content上挂上ContentSizeFitter以适应ABCD(EF), 再挂上VerticalLayoutGroup均匀排布就行了
↓但是题型有这样的
口 A.我是选项A
口 B.我是选项B, 我就是要比别的选项长, 别的选项只占一行, 而我就是要占好几行,
哎, 我就是特立独行, 我就是格外一个样, 你的VerticalLayoutGroup失效了,
你能拿我怎么办, 我就是我是颜色不一样的烟火
口 C.我是选项C
口 D.我是选项D
众所周知, LayoutGroup的子物体挂上ContentSizeFitter是不生效的
所以权宜之计是将Toggle预制体宽度调宽
口 A.我是选项A
效果如下, 很不好看
口 A.我是选项A
口 B.我是选项B, 我就是要比别的选项长, 别的选项只占一行, 而我就是要占好几行,
哎, 我就是特立独行, 我就是格外一个样, 你的VerticalLayoutGroup失效了,
你能拿我怎么办, 我就是我是颜色不一样的烟火
口 C.我是选项C
口 D.我是选项D
解决方法:
把Toggle预制体挂在一个Text下, 然后把这个Text作为预制体, Text上挂ContentSizeFitter是不会失效的
这个Text呢, 就用来取代Toggle中Label, 但是Label不要删, 只把字删掉就好
要是删了的话, 点击Toggle的文字部分就无效了, 只有点它前面的小方框才有效
子物体必须是活着的, 不然get不到
除非, 在参数里面加上 (true)
GetComponentsInChildren<T>(true);
最后一个元素后面 不 ! 加 ! 逗 ! 号 !
把这个脚本, 挂在场景的最高父物体上
不论是点到了窗子还是桌子, 选中的都是场景的最高父物体
using UnityEngine;
[SelectionBase]
public class IAmAncestor : MonoBehaviour
{
}
↑上面的方法, 不行, 下面的方法, 行↓
给所有不想点的东西(树啊房子啊)的layer设置成XXX
然后点开图中这个Layers
再点XXX后面的小锁
这样就再也点不到场景中的树和房子了
改变模型的Scale X Y Z的其中一个为负数就行了
带有协程的脚本.enabled = false; 协程会照常运行
带有协程脚本的gameObject.SetActive(false); 协程全部停止,即使再激活, 协程也不会继续执行
用params关键字
public void Speak(params int[] s)
{
for (int i = 0; i < s.Length; i++)
{
persons[i].DoAnim("Speak");
}
}
//用的时候:
Speak(0,1);
Speak(4,5,6,7,8,9);
↓这样写, 如果你没传参数进来, 会报空
void DontCheckNull(Action action = null)
{
action();
}
↓所以需要判断一下空
void DoCheckNull(Action action = null)
{
if (action != null)
{
action();
}
}
可以简化为↓ (C#6可以, C#4不行)
void DoCheckNull(Action action = null)
{
action?.Invoke();
}
后来我发现几乎所有的判空都能这样写: 加个问号
因为它在栈上, 怎么会空呢, 除非…
在声明的时候这样写:
int? a;
int? 表示可空类型,就是一种特殊的值类型,它的值可以为null
用于给变量设初值得时候,给变量(int类型)赋值为null,而不是0
int?? 用于判断并赋值,先判断当前变量是否为null,如果是就可以赋个新值,否则跳过
public int? a = null;
public int b()
{
return a ?? 0;
}
原文地址: https://www.cnblogs.com/firstcsharp/archive/2011/12/11/2283797.html
用EventSystem.current.IsPointerOverGameObject()
if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject())
{
//点在物体上了
}
else if(Input.GetMouseButtonDown(0) && EventSystem.current.IsPointerOverGameObject())
{
//点在UI上了
}
需求:
一个小弹窗, 它的固有点击事件为: 自身窗体消失, 还可能有别的点击事件, 且这些点击事件仅生效一次
开搞:
↓一开始我是这样写的, 很蠢, 不管有没有委托, 都全部移除, 再添加上消失事件和自定义的委托
public void ShowTip(string tipText, Action action = null)
{
textTip.text = tipText;
panelTip.SetActive(true);
btnTip.onClick.RemoveAllListeners();
btnTip.onClick.AddListener(() => panelTip.SetActive(false));
if (action != null)
{
btnTip.onClick.AddListener(() =>
{
action();
});
}
}
↓改进了一下, 用了EventTrigger, 但是还是很蠢
public void ShowTip(string tipText, Action action = null)
{
textTip.text = tipText;
panelTip.SetActive(true);
if (action != null)
{
btn.MyBtnClick += action;
btn.MyBtnClick += ()=> { btn.MyBtnClick -= action; };
}
}
↓其实明明可以更简单的
public void ShowTip(string tipText, Action action = null)
{
textTip.text = tipText;
panelTip.SetActive(true);
btn.MyBtnClick = action;
}
注意1 : 在Game面板中可见, 或在Scene面板中可见, 都会触发本方法
注意2 : 即使把Mash Fitter设置为None, 使之不可见, 仍会触发本方法
bool isVisiable;
private void OnBecameVisible()
{
isVisiable = true;
}
方法1: 调小相机的Near Clip Plane
方法2: 如果是自己手里的枪穿模, 那就另开一个相机, 只看枪, 相机的Clear Flags改为Depth only
方法3: 在相机上添加碰撞体
string sceneName = SceneManager.GetActiveScene().name;
刚才犯了一个很傻逼的问题:
在Start里声明, 在OnEnable里调用, 结果报空了;
生命周期啊生命周期, 先OnEnable再Start;
注意:
在同一个类里, 是先OnEnable再Start;
但是在不同类里, 顺序是不确定的, 举个例子:
触发顺序可能为:
A类的OnEnable, B类的OnEnable, A类的Start, B类的Start
也可能为:
A类的OnEnable, A类的Start, B类的OnEnable, B类的Start
(A的Start可能会排在B的OnEnable前面)
实现拖拽功能, 让ret跟着鼠标走, 遇到的坑:
ret.position = Input.mousePosition;
↑这样不行, ret的移动幅度特别大.
ret.parent = mother;//mother是一个点,锚点在左下角
ret.localPosition = Input.mousePosition;
↑这样才行
960 540(适配分辨率), 能完美运行
切换成1920 1080的时候, 鼠标在左下角, ret也在左下角, 此时没错
但当鼠标移动到屏幕中间时, ret已经跑到右上角去了, ret的移动距离是鼠标的2倍
解决方法:
ret.localPosition = Input.mousePosition * (540f / Screen.height);
乘以(除以)屏幕的放大(缩小)比例, 就行了
项目要求是15个模块, 不同的场景, 不同的人物, 不同的剧情, 相同点都是对话和播动画. 我的思路是做3个类
1.Data类存数据;
2.SceneModel存放场景里的人物和物品和基本方法;
3.SceneControl主控制器, 控制事件流程; 然后分15个子类
15个子类, 分别是Scene0Control, Scene1Control, Scene2Control…Scene14Control; 然后用映射方法, 通过不同的类名, 挂到不同的场景中
public int State = 0;
SceneControl sceneControl = gameObject.AddComponent<SceneControl>();
string ctrlClassName = "Scene" + State.ToString() + "Control";
sceneControl = Activator.CreateInstance(Type.GetType(ctrlClassName)) as SceneControl;
呃, 失败了…还是 Switch 吧
有空再研究…
我研究回来了
因为脚本是挂在物体上的, 不需要用Activator.CreateInstance, 只要拿到Type就行了
public static ProcessMgr CreateByName(string module)
{
Type type = Type.GetType("ProcessMgr" + module, true);
return new GameObject("ProcessMgr").AddComponent(type) as ProcessMgr;
}
不需要打包的脚本放入名字是Editor的文件夹下, Editor文件夹放哪都行, 有很多叫做Editor的文件夹也行
只能读, 不能改, 而且会产生垃圾, (理论上应该尽可能的少用)
有可能是它不能输入全角字符
也有可能是发布的WebGL版, 是打不了中文的
还有WebGL版要把字体全部改为中文字体, 不然字体不显示
因为你打半角空格的时候, Unity以为你打的是英语单词, 为了不让单词从中间切开, 它就自动换行了;
改成全角空格就好了;
项目需求是"光线"照射到"物体A"的时候, “物体A"显示出来, 然后再对"物体A"进行操作;
所以我用了OnTriggerEnter和OnTriggerExit;
以上都正常, 然后我在物体A上用OnMouseEnter, 方法没有用, 因为"物体A"被"光线"遮住了;
解决方法, 把"光线"的Layer改成"IngoneRayCast”;
s1.Equals(s2, StringComparison.OrdinalIgnoreCase)
不要在一个单例的Awake里使用另一个单例.
比如:
在A单例的Awake中使用B单例. 但是B还没Awake, 此时B单例为null, 报空;
解决方法:
for (int i = 0; i < 10; i++)
{
btns[i].onClick.AddListener(() =>
{
print(i);
});
}
↑这样btns里的每个btn打印出来都是"10";
for (int i = 0; i < 10; i++)
{
int temp = i;
btns[i].onClick.AddListener(() =>
{
print(temp);
});
}
↑这样打印出来才是想要的0,1,2,3,4,5,6,7,8,9
额, 这里有个很奇怪的地方我一直想不通, 哪位胸大的来分析一下:
↓在C#里这样写输出3 3 3
using System; using System.Collections.Generic; public class Test { public static void Main() { List<Action> actions = new List<Action>(); for(int i = 0; i < 3; i++) { actions.Add(()=>{Console.WriteLine(i);}); } for(int i = 0; i < actions.Count; i++) { actions[i].Invoke(); } } }
↓而在Lua里同样写法, 输出的却是1 2 3
actions = {}
for i = 1, 3 do
actions[i] = function() print(i) end
end
for i = 1, #actions do
actions[i]()
end
妈呀, 没想到, 1年之后, 我被↑这个问题坑到了
我是这样写的↓, 以为会输出123, 没想到输出333
actions = {}
for i = 1, 3 do
a = i
actions[i] = function() print(a) end
end
for i = 1, #actions do
actions[i]()
end
工具 > 自定义 > 命令 > 添加命令 > 文件 > 高级保存选项;
然后关闭, 再点击高级保存选项, 把编码改成UTF-8(无签名)
不间断空格\u00A0 让一个单词在结尾处不会换行显示
半角空格(英文符号)\u0020
全角空格(中文符号)\u3000
不知道为什么, 有的mp3能播, 有的mp3不能播, 可能是mp3的问题(怀疑是假mp3格式)
方法就是转换成wav格式
正确方法是要在Unity里调mp3的WebGl设置
记得给物体用特定的layer
相机只看这个layer, 别的不看
audioClip = Microphone.Start(null, false, RECORD_TIME, RECORD_RATE);
RECORD_TIME: 录音时长
RECORD_RATE: 录音的采样率, 填8000 - 44100
//取前 i个字符
str.Substring(0, i);
str.Remove(i, str.Length - i);
//去除所有的空格
str.Replace(" ", "");
//去除头尾的空格和类空格字符
str.Trim();
//去除回车
str.Replace("\r", "");
↓正则表达式↓ 不用记忆这些东西, 肯定忘, 用的时候再看就行
https://www.runoob.com/csharp/csharp-regular-expressions.html
↓给本物体添加AudioSource组件, 省的你忘了挂上
[RequireComponent(typeof (AudioSource))]
↓提示本方法已过时, 但方法依然可以用
[Obsolete("已过时, 请使用NewMethod")]
↓true表示已弃用, 方法不能用了
[Obsolete("已弃用, 请使用NewMethod", true)]
↓这样一来这个方法就不跑了, 除非在最上面(using XXX上面)写上:#define IsTest;
[Conditional("IsTest")]
↓只能挂一个本脚本, 不允许挂多个
[DisallowMultipleComponent]
↓会出现在菜单栏的Component > Test
[AddComponentMenu("Test")]
否则报错
正确格式: yyyy-MM-dd HH-mm-ss-ffff
System.DateTime.Now.ToString("yyyy-MM-ddHH-mm-ss-ffff");
Y按星期算年, 会不准, 原因我忘了
M是月, m是分钟, 这个没有大小写的转换
d是当月的天数(2月1日), D是一年中的天数(32天)
H是24小时制, h是12小时制
s是秒, S是毫秒
另外的还有w之类的, 和星期相关的, 对咱们用处不大, 估计对老外有用, 比如母亲节是:五月的第二个星期天
因为unity把动画压缩了
解决方法:Animation:Anim.Compression改成off (不压缩动画)
或者下面3个error改小
不要慌, 可能只是因为你的场景里没有EventSystem.
遇到好几次了, 我怎么就记不住呢?
还有别的可能:
1.被另一个透明panel覆盖住了
2.你Canvas上没挂Graphic Raycaster(毕竟Unity的UI本来就用的是射线检测)
3.你用射线检测写的按钮按下, 但按钮上没挂Collider
4.你用的Space World模式的Canvas, 摄像机的Tag层不是Main Camera
Sprite sp = Resources.Load("Die",typeof (Sprite)) as Sprite;
img.sprite=sp;
图片的载入一定要加上typeof (Sprite), 不然没有用
不要像下面这样, 在OnDisable()中给子物体换爸妈, 会报错
private void OnDisable()
{
for (int i = 0; i < transform.childCount; i++)
{
transform.GetChild(i).SetParent(null);
}
}
这样是没用的:
float x = joy.localScale.x;
这样才行:(仅锚点不分开的时候)
RectTransform rtf = joy.GetComponent<RectTransform>();
float x = rtf.sizeDelta.x;
这样也行:(锚点分开也行)
float x = rtf.rect.width;
float y = rtf.rect.height;
设置UI的宽:
rtf.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal,100);
得到中心点:
Vector2 pivot = rtf.pivot;
要勾选Text组件的"Rich Text"选项:
//将"奥特曼"粗体显示
我是<b>奥特曼</b>
//斜体
我是<i>奥特曼</i>
//字体大小
我是<size=14>奥特曼</size>
//字体颜色
我是<color=red>奥特曼</color>
tw.PlayBackwards(); 并不会触发tw.OnComplete();
UI.DOMove()
项目需求: UI移动到指定位置, 而且需要能够切换窗口和全屏模式:
常用的UI.DOMove(), 移动到new Vector3(1,1,1)就不行了, 因为屏幕分辨率变了之后, Vector3(1,1,1)并不会去自适应屏幕位置;
移动到Scene.height+UI自身长度也不行, 因为屏幕一变, 自身长度也是变的;
所以我放了一些空点在UI里, 这些点是有屏幕适配的, 直接DOMove移动到该点的坐标就行了
这里的坑是: 点的pivot要和被移动的UI的pivot一致才行, 锚点定位是没关系的, 上下左右定哪都行不影响, 但pivot一定要一毛一样;
内容一样, 顺序也一样:
using System.Linq;
if(list1.SequenceEqual(list2))
内容一样, 顺序可以不一样:
using System.Linq;
if(list1.Count == list2.Count && list1.Count(t => !list2.Contains(t)) == 0)
.txt文件要另存为utf-8格式;
// 将txt中的内容加载进TextAsset中
TextAsset txt = Resources.Load("txt") as TextAsset;
// 以换行符作为分割点,保存数组, 最后记得Trim()一下, 去掉多余的空格换行符什么的
string[] strs = txt.text.Split('\n').Trim();
//正确的枚举是这样是 public enum Character { A, B, C, } //而不是下面这样, 再用个类把枚举包起来 public class CharacterEnum { public enum Character { A, B, C, } }
枚举是值类型
IEnumerator LoadAsyncScene(string sceneName)
{
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
//只要没加载完, 就一直返回空
while (!asyncLoad.isDone)
{
yield return null;
}
//加载完了
DoSomething();
}
↓你还可以把下面这个玩意↓设为false, 等你的进度条加完了, 再设为true;
asyncLoad.allowSceneActivation;
↓带进度条的异步加载↓以及适配WebGL
https://blog.csdn.net/weixin_43994445/article/details/106231953
Cinemachine, ADS等Unity内置插件在商店是找不到的, 他们在这:
Windows → Package Manager
TimeLine在:
Windows → Sequencing
2018里好像没有
也可能是下架了, 没了
也可能是暂时下架了, 过几天就有了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。