换装+轮转图+无限滑动

换装+轮转图+无限滑动

换装

using System.Collections.Generic;
using UnityEngine;

public class SelectAvatar : MonoBehaviour
{
    public GameObject Avatar;

    public GameObject[] heads;
    public GameObject[] bodys;
    public GameObject[] legs;
    public Texture2D[] faces;

    int headIndex = 0;
    int bodyIndex = 0;
    int legsIndex = 0;
    int faceIndex = 0;

    int texMax = 1024;

    Dictionary<string, GameObject> objectDic = new Dictionary<string, GameObject>();

    // Start is called before the first frame update
    void Start()
    {
        Refresh();
    }

    public void SetHead(int index)
    {
        headIndex = index;
        Refresh();
    }

    public void SetBody(int index)
    {
        bodyIndex = index;
        Refresh();
    }

    public void SetLeg(int index)
    {
        legsIndex = index;
        Refresh();
    }

    GameObject LoadGameObject(string name, GameObject go)
    {
        if (objectDic.ContainsKey(name))
        {
            return objectDic[name];
        }
        else
        {
            GameObject game = Instantiate(go);
            objectDic.Add(name, game);
            game.SetActive(false);
            return game;
        }
    }

    void Refresh()
    {
        SkinnedMeshRenderer[] skinnes = new SkinnedMeshRenderer[3];//body.GetComponentsInChildren<SkinnedMeshRenderer>();
        GameObject head = LoadGameObject(heads[headIndex].name, heads[headIndex]);
        skinnes[0] = head.GetComponentInChildren<SkinnedMeshRenderer>();
        GameObject body = LoadGameObject(bodys[bodyIndex].name, bodys[bodyIndex]);
        skinnes[1] = body.GetComponentInChildren<SkinnedMeshRenderer>();
        GameObject leg = LoadGameObject(legs[legsIndex].name, legs[legsIndex]);
        skinnes[2] = leg.GetComponentInChildren<SkinnedMeshRenderer>();
        //Material[] materials = new Material[meshFilters.Length];

        Texture2D[] textures2Ds = new Texture2D[skinnes.Length];
        for (int i = 0; i < skinnes.Length; i++)
        {
            //materials[i] = skinnes[i].gameObject.GetComponent<Renderer>().material;
            textures2Ds[i] = skinnes[i].material.GetTexture("_BackTex") as Texture2D;
        }

        Texture2D texture = new Texture2D(512, 512, TextureFormat.ARGB32, false);
        Rect[] rects = texture.PackTextures(textures2Ds, 0);
        List<Vector2[]> old = new List<Vector2[]>();
        for (int i = 0; i < skinnes.Length; i++)
        {
            Vector2[] olduvs = skinnes[i].sharedMesh.uv;
            old.Add(olduvs);
            Vector2[] newuvs = new Vector2[olduvs.Length];
            for (int j = 0; j < olduvs.Length; j++)
            {
                newuvs[j] = new Vector2(olduvs[j].x * rects[i].width + rects[i].x, olduvs[j].y * rects[i].height + rects[i].y);
            }
            skinnes[i].sharedMesh.uv = newuvs;
        }

        CombineInstance[] instances = new CombineInstance[skinnes.Length];
        for (int i = 0; i < skinnes.Length; i++)
        {
            instances[i].mesh = skinnes[i].sharedMesh;
            instances[i].transform = skinnes[i].transform.localToWorldMatrix;
        }

        SkinnedMeshRenderer skinnedMesh;// = Avatar.AddComponent<SkinnedMeshRenderer>();
        if (!Avatar.TryGetComponent(out skinnedMesh))
        {
            skinnedMesh = Avatar.AddComponent<SkinnedMeshRenderer>();
        }
        skinnedMesh.sharedMesh = new Mesh();
        skinnedMesh.sharedMesh.CombineMeshes(instances, true, false);
        skinnedMesh.material = new Material(Shader.Find("Custom/Face"));
        skinnedMesh.material.SetTexture("_BackTex", texture);
        skinnedMesh.material.SetTexture("_MainTex", faces[faceIndex]);
        skinnedMesh.material.SetFloat("_PosX", texture.width / texMax * 4);
        skinnedMesh.material.SetFloat("_PosY", texture.height / texMax * 4);
        #region//绑定骨骼
        Transform[] bones = Avatar.GetComponentsInChildren<Transform>(true);
        Dictionary<string, Transform> boneDic = new Dictionary<string, Transform>();
        for (int i = 0; i < bones.Length; i++)
        {
            boneDic.Add(bones[i].name, bones[i]);
        }
        List<Transform> allbones = new List<Transform>();
        for (int i = 0; i < skinnes.Length; i++)
        {
            for (int j = 0; j < skinnes[i].bones.Length; j++)
            {
                if (boneDic.ContainsKey(skinnes[i].bones[j].name))
                {
                    allbones.Add(boneDic[skinnes[i].bones[j].name]);
                }
            }
        }
        skinnedMesh.bones = allbones.ToArray();
        #endregion
        //MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
        //meshFilter.mesh = new Mesh();
        //meshFilter.mesh.CombineMeshes(combines, true, true);

        //Material newMaterial = new Material(Shader.Find("Standard"));
        //MeshRenderer meshRenderer = gameObject.AddComponent<MeshRenderer>();
        //meshRenderer.material = newMaterial;
        //meshRenderer.material.mainTexture = texture;
        for (int i = 0; i < skinnes.Length; i++)
        {
            skinnes[i].sharedMesh.uv = old[i];
        }
        //获取模型图片写入到本地
        //for (int i = 0; i < heads.Length; i++)
        //{
        //    UnityEditor.EditorUtility.SetDirty(heads[i]);
        //    Texture2D img = UnityEditor.AssetPreview.GetAssetPreview(heads[i]);
        //    if (!System.IO.Directory.Exists(Application.dataPath + "/Resources/tou"))
        //    {
        //        System.IO.Directory.CreateDirectory(Application.dataPath + "/Resources/tou");
        //    }
        //    System.IO.File.WriteAllBytes(Application.dataPath + "/Resources/tou/tou_" + i + ".png", img.EncodeToPNG());
        //}
    }

