Unity2D轮转图换装

合并网格

把多个物体的网格合并在一起,同时进行贴图,下面是简单的合并网格

    public List<GameObject> list;
    public List<CombineInstance> combines = new List<CombineInstance>();
    public Dictionary<string, Transform> bonesDic = new Dictionary<string, Transform>();
    public List<Material> materialList = new List<Material>();
    public List<Transform> bones = new List<Transform>();
    public Transform[] mybones;      

    privat void Satrt
    {

         Mesh mesh = new Mesh();
        //找到我身上的所有骨骼
        mybones = GetComponentsInChildren<Transform>();
        //把我身上的所有骨骼添加到字典里面  后续需要查找
        foreach (var item in mybones)
        {
            bonesDic.Add(item.name, item);
        }

        for (int i = 0; i < list.Count; i++)
        {
            CombineInstance instance = new CombineInstance();
            instance.mesh = list[i].GetComponentInChildren<SkinnedMeshRenderer>                        ().sharedMesh;
            instance.transform = list[i].transform.localToWorldMatrix;
            combines.Add(instance);
            materialList.Add(list[i].GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial);
            //循环我每个预制体上的骨骼  返回一个 Transform类型的数组
            foreach (var item in list[i].GetComponentInChildren<SkinnedMeshRenderer>().bones)
            {
                //如果字典中存在这个名字  添加到我身上的数组
                if (bonesDic.ContainsKey(item.name))
                {
                    bones.Add(bonesDic[item.name]);
                }
            }
        }

        mesh.CombineMeshes(combines.ToArray(), false, false);
        GetComponent<SkinnedMeshRenderer>().sharedMesh = mesh;
        GetComponent<SkinnedMeshRenderer>().bones = bones.ToArray();
        GetComponent<SkinnedMeshRenderer>().materials = materialList.ToArray();
}

       

Unity2D轮转图


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using DG.Tweening;
using UnityEngine.UI;
 
public class Rotationchart2D : MonoBehaviour, IDragHandler, IEndDragHandler
{
    public GameObject prefab;
    //图片数量
    public int num;
    //半径
    float r;
    //差值
    float max = 1;
    float min = 0.5f;
    //间距 (单位是像素)
    float padding = 50;
    //移动弧度
    float moveAngle = 0;
    float angle;
    //减速度
    float cutSpeed = 50;
    List<GameObject> list = new List<GameObject>();
    List<Transform> trans = new List<Transform>();
    // Start is called before the first frame update
    void Start()
    {
        angle = 2 * Mathf.PI / num;
        //算出合适的生成半径
        r = (prefab.GetComponent<RectTransform>().sizeDelta.x + padding) * num / (2 * Mathf.PI);
        OnMove();
       
    }
    public void OnMove()
    {
        for (int i = 0; i < num; i++)
        {
            float x = Mathf.Sin(angle * i + moveAngle) * r;
            float z = Mathf.Cos(angle * i + moveAngle) * r;
            if (list.Count < num)
            {
                GameObject go = Instantiate(prefab, transform);
                go.name = i.ToString();
                list.Add(go);
                trans.Add(go.transform);
            }
            list[i].transform.localPosition = new Vector3(x, 0, 0);
            //跟据  z值(距离摄像机前后) / 直径 来求出比例  *  差值  + min 最小值不能小于min限制   求出缩放比
            float scale = (z + r) / (2 * r) * (max - min) + min;
            list[i].transform.localScale = Vector3.one * scale;
        }
        //根据图片缩放排序更改层级
        trans.Sort((a, b) => { return (int)(a.transform.localScale.z * 100 - b.transform.localScale.z * 100); });
        for (int j = 0; j < trans.Count; j++)
        {
            trans[j].transform.SetSiblingIndex(j);
        }
    }
 
    public void OnDrag(PointerEventData eventData)
    {
        float dis = eventData.delta.x;
        //需要转动的弧度数
        float angle = dis / r;
        //3D和2D的区别
        //3D时 z越小离摄像机越近 因为相机放在了-10的位置上  所以-=
        //2D时 z越大离摄像机越近 所以+=
        moveAngle += angle;
        OnMove();
    }
    /// <summary>
    /// 惯性向前  并对齐
    /// </summary>
    /// <param name="eventData"></param>
    public void OnEndDrag(PointerEventData eventData)
    {
        // eventData.delta.x会有负值
        // 惯性时间
        float moveTime = Mathf.Abs(eventData.delta.x / cutSpeed);
        DOTween.To((a) =>
        {
            //调用drag方法
            float angel = a / r;
            moveAngle += angel;
            OnMove();
        }, eventData.delta.x, 0, moveTime).OnComplete(() =>
        {
            //当前z值最大的  离摄像机最近  自动对齐
            Align(list.IndexOf(trans[num - 1].gameObject));
        });
    }
    /// <summary>
    /// 对齐方法
    /// </summary>
    /// <param name="n"></param>
    public void Align(int n)
    {
        int index = list.IndexOf(trans[num - 1].gameObject);
        int zheng = n - index;
        int fan = num - Mathf.Abs(zheng);
        fan = zheng < 0 ? fan : -fan;
        int insert = Mathf.Abs(zheng) < Mathf.Abs(fan) ? zheng : fan;
        float insertAngle = insert * angle;
        //得到弧长
        float alignAngel = Mathf.Asin(trans[num - 1].localPosition.x / r) + insertAngle;
        float moveTime = Mathf.Abs(alignAngel * r / cutSpeed);
        DOTween.To((a) =>
        {
            moveAngle = a;
            OnMove();
        }, moveAngle, moveAngle - alignAngel, 2);
    }
 
}

