1. 解决Texture2D提示压缩格式问题,无法转byte[]
public static Texture2D DeCompress(Texture2D source)
{
RenderTexture renderTex = RenderTexture.GetTemporary(
source.width,
source.height,
0,
RenderTextureFormat.Default,
RenderTextureReadWrite.Linear);
Graphics.Blit(source, renderTex);
RenderTexture previous = RenderTexture.active;
RenderTexture.active = renderTex;
Texture2D readableText = new Texture2D(source.width, source.height);
readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
readableText.Apply();
RenderTexture.active = previous;
RenderTexture.ReleaseTemporary(renderTex);
return readableText;
}
2. Texture2D尺寸压缩
/**
* Reference: https://gamedev.stackexchange.com/questions/92285/unity3d-resize-texture-without-corruption
*/
public static Texture2D ResizeTexture(Texture2D source, int newWidth, int newHeight)
{
FilterMode mode = FilterMode.Bilinear;
source.filterMode = mode;
RenderTexture lastRt = RenderTexture.active;
RenderTexture rt = RenderTexture.GetTemporary(newWidth, newHeight);
rt.filterMode = mode;
RenderTexture.active = rt;
Graphics.Blit(source, rt);
Texture2D nTex = new Texture2D(newWidth, newHeight);
nTex.ReadPixels(new Rect(0, 0, newWidth, newHeight), 0, 0);
nTex.Apply();
RenderTexture.active = lastRt;
RenderTexture.ReleaseTemporary(rt);
return nTex;
}
/**
* Attention: Not supported on DX9 or Mac+OpenGL
*/
public static Texture2D ConvertTexture(Texture2D orgText, int width, int height)
{
Texture2D newTex = new Texture2D(width, height);
Graphics.ConvertTexture(orgText, newTex);
return newTex;
}
# 3. Texture2D裁剪
```C#
/**
* The cut width and height should be less than the size of the source texture size.
*/
public static Texture2D CutTexture(Texture2D source, int cutWidth, int cutHeight, int cutOffX = 0, int cutOffY = 0)
{
FilterMode mode = FilterMode.Bilinear;
source.filterMode = mode;
RenderTexture lastRt = RenderTexture.active;
RenderTexture rt = RenderTexture.GetTemporary(source.width, source.height);
rt.filterMode = mode;
RenderTexture.active = rt;
Graphics.Blit(source, rt);
Texture2D nTex = new Texture2D(cutWidth, cutHeight);
int deltaX = source.width - cutWidth;
int deltaY = source.height - cutHeight;
int paddingX = Mathf.Max((int)(deltaX * 0.5f) + cutOffX, 0);
paddingX = Mathf.Min(paddingX, deltaX);
int paddingY = Mathf.Max((int)(deltaY * 0.5f) + cutOffY, 0);
paddingY = Mathf.Min(paddingY, deltaY);
nTex.ReadPixels(new Rect(paddingX, paddingY, cutWidth, cutHeight), 0, 0);
nTex.Apply();
RenderTexture.active = lastRt;
RenderTexture.ReleaseTemporary(rt);
return nTex;
}
4. Texture2D 90度旋转
public static Texture2D RotateTexture(Texture2D orgTex, bool rotLeft)
{
FilterMode mode = FilterMode.Bilinear;
orgTex.filterMode = mode;
RenderTexture lastRt = RenderTexture.active;
RenderTexture rt = RenderTexture.GetTemporary(orgTex.width, orgTex.height);
rt.filterMode = mode;
RenderTexture.active = rt;
Graphics.Blit(orgTex, rt);
Texture2D newTex = new Texture2D(rt.width, rt.height);
newTex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
newTex.Apply();
RenderTexture.active = lastRt;
RenderTexture.ReleaseTemporary(rt);
newTex = InnerRotateTexture(newTex, rotLeft);
return newTex;
}
private static Texture2D InnerRotateTexture(Texture2D orgTex, bool rotLeft)
{
int width = orgTex.width, height = orgTex.height;
Color32[] orgColors = orgTex.GetPixels32();
Texture2D newTex = new Texture2D(height, width);
Color32[] newColors = newTex.GetPixels32();
for (int i = 0; i < width - 1; i++)
{
for (int j = 0; j < height - 1; j++)
{
int x = rotLeft ? height - 1 - j : j, y = rotLeft ? i : width - 1 - i;
newColors[y * height + x] = orgColors[j * width + i];
}
}
newTex.SetPixels32(newColors);
newTex.Apply();
return newTex;
}
或
public static Texture2D RotateFlipTexture(Texture2D orgTex, bool isFlip = false)
{
int width = orgTex.width, height = orgTex.height;
Color32[] orgColors = orgTex.GetPixels32();
Texture2D newTex = new Texture2D(height, width);
Color32[] newColors = newTex.GetPixels32();
for (int i = 0; i < width - 1; i++)
{
for (int j = 0; j < height - 1; j++)
{
int x = isFlip ? height - 1 - j : j, y = isFlip ? i : width - 1 - i;
if (isFlip) x = height - x;
newColors[y * height + x] = orgColors[j * width + i];
}
}
newTex.SetPixels32(newColors);
newTex.Apply();
return newTex;
}
5. 调用Android代码
/**
* "com.unity3d.player.UnityPlayerActivity"为需要调用的方法所在类的路径(包名+类名);
* "mInstance"为对应类记录的实例变量,根据变量是否是static,可调用 GetStatic 或 Get;
*/
public static AndroidJavaObject GetCurActivity()
{
AndroidJavaClass javaCls = new AndroidJavaClass("com.unity3d.player.UnityPlayerActivity");
AndroidJavaObject curActivity = javaCls.GetStatic("mInstance");
return curActivity;
}
/**
* "funcName"为需要调用的方法名称;
* param为方法需要传入的参数;
* 根据方法是否为static,可调用 CallStatic 或 Call;
*/
public static T CallFunc(Object param)
{
AndroidJavaObject activity = GetCurActivity();
if (activity != null)
{
return activity.Call("funcName", param);
}
}
6. 单例基类的实现
using UnityEngine;
public class Singleton : MonoBehaviour where T : Singleton
{
private static T instance;
public static T Instance
{
get { return instance; }
}
public static bool IsInitialized
{
get { return instance != null; }
}
protected virtual void Awake()
{
if (instance != null)
Destroy(gameObject);
else
instance = (T)this;
}
protected virtual void OnDestroy()
{
if (instance == this)
{
instance = null;
}
}
}
子类的代码实现:
public class ApiManager : Singleton
{
// ...
}
7. PaveView的实现代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class PageView : MonoBehaviour, IBeginDragHandler, IEndDragHandler
{
public Action OnPageChanged;
public RectTransform tfContent;
public float smoothing = 4;
public float sensitivity = 0;
ScrollRect rect;
bool isDrag = false;
bool isStopMove = true;
int curPageIndex = -1;
float targetHorizontal = 0;
float startDragHorizontal;
float startTime = 0;
List posList = new List();
private void Awake()
{
rect = GetComponent();
}
private void Update()
{
if (!isDrag && !isStopMove)
{
startTime += Time.deltaTime;
float t = startTime * smoothing;
rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition, targetHorizontal, t);
if (t > 1) isStopMove = true;
}
}
public void PageTo(int index)
{
if (index >= 0 && index < posList.Count)
{
rect.horizontalNormalizedPosition = posList[index];
SetPageIndex(index);
GetIndex(index);
}
}
private void SetPageIndex(int index)
{
if (curPageIndex == index) return;
curPageIndex = index;
if (OnPageChanged != null) OnPageChanged(index);
}
private void GetIndex(int index)
{
}
public void AddItem(RectTransform child)
{
child.SetParent(tfContent);
child.localScale = Vector3.one;
}
public void Activate()
{
int count = tfContent.transform.childCount;
var itemW = GetComponent().rect.width;
var tmpWidth = ((float)count * itemW);
tfContent.sizeDelta = new Vector2(tmpWidth, 0);
float widthNotShow = tfContent.rect.width - itemW;
for (int i = 0; i < count; i++)
{
posList.Add(itemW * i / widthNotShow);
}
}
public void OnBeginDrag(PointerEventData eventData)
{
isDrag = true;
startDragHorizontal = rect.horizontalNormalizedPosition;
}
public void OnEndDrag(PointerEventData eventData)
{
float posX = rect.horizontalNormalizedPosition;
posX += ((posX - startDragHorizontal) * sensitivity);
posX = posX < 1 ? posX : 1;
posX = posX > 0 ? posX : 0;
int index = 0;
float offset = Mathf.Abs(posList[index] - posX);
for (int i = 1; i < posList.Count; i++)
{
float tmp = Mathf.Abs(posList[i] - posX);
if (tmp < offset)
{
index = i;
offset = tmp;
}
}
SetPageIndex(index);
GetIndex(index);
targetHorizontal = posList[index];
startTime = 0;
isDrag = false;
isStopMove = false;
}
}
使用:
ScrollView + PageView;
8. Android代码判断权限
private static int PERMISSION_CODE = 1;
private String _unityObjName = "";
private Map permissionResults = new HashMap<>();
public boolean hasPermission(String permission)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
return this.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
}
else
{
return PermissionChecker.checkSelfPermission(this, permission) == PermissionChecker.PERMISSION_GRANTED;
}
}
public void requestPermission(String permission, String objName)
{
_unityObjName = objName;
String[] permissions;
if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permission) || Manifest.permission.READ_EXTERNAL_STORAGE.equals((permission)))
{
permissions = new String[] {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
};
}
else
{
permissions = new String[] {permission};
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
this.requestPermissions(permissions, PERMISSION_CODE);
}
else
{
ActivityCompat.requestPermissions(this, permissions, PERMISSION_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode != PERMISSION_CODE) return;
for (int i = 0; i < permissions.length; i++)
{
String permission = permissions[i];
int grantResult = grantResults[i];
boolean granted = (grantResult == PackageManager.PERMISSION_GRANTED);
if (granted)
{
sendUnityMessage("OnPermissionAccepted", permission);
}
else
{
sendUnityMessage("OnPermissionDenied", permission);
}
if (permissionResults.containsKey(permission))
permissionResults.remove(permission);
permissionResults.put(permission, granted);
}
}
/**
* Used for Android M bellowing
* @param permission
* @return
*/
public boolean isPermissionGranted(String permission)
{
if (isAboveAndroidM()) return false;
return permissionResults.get(permission);
}
private void sendUnityMessage(String funcName, String param)
{
UnityPlayer.UnitySendMessage(_unityObjName, funcName, param);
}
9. Android跳转当前应用的设置详情
public void goCurrentAppSettings()
{
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", getPackageName(), null));
startActivity(intent);
}
10. Android调用Unity的C#代码
UnityPlayer.UnitySendMessage(scriptName, funcName, stringParam);