    public void OnBtnChange(int i)
    {
        switch (i)
        {
            case 0:
                headIndex += 1;
                headIndex %= heads.Length;
                break;
            case 1:
                bodyIndex += 1;
                bodyIndex %= bodys.Length;
                break;
            case 2:
                legsIndex += 1;
                legsIndex %= legs.Length;
                break;
            case 3:
                faceIndex += 1;
                faceIndex %= faces.Length;
                break;
            default:
                break;
        }
        //headIndex = i;
        Refresh();
    }
}

轮转图

using DG.Tweening;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class RotationDiagram<T> : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    public float padding = 0;
    public float scaleMax = 1;
    public float scaleMin = 1;

    public GameObject prefab;
    protected float len;
    protected float r;
    protected T[] arr;
    protected List<GameObject> games = new List<GameObject>();
    protected List<Transform> trans = new List<Transform>();
    protected Vector2 beginpos;
    protected float moveW;
    protected Tweener tweener;

    public void OnBeginDrag(PointerEventData eventData)
    {
        tweener.Kill();
        //记录鼠标起始位置
        beginpos = eventData.position;
    }

    public void OnDrag(PointerEventData eventData)
    {
        //计算滑动距离
        moveW += eventData.position.x - beginpos.x;
        //重置起始位置
        beginpos = eventData.position;
        //滚动
        LookData(moveW);
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        tweener = DOTween.To((a) =>
        {
            moveW += a; //
            LookData(moveW);
        }, eventData.delta.x, 0, 1f).SetEase(Ease.OutQuad).OnComplete(() =>
        {
            float x = trans[trans.Count - 1].GetComponent<RectTransform>().anchoredPosition.x;
            float d = Mathf.Sin(x / r) / (2 * Mathf.PI) * len;
            //做结束的缓动
            tweener = DOTween.To((a) =>
            {
                LookData(a);
            }, moveW, moveW - d, 1f).SetEase(Ease.OutQuad).OnComplete(() =>
            {
                trans[trans.Count - 1].GetComponent<TableCell>().OnChange();
            });
        });
    }

    public void OnBtnDown(int num)
    {
        tweener.Kill();
        int id = num % arr.Length;
        float d = (int.Parse(trans[trans.Count - 1].name) - id) * (len / arr.Length);
        tweener = DOTween.To((a) =>
        {
            LookData(a);
            moveW = a;
        }, moveW, moveW + d, 1f).SetEase(Ease.OutQuad).OnComplete(() =>
        {
            float x = trans[trans.Count - 1].GetComponent<RectTransform>().anchoredPosition.x;
            float d = Mathf.Sin(x / r) / (2 * Mathf.PI) * len;
            //做结束的缓动
            tweener = DOTween.To((a) =>
            {
                LookData(a);
            }, moveW, moveW - d, 1f).SetEase(Ease.OutQuad).OnComplete(() =>
            {
                trans[trans.Count - 1].GetComponent<TableCell>().OnChange();
            });
            //games2[games2.Count - 1].GetComponent<TableCell>().OnChange();
        });
    }

    public void Init(T[] arr)
    {
        this.arr = arr;
        len = (prefab.GetComponent<RectTransform>().rect.width + padding) * arr.Length;
        r = len / (2 * Mathf.PI);
        LookData(0);
    }

    protected void LookData(float moveW)
    {
        moveW %= len;
        float moveAng = (moveW / len) * 2 * Mathf.PI;
        float ang = 2 * Mathf.PI / arr.Length;
        for (int i = 0; i < arr.Length; i++)
        {
            float x = Mathf.Sin(ang * i + moveAng) * r;
            float z = Mathf.Cos(ang * i + moveAng) * r + r;
            float scale = (z / (2 * r)) * (scaleMax - scaleMin) + scaleMin;
            if (i < games.Count && games[i] != null)
            {
                RectTransform rectTran = games[i].GetComponent<RectTransform>();
                rectTran.anchoredPosition = new Vector2(x, 0);
                rectTran.localScale = Vector3.one * scale;
                //games[i].transform.SetSiblingIndex((int)(z * 10));
            }
            else
            {
                GameObject go = Instantiate(prefab, transform);
                go.name = i.ToString();
                RectTransform rectTran = go.GetComponent<RectTransform>();
                rectTran.anchoredPosition = new Vector2(x, 0);
                rectTran.localScale = Vector3.one * scale;
                //go.transform.SetSiblingIndex((int)(z * 10));
                go.GetComponent<TableCell>().Init(arr[i]);
                games.Add(go);
                trans.Add(go.transform);
            }
        }
        Comparison<Transform> comparison = new Comparison<Transform>((Transform a, Transform b) =>
        {
            if (a.localScale.x > b.localScale.x)
            {
                return 1;
            }
            //else if(a.localScale.x == b.localScale.x)
            //{
            //    return 0;
            //}
            else
            {
                return -1;
            }
        });
        trans.Sort(comparison);
        for (int i = 0; i < games.Count; i++)
        {
            trans[i].SetSiblingIndex(i);
        }
    }
}

