阅读量:0
最终效果展示
主要步骤
一. 扇形开牌
二. 鼠标指向卡牌时,卡牌强调动画
①卡牌高度提升
②卡牌旋转归零
③卡牌层级高于其他手牌
三. 卡牌使用效果
1. 攻击类型卡牌
①拖拽超过一定高度之后卡牌会移动到手牌中心位置
②出现攻击引导箭头
③成功指向目标怪物后打出
2. 技能能力类型卡牌
①可自由拖动
②脱离手牌高度后打出
四. 卡牌使用结束效果
1. 播放攻击特效
2. 播放卡牌收尾特效
①卡牌从当前位置移动到中心位置
②卡牌居中悬停展示几毫秒
③播放回归弃牌堆动画
代码详解
一. 扇形开牌
核心代码
public class CardItem : MonoBehaviour { /// <summary> /// 卡牌扇形展开中心点 /// </summary> public Vector3 root; /// <summary> /// 展开角度 /// </summary> public float rot; /// <summary> /// 展开半径 /// </summary> public float size; /// <summary> /// 动画速度 /// </summary> public float animSpeed = 10; /// <summary> /// 高度值(决定卡牌层级) /// </summary> public float zPos=0; public void RefreshData(Vector3 root,float rot, float size,float zPos) { this.root = root; this.rot = rot; this.size = size; this.zPos = -zPos*0.02f; } // Update is called once per frame void Update() { SetPos(); } public void SetPos() { //设置卡牌位置 float x = root.x + Mathf.Cos(rot) * size; float y = root.y + Mathf.Sin(rot) * size; transform.position = Vector3.Lerp(transform.position, new Vector3(x, y, root.z+this.zPos), Time.deltaTime * animSpeed); //设置卡牌角度 float rotZ = GetAngleInDegrees(root, transform.position); Vector3 localEulerAngles = transform.localEulerAngles; Quaternion rotationQuaternion = Quaternion.Euler(new Vector3(0, 0, rotZ)); transform.rotation = Quaternion.RotateTowards(transform.rotation, rotationQuaternion, Time.deltaTime * animSpeed * 30); } /// <summary> /// 获取两个向量之间的弧度值0-2π /// </summary> /// <param name="positionA">点A坐标</param> /// <param name="positionB">点B坐标</param> /// <returns></returns> public static float GetAngleInDegrees(Vector3 positionA, Vector3 positionB) { // 计算从A指向B的向量 Vector3 direction = positionB - positionA; // 将向量标准化 Vector3 normalizedDirection = direction.normalized; // 计算夹角的弧度值 float dotProduct = Vector3.Dot(normalizedDirection, Vector3.up); float angleInRadians = Mathf.Acos(dotProduct); //判断夹角的方向:通过计算一个参考向量与两个物体之间的叉乘,可以确定夹角是顺时针还是逆时针方向。这将帮助我们将夹角的范围扩展到0到360度。 Vector3 cross = Vector3.Cross(normalizedDirection, Vector3.up); if (cross.z > 0) { angleInRadians = 2 * Mathf.PI - angleInRadians; } // 将弧度值转换为角度值 float angleInDegrees = angleInRadians * Mathf.Rad2Deg; return angleInDegrees; }}
public class CardManager : MonoBehaviour { /// <summary> /// 卡牌起始位置 /// </summary> public Vector3 rootPos=new Vector3(0,-33.5f,20); /// <summary> /// 卡牌对象 /// </summary> public GameObject cardItem; /// <summary> /// 扇形半径 /// </summary> public float size =30f; /// <summary> /// 卡牌出现最大位置 /// </summary> private float minPos = 1.415f; /// <summary> /// 卡牌出现最小位置 /// </summary> private float maxPos = 1.73f; /// <summary> /// 手牌列表 /// </summary> private List<CardItem> cardList; /// <summary> /// 手牌位置 /// </summary> private List<float> rotPos; /// <summary> /// 最大手牌数量 /// </summary> private int CardMaxCount=8; void Start() { InitCard(); } /// <summary> /// 数据初始化 /// </summary> public void InitCard() { rotPos=InitRotPos(CardMaxCount); } /// <summary> /// 初始化位置 /// </summary> /// <param name="count"></param> /// <param name="interval"></param> /// <returns></returns> public List<float> InitRotPos(int count) { List<float> rotPos=new List<float>(); float interval = (maxPos - minPos)/count; for (int i = 0; i < count; i++) { float nowPos = maxPos - interval * i; rotPos.Add(nowPos); } return rotPos; } // Update is called once per frame void Update() { TaskItemDetection(); RefereshCard(); } /// <summary> /// 添加卡牌 /// </summary> public void AddCard() { if (cardList==null) { cardList=new List<CardItem>(); } if (cardList.Count>=CardMaxCount) { Debug.Log("手牌数量上限"); return; } GameObject item = Instantiate(cardItem,this.transform); CardItem text=item.GetComponent<CardItem>(); text.RefreshData(rootPos,0,0,0); cardList.Add(text); } /// <summary> /// 手牌状态刷新 /// </summary> public void RefereshCard() { if (cardList==null) { return; } for (int i = 0; i < cardList.Count; i++) { cardList[i].RefreshData(rootPos,rotPos[i],size,i); } } /// <summary> /// 销毁卡牌 /// </summary> public void RemoveCard() { if (cardList==null) { return; } CardItem item = cardList[cardList.Count - 1]; cardList.Remove(item); Destroy(item.gameObject); } /// <summary> /// 销毁卡牌 /// </summary> /// <param name="item"></param> public void RemoveCard(CardItem item) { if (cardList==null) { return; } cardList.Remove(item); Destroy(item.gameObject); } private Vector3 oldmousePosition; /// <summary> /// 玩家操作检测 /// </summary> public void TaskItemDetection() { if (Input.GetKeyDown(KeyCode.A)) { AddCard(); } } }