使LitJson支持Unity的类型

在使用LitJson时,会发现不支持Unity的Vector3等类型,更为奇怪的是在Unity的Editor模式下是正常的,在真机设备上不行了,今天查看源码终于找到原因了。 LitJson本身为支持Unity已经定义了一个类UnityTypeBindings,局部代码如下:

#if UNITY_EDITOR
[UnityEditor.InitializeOnLoad]
#endif
public static class UnityTypeBindings {

static bool registerd;

static UnityTypeBindings(){
Register();
}

就是因为在UNITY_EDITOR下加了标签[UnityEditor.InitializeOnLoad],所以在编辑器模式下支持Vector3等类型,因此只需要在项目加上如下代码即可:

UnityTypeBindings.Register()

参照以下注册方法,可实现自定义类型的Json序列化支持

Action<Vector2,JsonWriter> writeVector2 = (v,w) => {
w.WriteObjectStart();
w.WriteProperty(“x”,v.x);
w.WriteProperty(“y”,v.y);
w.WriteObjectEnd();
};

JsonMapper.RegisterExporter((v,w) => {
writeVector2(v,w);
});

参考资料:
LitJson官网:http://lbv.github.io/litjson/

Unity笔记

1.二维夹角计算

UI上三个点,其中一个是原点(0,0),另外两个点A为起始点,B为当前点,计算当前点和起始点的夹角

方法1:通过Vector3.Cross判断正负,纯Vector2.Angle 只能给出夹角

1
2
3
4
5
6
7
float VectorAngle (Vector2 from, Vector2 to)
{
            float angle;
            Vector3 cross = Vector3.Cross (from, to);
            angle = Vector2.Angle (from, to);
            return cross.z > 0 ? -angle : angle;
}

方法2:三角函数,先计算两个点相对X轴夹角,相减,得到需要的夹角—-老魏

1
2
3
4
5
6
float GetAngleByScreenPos (Vector2 screenPos)
{
Vector2 offsetPos = Vector2.zero - screenPos;
return Mathf.Atan2 (offsetPos.y, offsetPos.x) * Mathf.Rad2Deg;
}

2.方向上的点计算

UI上三个点,其中一个是原点O(0,0),另外两个点A为鼠标点击的屏幕点,求在OA方向上的B点 如下图,限制B点不超过圆圈,圆圈半径100. 2017-04-26 11-44-09.png 首先转换坐标:

1
2
 Vector3 worldPos = UICamera.ScreenToWorldPoint(ScreenPos);//ScreenPos 即为 A点坐标
 Vector3 localPos = this.transform.parent.InverseTransformPoint (worldPos);

然后获取B点两种方法: A:射线法:

1
2
3
4
if (localPos.sqrMagnitude > MAX_DIS * MAX_DIS) {
Ray ray = new Ray (Vector3.zero, localPos);
localPos = ray.GetPoint (MAX_DIS);
}

B:向量法:

1
2
3
if (localPos.sqrMagnitude > MAX_DIS * MAX_DIS) 
localPos = localPos.normalized * MAX_DIS;

 

3.局部截屏

截屏局部需要以(Screen.width,Screen.height)来创建RenderTexture,然后以Texture2D的ReadPixels(rect,destX,destY)来读取局部信息,此时的坐标系是左下角为原点(0,0).如下图,如果要需要截取内框(绿色)区域,需要计算出A和B的屏幕坐标,B-A获取框的宽高,来得到new Rect(A.x,A.y,B.x-Ax,B.y-A.y),调用下面的CaptureCameras方法来获取相应区域的Texture2D。

*注:仅5.3.6版本,截图上下会有偏移,左右正常,截图时可先将图片调至纵向居中,截图后调回。

2017-05-12 10-50-21.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public static Texture2D CaptureCameras (Rect rect, params Camera[] cameras)
{
RenderTexture rt = new RenderTexture ((int)Screen.width, (int)Screen.height, 24);
//临时设置相关相机的targetTexture为rt, 并手动渲染相关相机
for (int i = 0; i < cameras.Length; i++) {
if (cameras [i] != null) {
cameras [i].targetTexture = rt;
cameras [i].Render ();
}
}

//激活这个rt, 并从中中读取像素。
RenderTexture.active = rt;
Texture2D screenShot = new Texture2D ((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
screenShot.ReadPixels (rect, 0, 0);   //注:这个时候,它是从RenderTexture.active中读取像素
screenShot.Apply ();

//重置相关参数,以使用camera继续在屏幕上显示
for (int i = 0; i < cameras.Length; i++) {
if (cameras [i] != null)
cameras [i].targetTexture = null;
}
RenderTexture.active = null;
rt.Release ();
GameObject.Destroy (rt);
rt = null;

return screenShot;
}

4.跟随手指拖拽来旋转镜头

使用场景,手指拖拽时镜头跟随手指移动,计算方法:

先计算整个屏幕宽度所对应的旋转角度,然后根据手指在屏幕上的横移距离来获得需要旋转的角度。

1
2
3
4
5
a.计算总角度(fieldOfView是摄像机的侧面垂直角度,横向角度会根据屏幕比例变化)
var m_TotalCameraScreenWAngle = Camera.main.fieldOfView * Screen.width / Screen.height;
b.计算需要移动的角度
var angle = pDragGesture.DeltaMove.x * m_TotalCameraScreenWAngle / Screen.width;
m_CameraTransform.localEulerAngles -= new Vector3(0, angle, 0);

Unity之查找资源被哪里引用了

有时候要删除一个资源,就需要先查看下被哪里引用了,防止误删。Unity提供了一个方法 AssetDatabase.GetDependencies(),但是它只能查找这个资源引用了那些资源。 但是我想要的是查找某个资源被那些资源引用了,这是两种相反的查找公式。 网上找到一个查找脚本,速度很快,不过只能在Mac上用。右键选择一个资源,点击 Find References,会在Console面板上输出结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;

public class FindProject {

#if UNITY_EDITOR_OSX

[MenuItem("Assets/Find References In Project", false, 2000)]
private static void FindProjectReferences()
{
string appDataPath = Application.dataPath;
string output = "";
string selectedAssetPath = AssetDatabase.GetAssetPath (Selection.activeObject);
List<string> references = new List<string>();

string guid = AssetDatabase.AssetPathToGUID (selectedAssetPath);

var psi = new System.Diagnostics.ProcessStartInfo();
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized;
psi.FileName = "/usr/bin/mdfind";
psi.Arguments = "-onlyin " + Application.dataPath + " " + guid;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;

System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo = psi;

process.OutputDataReceived += (sender, e) => {
if(string.IsNullOrEmpty(e.Data))
return;

string relativePath = "Assets" + e.Data.Replace(appDataPath, "");

// skip the meta file of whatever we have selected
if(relativePath == selectedAssetPath + ".meta")
return;

references.Add(relativePath);

};
process.ErrorDataReceived += (sender, e) => {
if(string.IsNullOrEmpty(e.Data))
return;

output += "Error: " + e.Data + "\n";
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();

process.WaitForExit(2000);

foreach(var file in references){
output += file + "\n";
Debug.Log(file, AssetDatabase.LoadMainAssetAtPath(file));
}

Debug.LogWarning(references.Count + " references found for object " + Selection.activeObject.name + "\n\n" + output);
}

#endif
}

Pip安装依赖于six的库失败的解决方法

今天在安装 google-api-python-client库时,six库一直报错升级不了

1
2
3
4
5
Installing collected packages: six
Found existing installation: six 1.4.1
DEPRECATION: Uninstalling a distutils installed project (six) has been deprecated and will be removed in a future version. This is due to the fact that uninstalling a distutils project will only partially uninstall the project.
Uninstalling six-1.4.1:
...

参考github上的解决办法:https://github.com/pypa/pip/issues/3165 将安装命令改成如下即可:

1
sudo pip install --upgrade google-api-python-client --ignore-installed six

即使用参数–ignore-installed来忽略本地安装的six。

原因可能是Apple预安装的这个six库出于安全原因被设置为sudo也不可以执行操作,所以需要依赖于高版本的库就需要更新six,但是没有six的权限,所以就回报错。

Unity之文本Text颜色渐变

Unity的UGUI的Text只能设置单个颜色,由于项目需求,需要Text有渐变色,在网上找了几篇,发型都在用一个叫 TextVerticalGradientThreeColor的组件,不过这个组件虽然支持三种颜色,但是不能更改颜色数量和渐变位置,还是太方便,怎么办呢?那就花点时间自己造轮子吧。 TextGradientColor可配合自带的Outline和Shadow使用,上下顺序不同,渲染出来的效果也有差别,可以自己试试。 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;

namespace UI.Extension
{
//和文本的 Shadow 和 outline 效果配合 , 渲染顺序不一样,效果也不一样

[AddComponentMenu ("UI/Effects/Text Gradient Color")]
[RequireComponent (typeof(Text))]
public class TextGradientColor : BaseMeshEffect
{
public Gradient gradientColor = new Gradient ();
//是否垂直方向
public bool isVertical = true;
//是否叠加原有颜色
public bool isMultiplyTextColor = false;
protected TextGradientColor ()
{
}

private void ModifyVertices (VertexHelper vh)
{
List<UIVertex> verts = new List<UIVertex> (vh.currentVertCount);
vh.GetUIVertexStream (verts);
vh.Clear ();

//每个字母 分为两个三角形,6个顶点,如下图 0和5位置相同 2和3位置相同
/**
* 5-0 ---- 1
* \
* \
* \
* \
* 4-----3-2
**/

int step = 6;
for (int i = 0; i < verts.Count; i += step) {

UIVertex start1, start2, end1, end2, current1, current2;
if (isVertical) {
start1 = verts [i + 0];
start2 = verts [i + 1];
end1 = verts [i + 4];
end2 = verts [i + 3];
} else {
start1 = verts [i + 0];
start2 = verts [i + 4];
end1 = verts [i + 1];
end2 = verts [i + 2];
}

for (int j = 0; j < gradientColor.colorKeys.Length; j++) {
GradientColorKey colorKey = gradientColor.colorKeys [j];
if (j == 0) {
multiplyColor (start1,colorKey.color);
multiplyColor (start2,colorKey.color);
} else if (j == gradientColor.colorKeys.Length - 1) {
multiplyColor (end1,colorKey.color);
multiplyColor (end2,colorKey.color);

//right
vh.AddVert (start1);
vh.AddVert (start2);
vh.AddVert (end2);

//left
vh.AddVert (end2);
vh.AddVert (end1);
vh.AddVert (start1);

} else {
// create right
current2 = CreateVertexByTime (start2, end2, colorKey.time);
vh.AddVert (start1);
vh.AddVert (start2);
vh.AddVert (current2);

// create left
current1 = CreateVertexByTime (start1, end1, colorKey.time);
vh.AddVert (current2);
vh.AddVert (current1);
vh.AddVert (start1);

start1 = current1;
start2 = current2;
}
}
}

//添加三角形

//每个字母的顶点数量
int stepVertCount = (gradientColor.colorKeys.Length - 1) * 2 * 3;
for (int i = 0; i < vh.currentVertCount; i += stepVertCount) {
for (int m = 0; m < stepVertCount; m += 3) {
vh.AddTriangle (i + m + 0, i + m + 1, i + m + 2);
}
}
}

private UIVertex multiplyColor(ref UIVertex vertex, Color color)
{
if (isMultiplyTextColor)
vertex.color = Multiply (vertex.color, color);
else
vertex.color = color;
return vertex;
}

public static Color32 Multiply(Color32 a, Color32 b)
{
a.r = (byte)((a.r * b.r) >> 8);
a.g = (byte)((a.g * b.g) >> 8);
a.b = (byte)((a.b * b.b) >> 8);
a.a = (byte)((a.a * b.a) >> 8);
return a;
}

//根据比例创建顶点 (time这里是gradientColor里的比例)
private UIVertex CreateVertexByTime (UIVertex start, UIVertex end, float time)
{
UIVertex center = new UIVertex ();
center.normal = Vector3.Lerp (start.normal, end.normal, time);
center.position = Vector3.Lerp (start.position, end.position, time);
center.tangent = Vector4.Lerp (start.tangent, end.tangent, time);
center.uv0 = Vector2.Lerp (start.uv0, end.uv0, time);
center.uv1 = Vector2.Lerp (start.uv1, end.uv1, time);
center.color = gradientColor.Evaluate (time);

if (isMultiplyTextColor) {
//multiply color
var color = Color.Lerp(start.color, end.color, time);
center.color = Multiply (color, gradientColor.Evaluate (time));
} else {
center.color = gradientColor.Evaluate (time);
}

return center;
}

#region implemented abstract members of BaseMeshEffect

public override void ModifyMesh (VertexHelper vh)
{
if (!this.IsActive ()) {
return;
}

ModifyVertices (vh);
}

#endregion
}
}