换装+轮转图+无限滑动
换装
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>();
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];
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>();
Texture2D[] textures2Ds = new Texture2D[skinnes.Length];
for (int i = 0; i < skinnes.Length; i++)
{
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;
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
for (int i = 0; i < skinnes.Length; i++)
{
skinnes[i].sharedMesh.uv = old[i];
}
}
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;
}
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();
});
});
}
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;
}
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.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
{
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;
public enum Direction
{
horizontal,
vertical,
}
public class UnlimitedSliding<T> : MonoBehaviour
{
private RectTransform self;
public 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>();
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)
{
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))
{
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))
{
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;
}
}
}