合并网格
把多个物体的网格合并在一起,同时进行贴图,下面是简单的合并网格
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();
}
}