王者荣耀选择皮肤的效果大家都应该知道吧。一张张的卡片选择,今天给大家一个类,就可以实现这个功能。功能只提供了一些基本的,根据需求不同,也要各位自己做扩展。废话不多说,看代码
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using DG.Tweening;
using System;
enum FINGER { FINGER_STATE_NUL, FINGER_STATE_TOUCH, FINGER_STATE_ADD }
public class CardMove : MonoBehaviour
{
private GameObject[] sprites;
private int halfSize;
Vector2 screenCenterPos;
public float startAngle = -90;//中间卡牌的角度
float deltaAngle = 20;//相邻卡牌的角度差值
/* public float moveSpeed;//移动动画的速度*/
public string currentSelectName;
public Vector2 center;//椭圆中心点
public float Y_axis = 400;//long axis
public float X_axis = 100;//short axis
private int cardcount;//卡牌数量
private float fingerActionSensitivity = Screen.width * 0.05f; //手指动作的敏感度,这里设定为 二十分之一的屏幕宽度.
private float fingerBeginX;
private float fingerBeginY;
private float fingerCurrentX;
private float fingerCurrentY;
private float fingerSegmentX;
private float fingerSegmentY;
private FINGER fingerTouchState;
float angle;
public float mouseSpeed = 1;
public Action MoveEndAction;
void Start()
{
deltaAngle = Screen.width / 100f;
Y_axis = Screen.width / 2;
UpdateChild();
}
/// <summary>
/// 初始化卡牌显示位置
/// </summary>
void InitSprites()
{
screenCenterPos = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
cardcount = transform.childCount;
halfSize = (cardcount - 1) / 2;
sprites = new GameObject[cardcount];
for (int i = 0; i < cardcount; i++)
{
sprites[i] = transform.GetChild(i).gameObject;
SetPosition(i, false);
SetDeeps(i);
}
}
/// <summary>
/// 椭圆的半长轴为A,半短轴为B,计算椭圆上一点的位置
/// x=A*cos(angle),y=B*sin(angle)
/// </summary>
/// <param name="index">Index.</param>
/// <param name="userTweener">是否使用tween动画.</param>
void SetPosition(int index, bool userTweener = true)
{
//计算每一张卡片在椭圆上相对中间卡牌的角度
angle = 0;
if (index < halfSize)
{//left
angle = startAngle - (halfSize - index) * deltaAngle;
sprites[index].GetComponent<RectTransform>().DOScale(1f, 0.3f);
}
else if (index > halfSize)
{//right
angle = startAngle + (index - halfSize) * deltaAngle;
sprites[index].GetComponent<RectTransform>().DOScale(1f, 0.3f);
}
else
{//medim
angle = startAngle;
sprites[index].GetComponent<RectTransform>().DOScale(1.5f, 0.3f).OnComplete(MoveEnd);
}
//通过卡牌的角度,计算对应的位置
float xpos = Y_axis * Mathf.Cos((angle / 180) * Mathf.PI) + center.x;
float ypos = X_axis * Mathf.Sin((angle / 180) * Mathf.PI) + center.y;
Vector2 pos = new Vector2(xpos, ypos);
// Vector2 pos = new Vector2(center.x, center.y);
if (!userTweener)
{
sprites[index].GetComponent<RectTransform>().DOMove(new Vector2(screenCenterPos.x + pos.x, screenCenterPos.y + pos.y), 0f);
}
else
sprites[index].GetComponent<RectTransform>().DOMove(new Vector2(screenCenterPos.x + pos.x, screenCenterPos.y + pos.y), 0.2f);
}
/// <summary>
/// 选择移动动画结束后的设置当前选择的名字和回调
/// </summary>
void MoveEnd()
{
currentSelectName = transform.GetChild(transform.childCount - 1).name;
if (MoveEndAction != null) MoveEndAction();
}
/// <summary>
/// 计算每一张卡片的层级
/// </summary>
/// <param name="index">Index.</param>
void SetDeeps(int index)
{
int deep = 0;
if (index < halfSize)
{//左侧卡牌层级,从左侧到中间,层级依此递增
deep = index;
}
else if (deep > halfSize)
{//右侧卡牌层级,从中间到右侧,层级依此递减
deep = sprites.Length - (index + 1);
}
else
{
deep = halfSize;
}
sprites[index].GetComponent<RectTransform>().SetSiblingIndex(deep);
}
public void LeftMove()
{
int length = sprites.Length;
GameObject temp = sprites[0];
for (int i = 0; i < length; i++)
{//移动卡片在数组中的位置,依此向前移动一位
if (i == length - 1)
sprites[i] = temp;
else
sprites[i] = sprites[i + 1];
}
for (int i = 0; i < length; i++)
{//更新数组卡片需要显示的位置和层级
if (i < length - 1) SetPosition(i);
else SetPosition(i, false);
SetDeeps(i);
}
}
public void RightMove()
{
int length = sprites.Length;
GameObject temp = sprites[length - 1];
for (int i = length - 1; i >= 0; i--)
{
if (i == 0)
sprites[i] = temp;
else
sprites[i] = sprites[i - 1];
}
for (int i = 0; i < length; i++)
{
if (i == 0) SetPosition(i, false);
else SetPosition(i);
SetDeeps(i);
}
}
private void Update()
{
CheckMouse();
}
private void AddFingerAction()
{
fingerTouchState = FINGER.FINGER_STATE_ADD;
if (Mathf.Abs(fingerSegmentX) > Mathf.Abs(fingerSegmentY))
{
fingerSegmentY = 0;
}
else
{
fingerSegmentX = 0;
}
if (fingerSegmentY == 0)
{
if (fingerSegmentX > 0)
{
RightMove();
}
else
{
LeftMove();
}
}
}
readonly string MYMouseScrollWheel = "Mouse ScrollWheel";
float timer, axis;//timer可以防止快速滚轮导致速度过快动画得bug
void CheckMouse()
{
switch (fingerTouchState)
{
case FINGER.FINGER_STATE_NUL:
if (Input.GetKeyDown(KeyCode.Mouse0))
{
fingerTouchState = FINGER.FINGER_STATE_TOUCH;
fingerBeginX = Input.mousePosition.x;
fingerBeginY = Input.mousePosition.y;
}
break;
case FINGER.FINGER_STATE_TOUCH:
fingerCurrentX = Input.mousePosition.x;
fingerCurrentY = Input.mousePosition.y;
fingerSegmentX = fingerCurrentX - fingerBeginX;
fingerSegmentY = fingerCurrentY - fingerBeginY;
float fingerDistance = fingerSegmentX * fingerSegmentX + fingerSegmentY * fingerSegmentY;
if (fingerDistance > (fingerActionSensitivity * fingerActionSensitivity))
{
AddFingerAction();
}
break;
case FINGER.FINGER_STATE_ADD:
break;
}
if (Input.GetKeyUp(KeyCode.Mouse0))
{
fingerTouchState = FINGER.FINGER_STATE_NUL;
}
timer += Time.deltaTime;
axis = Input.GetAxis(MYMouseScrollWheel);
if (axis > 0 && timer > 0.2f)
{
timer = 0;
LeftMove();
}
else if (axis < 0 && timer > 0.2f)
{
timer = 0;
RightMove();
}
}
void InitData()
{
fingerActionSensitivity = Screen.width * 0.05f;
fingerBeginX = 0;
fingerBeginY = 0;
fingerCurrentX = 0;
fingerCurrentY = 0;
fingerSegmentX = 0;
fingerSegmentY = 0;
}
public void UpdateChild()
{
InitSprites();
InitData();
}
}
原文链接:https://blog.csdn.net/terrysandra/java/article/details/88885595