【持续更新】Unity代码片段积累

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;
}</pre>

# 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<AndroidJavaObject>("mInstance");
    return curActivity;
}

/**
 * "funcName"为需要调用的方法名称;
 * param为方法需要传入的参数;
 * 根据方法是否为static,可调用 CallStatic 或 Call;
 */
public static T CallFunc(Object param)
{
    AndroidJavaObject activity = GetCurActivity();
    if (activity != null)
    {
        return activity.Call<T>("funcName", param);
    }
}

6. 单例基类的实现

using UnityEngine;

public class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
    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<ApiManager>
{
    // ...
}

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<int> 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<float> posList = new List<float>();

    private void Awake()
    {
        rect = GetComponent<ScrollRect>();
    }

    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<RectTransform>().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;

image
image
image

8. Android代码判断权限

private static int PERMISSION_CODE = 1;
private String _unityObjName = "";
private Map<String, Boolean> 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);
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容