前天朋友遇到一个这样的需求,而且比较棘手让我帮忙解决。需求就是棋牌类的游戏,玩家的个人资料中包括自己的头像而且可以浏览相册中的图片或者使用相机拍照设置。关于这个问题我也查阅一些资料,由于涉及安卓部分知识,首先要了解Unity和安卓是如何通信的。
首先看到的是雨松老师的博客:http://www.xuanyusong.com/archives/1480咱们可以一起参考下这篇博客。好了,废话就不多说了,夜已深,开始撸代码吧!
1 新建空的工程
2,头像显示当然要用图片了,就用UGUI的RawImage吧。
3,准备工作基本上结束了,接下来就是完成浏览相册和拍照上传了。这部分就不详细介绍了网上有很多教程,借助Eclipse完成浏览相册和拍照的逻辑,导出jar包在Unity中调用即可。插件已经导出,稍后会把工程共享给大家!
接下来该调用浏览相册和拍照的功能了,简单的测试,就这样吧!
void OnGUI()
{
if (GUI.Button(new Rect(10, 10, 100, 100), "Take Photo"))
{
OpenCamera();
}
if (GUI.Button(new Rect(220, 10, 100, 100), "Photo view"))
{
OpenPick();
}
if (Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.Home))
{
Application.Quit();
}
}
4,既然是圆角头像,那么还要处理圆角了。首先想到的是Shader做个裁剪即可。
是不是很神奇,上一秒还是方的哦!
5,接下来开始测试了,要打包真机测试的,请稍后打包中,,,,
6,哇咔咔,接下来要真机测试了。
对了,上面日志显示两个图片字节数值而且相差很大的,你看到的是对的。由于要考虑网络传输,传输的数据包要尽可能的小,这样才会节省流量和提高效率,第一个值是图片真是的字节数,第二个数值表示压缩后的图片字节数:2119,除以1024也就是2.07kb。这个数据还是可以接受的。
接下来是压缩的实现方法:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Threading;
public class TextureTools : MonoBehaviour
{
public class ThreadData
{
public int start;
public int end;
public ThreadData(int s, int e)
{
start = s;
end = e;
}
}
private static Color[] texColors;
private static Color[] newColors;
private static int w;
private static float ratioX;
private static float ratioY;
private static int w2;
private static int finishCount;
private static Mutex mutex;
public static Texture2D Point(Texture2D tex, int newWidth, int newHeight, bool flipH, bool flipV)
{
return ThreadedScale(tex, newWidth, newHeight, false, flipH, flipV);
}
public static Texture2D Bilinear(Texture2D tex, int newWidth, int newHeight, bool flipH, bool flipV)
{
return ThreadedScale(tex, newWidth, newHeight, true, flipH, flipV);
}
private static Texture2D ThreadedScale(Texture2D tex, int newWidth, int newHeight, bool useBilinear, bool flipH, bool flipV)
{
texColors = tex.GetPixels();
newColors = new Color[newWidth * newHeight];
if (useBilinear)
{
ratioX = 1.0f / ((float)newWidth / (tex.width - 1));
ratioY = 1.0f / ((float)newHeight / (tex.height - 1));
}
else
{
ratioX = ((float)tex.width) / newWidth;
ratioY = ((float)tex.height) / newHeight;
}
w = tex.width;
w2 = newWidth;
var cores = Mathf.Min(SystemInfo.processorCount, newHeight);
var slice = newHeight / cores;
finishCount = 0;
if (mutex == null)
{
mutex = new Mutex(false);
}
if (cores > 1)
{
int i = 0;
ThreadData threadData;
for (i = 0; i < cores - 1; i++)
{
threadData = new ThreadData(slice * i, slice * (i + 1));
ParameterizedThreadStart ts = useBilinear ? new ParameterizedThreadStart(BilinearScale) : new ParameterizedThreadStart(PointScale);
Thread thread = new Thread(ts);
thread.Start(threadData);
}
threadData = new ThreadData(slice * i, newHeight);
if (useBilinear)
{
BilinearScale(threadData);
}
else
{
PointScale(threadData);
}
while (finishCount < cores)
{
Thread.Sleep(1);
}
}
else
{
ThreadData threadData = new ThreadData(0, newHeight);
if (useBilinear)
{
BilinearScale(threadData);
}
else
{
PointScale(threadData);
}
}
tex.Resize(newWidth, newHeight);
tex.SetPixels(newColors);
tex.Apply();
Texture2D orig = new Texture2D(tex.width, tex.height);
if (flipV)
{
int xN = tex.width;
int yN = tex.width;
for (int i = 0; i < xN; i++)
{
for (int j = 0; j < yN; j++)
{
// tex.SetPixel(xN - i - 1, j, orig.GetPixel(i, j));
orig.SetPixel(i, yN - j - 1, tex.GetPixel(i, j));
}
}
orig.Apply();
}
else if (flipH)
{
int xN = tex.width;
int yN = tex.width;
for (int i = 0; i < xN; i++)
{
for (int j = 0; j < yN; j++)
{
// tex.SetPixel(xN - i - 1, j, orig.GetPixel(i, j));
orig.SetPixel(xN - i - 1, j, tex.GetPixel(i, j));
}
}
orig.Apply();
}
else
{
orig = tex;
}
return orig;
}
public static void BilinearScale(System.Object obj)
{
ThreadData threadData = (ThreadData)obj;
for (var y = threadData.start; y < threadData.end; y++)
{
int yFloor = (int)Mathf.Floor(y * ratioY);
var y1 = yFloor * w;
var y2 = (yFloor + 1) * w;
var yw = y * w2;
for (var x = 0; x < w2; x++)
{
int xFloor = (int)Mathf.Floor(x * ratioX);
var xLerp = x * ratioX - xFloor;
newColors[yw + x] = ColorLerpUnclamped(ColorLerpUnclamped(texColors[y1 + xFloor], texColors[y1 + xFloor + 1], xLerp),
ColorLerpUnclamped(texColors[y2 + xFloor], texColors[y2 + xFloor + 1], xLerp),
y * ratioY - yFloor);
}
}
mutex.WaitOne();
finishCount++;
mutex.ReleaseMutex();
}
public static void PointScale(System.Object obj)
{
ThreadData threadData = (ThreadData)obj;
for (var y = threadData.start; y < threadData.end; y++)
{
var thisY = (int)(ratioY * y) * w;
var yw = y * w2;
for (var x = 0; x < w2; x++)
{
newColors[yw + x] = texColors[(int)(thisY + ratioX * x)];
}
}
mutex.WaitOne();
finishCount++;
mutex.ReleaseMutex();
}
private static Color ColorLerpUnclamped(Color c1, Color c2, float value)
{
return new Color(c1.r + (c2.r - c1.r) * value,
c1.g + (c2.g - c1.g) * value,
c1.b + (c2.b - c1.b) * value,
c1.a + (c2.a - c1.a) * value);
}
}
OK,实用的小功能已做完,大家如果有问题可以给我留言,猿类要技术共享哦!
传送门:git@github.com:wuzhangwuzhang/UnityHeadIconSet.git