无限滑动

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 表示无限滑动方向的枚举
/// </summary>
public enum Direction
{
    horizontal,
    vertical,
}
/// <summary>
/// 无限滑动列表的基类
/// </summary>
/// <typeparam name="T">传给TableCell对象的数据的类型</typeparam>
public class UnlimitedSliding<T> : MonoBehaviour
{
    private RectTransform self;//当前scrollView的RectTransform
    public ScrollRect scrollRect;//用到的scrollRect
    public RectOffset padding;//与父级的上下左右间隔
    public float spacing;//两个子物体之间的间隔
    public Direction direction = Direction.horizontal;//默认横向滑动
    Dictionary<Rect, T> dataDic = new Dictionary<Rect, T>();//存数据的字典
    Dictionary<Rect, GameObject> lookDic = new Dictionary<Rect, GameObject>();//存子物体的字典
    public RectTransform tableCell;//子物体

    public virtual void Start()
    {
        self = GetComponent<RectTransform>();
        //设置content的锚点和中心点
        scrollRect.content.anchorMin = new Vector2(0.5f, 0.5f);
        scrollRect.content.anchorMax = new Vector2(0.5f, 0.5f);
        scrollRect.content.pivot = new Vector2(0.5f, 0.5f);
        scrollRect.horizontalScrollbar.value = 0;
        //监听滑动的事件
        scrollRect.onValueChanged.AddListener((Vector2 v) =>
        {
            LookData();
        });
    }