Unity2D轮转图换装

轮转图换装是在合并网格和轮转图的基础上进行的,下面是代码演示

代码演示

轮转图代码

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

public class Cyclogram : MonoBehaviour, IDragHandler, IEndDragHandler
{
    public List<GameObject> list = new List<GameObject>();
    public List<GameObject> sortList = new List<GameObject>();
    public List<Sprite> icon;
    public GameObject obj;
    float angle;
    public int num;
    public float r;
    float max = 1;
    float min = 0.5f;
    public float angleMove = 0;
    public GameObject prefab;
    public int index = 0;
    public static Cyclogram instance;
    //玩家根骨骼
    public GameObject player;
    //需要更换的材质
    public GameObject[] materials;
    private void Awake()
    {
        instance = this;
    }
    private void Start()
    {
        //弧度
        angle = 2 * Mathf.PI / num;
        //求出合适半径
        r = (obj.GetComponent<RectTransform>().sizeDelta.x + 50) * num / (2 * Mathf.PI);


        //EditorUtility.SetDirty(prefab);
        //Texture2D image = AssetPreview.GetAssetPreview(prefab);
        //System.IO.File.WriteAllBytes(Application.dataPath+ "/Resources/" + "YF3.png", image.EncodeToPNG());
    }
    public void OnMove()
    {

        for (int i = 0; i < num; i++)
        {

            if (list.Count <= i)
            {

                GameObject go = Instantiate(obj, transform);
                go.GetComponent<Image>().sprite = icon[i];
                list.Add(go);
                sortList.Add(go);
            }
            float x = Mathf.Sin(angle * i + angleMove) * r;
            float z = Mathf.Cos(angle * i + angleMove) * r;
            list[i].transform.localPosition = new Vector3(x, 0, z);
            //近大远小区别谁在前后
            float scale = (z + r) / (2 * r) * (max - min) + min;
            list[i].transform.localScale = Vector3.one * scale;
        }
        //排序并且设置层级
        sortList.Sort((a, b) => (int)(a.transform.localScale.z * 100 - b.transform.localScale.z * 100));
        for (int i = 0; i < sortList.Count; i++)
        {
            sortList[i].transform.SetSiblingIndex(i);
        }
    }
    private void Update()
    {
        OnMove();
    }

    public void OnDrag(PointerEventData eventData)
    {
        float dis = eventData.delta.x;
        float ang = dis / r;
        angleMove += ang;
        OnMove();
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        //求出最近的弧度
        float interver = Mathf.Asin(sortList[num - 1].transform.localPosition.x / r);
        DOTween.To((a) =>
        {
            angleMove = a;
            OnMove();
        }, angleMove, angleMove - interver, 1f).OnComplete(() =>
        {
            //求出最近在原集合中的下标
            index = list.IndexOf(sortList[num - 1]);
            //改变材质
            player.GetComponent<CombineMesh>().ChangeBones(index);
        });
    }
}

合并网格代码

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

public class CombineMesh : MonoBehaviour
{
    public List<GameObject> list;
    public List<CombineInstance> combines = new List<CombineInstance>();
    public List<Material> materials = new List<Material>();
    public List<GameObject> changeMater = new List<GameObject>();
    List<Transform> bones = new List<Transform>();
    Transform[] mybones;
    Dictionary<string, Transform> bonesDic = new Dictionary<string, Transform>();
    Mesh mesh;
    private void Start()
    {
        mesh = new Mesh();
        //获取根骨骼下的所有带Transform的对象
        mybones = GetComponentsInChildren<Transform>();
        //加入到字典当中 方便查找
        foreach (var item in mybones)
        {
            bonesDic.Add(item.name, item);
        }

        for (int i = 0; i < list.Count; i++)
        {
            CombineInstance instance = new CombineInstance();
            instance.mesh = list[i].GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh;
            instance.transform = list[i].transform.localToWorldMatrix;
            combines.Add(instance);
            materials.Add(list[i].GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial);

            //循环对象下所有的骨骼
            foreach (var item in list[i].GetComponentInChildren<SkinnedMeshRenderer>().bones)
            {
                //字典中存在  加入到数组中
                if (bonesDic.ContainsKey(item.name))
                {
                    bones.Add(bonesDic[item.name]);
                }
            }
        }


        mesh.CombineMeshes(combines.ToArray(), false, false);
        GetComponent<SkinnedMeshRenderer>().sharedMesh = mesh;
        GetComponent<SkinnedMeshRenderer>().bones = bones.ToArray();
        GetComponent<SkinnedMeshRenderer>().materials = materials.ToArray();
    }
    public void ChangeBones(int index)
    {
        list[0] = changeMater[index];
        List<CombineInstance> newCombines = new List<CombineInstance>();

        for (int i = 0; i < list.Count; i++)
        {
            CombineInstance instance = new CombineInstance();
            instance.mesh = list[i].GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh;
            instance.transform = list[i].transform.localToWorldMatrix;
            newCombines.Add(instance);
        }
        mesh.Clear();
        mesh.CombineMeshes(newCombines.ToArray(), false, false);
        GetComponent<SkinnedMeshRenderer>().sharedMesh = mesh;
        materials[0] = changeMater[index].GetComponent<SkinnedMeshRenderer>().sharedMaterial;
        GetComponent<SkinnedMeshRenderer>().materials = materials.ToArray();
    }
}

效果演示

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值