    public void Init(T[] arr)
    {
        //根据滑动方向计算content大小和记录子物体的位置
        switch (direction)
        {
            case Direction.horizontal:
                {
                    float width = padding.left + arr.Length * (tableCell.rect.width + spacing) - spacing + padding.right;
                    float height = padding.top + tableCell.rect.height + padding.bottom;
                    scrollRect.content.sizeDelta = new Vector2(width, height);
                    //把所有子物体的位置一次性计算完成保存在字典中
                    for (int i = 0; i < arr.Length; i++)
                    {
                        Vector2 pos = new Vector2(padding.left + i * (tableCell.rect.width + spacing) + tableCell.rect.width / 2 - width / 2, 0);
                        Rect rect = new Rect(pos, tableCell.sizeDelta);
                        dataDic.Add(rect, arr[i]);
                    }
                }
                break;
            case Direction.vertical:
                {
                    float width = padding.left + tableCell.rect.width + padding.right;
                    float height = padding.top + arr.Length * (tableCell.rect.height + spacing) - spacing + padding.bottom;
                    scrollRect.content.sizeDelta = new Vector2(width, height);
                    for (int i = 0; i < arr.Length; i++)
                    {
                        Vector2 pos = new Vector2(0, padding.top + i * (tableCell.rect.height + spacing) + tableCell.rect.height / 2 - height / 2);
                        Rect rect = new Rect(pos, tableCell.sizeDelta);
                        dataDic.Add(rect, arr[i]);
                    }
                }
                break;
            default:
                break;
        }
        LookData();
    }

    private void LookData()
    {
        Rect rect = new Rect(-scrollRect.content.anchoredPosition.x, -scrollRect.content.anchoredPosition.y, self.rect.width, self.rect.height);

        Dictionary<Rect, T> dic = new Dictionary<Rect, T>();

        foreach (var item in dataDic)
        {
            if (rect.Overlaps(item.Key))//IsLap(rect, item.Key))
            {
                if (!lookDic.ContainsKey(item.Key))
                {
                    dic.Add(item.Key, item.Value);
                }
            }
        }

        foreach (var item in dic)
        {
            GameObject cell = null;
            foreach (var look in lookDic)
            {
                if (!rect.Overlaps(look.Key))//!IsLap(rect, look.Key))
                {
                    cell = look.Value;
                    cell.GetComponent<RectTransform>().anchoredPosition = new Vector2(item.Key.x, item.Key.y);
                    cell.GetComponent<TableCell>().Init(item.Value);
                    lookDic.Remove(look.Key);
                    lookDic.Add(item.Key, cell);
                    break;
                }
            }
            if (cell == null)
            {
                cell = Instantiate(tableCell.gameObject, scrollRect.content);
                cell.GetComponent<RectTransform>().anchoredPosition = new Vector2(item.Key.x, item.Key.y);
                cell.GetComponent<TableCell>().Init(item.Value);
                lookDic.Add(item.Key, cell);
            }
        }
    }

    private bool IsLap(Rect rc1, Rect rc2)
    {
        float rect1MinX = rc1.x - rc1.width / 2;
        float rect1MaxX = rc1.x + rc1.width / 2;
        float rect1MinY = rc1.y - rc1.height / 2;
        float rect1MaxY = rc1.y + rc1.height / 2;

        float rect2MinX = rc2.x - rc2.width / 2;
        float rect2MaxX = rc2.x + rc2.width / 2;
        float rect2MinY = rc2.y - rc2.height / 2;
        float rect2MaxY = rc2.y + rc2.height / 2;

        if (rect1MinX < rect2MaxX &&
            rect2MinX < rect1MaxX &&
            rect1MinY < rect2MaxY &&
            rect2MinY < rect1MaxY)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值