最终效果

文章目录
- 最终效果
- 前言
- 实战
-
- 1、Splines的使用
- 2、绘制样条线
- 3、DOTween安装和使用
- 4、基于样条曲线(Spline)的手牌管理系统
-
- [4.1 代码实现](#4.1 代码实现)
- [4.2 解释:](#4.2 解释:)
- [4.3 配置参数](#4.3 配置参数)
- [4.4 效果](#4.4 效果)
- 参考
- 专栏推荐
- 完结
前言
本文介绍了基于Unity样条曲线(Spline)的手牌管理系统实现方法。通过Spline插件绘制平滑路径,结合DOTween实现卡牌动态排列效果。
系统核心功能包括:
- 按空格键生成新卡牌(不超过最大数量限制),
- 沿样条曲线均匀分布卡牌,
- 并利用DOTween实现平滑移动和旋转动画。
重点解析了卡牌居中排列的数学计算和关键旋转算法,展示了如何通过LookRotation
和叉积计算实现卡牌朝向的正确调整。文章提供了完整的C#代码实现和参数配置说明,最终效果可让卡牌按样条路径丝滑排列。
实战
1、Splines的使用
Splines插件的基础使用具体可以参考:【unity实战】Spline 插件让物体沿路径 "丝滑" 走位,实现火车沿轨道移动------Spline 插件的使用
2、绘制样条线

修改中间点弧度,使其更加平滑
3、DOTween安装和使用
DOTween安装和使用,具体可以参考:【推荐100个unity插件之2】 DoTween动画插件的安装和使用整合(最全)
4、基于样条曲线(Spline)的手牌管理系统
4.1 代码实现
主要用于在游戏中实现卡牌的动态生成、排列和动画效果。核心功能:
-
按空格键抽牌:每按一次空格,生成一张新卡牌(不超过最大数量)。
-
沿样条曲线排列卡牌:所有卡牌会均匀分布在一条预定义的样条曲线上。
-
平滑动画过渡:使用 DOTween 实现卡牌移动和旋转的平滑动画。
csharp
using UnityEngine;
using DG.Tweening;
using UnityEngine.Splines;
using System.Collections.Generic;
public class HandManager : MonoBehaviour
{
[SerializeField] private int maxHandSize; // 手牌最大数量
[SerializeField] private GameObject cardPrefab; // 卡牌预制体
[SerializeField] private SplineContainer splineContainer; // 样条曲线容器,用于卡牌排列路径
[SerializeField] private Transform spawnPoint; // 卡牌生成位置
private List<GameObject> handCards = new List<GameObject>();// 当前手牌列表
private void Update()
{
// 按空格键抽牌
if (Input.GetKeyDown(KeyCode.Space)) DrawCard();
}
/// <summary>
/// 抽牌方法
/// </summary>
private void DrawCard()
{
// 如果手牌已满则返回
if (handCards.Count >= maxHandSize) return;
// 实例化新卡牌
GameObject g = Instantiate(cardPrefab, spawnPoint.position, spawnPoint.rotation);
handCards.Add(g);
// 更新所有卡牌位置
UpdateCardPositions();
}
/// <summary>
/// 更新所有卡牌位置和旋转
/// </summary>
private void UpdateCardPositions()
{
// 如果没有手牌则返回
if (handCards.Count == 0) return;
// 计算卡牌间距(基于最大手牌数)
float cardSpacing = 1f / maxHandSize;
// 计算第一张卡牌的位置(居中排列)
float firstCardPosition = 0.5f - (handCards.Count - 1) * cardSpacing / 2;
// 获取样条曲线
Spline spline = splineContainer.Spline;
// 遍历所有卡牌并设置位置和旋转
for (int i = 0; i < handCards.Count; i++)
{
// 计算当前卡牌在曲线上的参数位置
float p = firstCardPosition + i * cardSpacing;
// 获取曲线上的位置、前向向量和上向量
Vector3 splinePosition = spline.EvaluatePosition(p);
Vector3 forward = spline.EvaluateTangent(p);
Vector3 up = spline.EvaluateUpVector(p);
// 计算卡牌旋转(使卡牌朝向正确方向)
// Vector3.Cross(up, forward) 计算 up 和 forward 的 叉积,得到一个垂直于二者的方向(即"右方向")。
Quaternion rotation = Quaternion.LookRotation(up, -Vector3.Cross(up, forward).normalized);
// 使用DOTween动画平滑移动和旋转卡牌
handCards[i].transform.DOMove(splinePosition, 0.25f);
handCards[i].transform.DOLocalRotateQuaternion(rotation, 0.25f);
}
}
}
4.2 解释:
(1)计算第一张卡牌的位置(居中排列)
csharp
float firstCardPosition = 0.5f - (handCards.Count - 1) * cardSpacing / 2;
- 目的是让所有卡牌以样条曲线的中点(0.5)对称分布。
- 例如 3 张卡牌时,第一张卡牌位置为 0.3,后续卡牌依次为 0.5、0.7。
(1)关键旋转计算:
csharp
Quaternion rotation = Quaternion.LookRotation(up, -Vector3.Cross(up, forward).normalized);
我们可以查看目前曲线上点的旋转,因为我们只取获取曲线上点的前向向量和上向量,所以样条线的x旋转不重要,y和z分别是90和270
这么查看比较抽象,我们可以新建一个空物体模拟曲线点的旋转,y和z分别设置成90和270度,看xyz轴具体对应的方向。记得切换成3D模式和局部坐标下观察
我们可以看,曲线点的x、y、z方向分别对应世界坐标的-y、-z、x轴方向。
所以我们使用LookRotation(up, -Cross(up, forward))
可以让卡牌的:
-
Z 轴 对齐曲线的 up 方向。这里也就是世界坐标的-z轴方向。
-
Y 轴 对齐曲线的"左方向"(通过叉积计算,这里取了负号)。这里也就是世界坐标的y轴方向。
(3)应用动画
使用 DOTween
的 DOMove
和 DOLocalRotateQuaternion
实现平滑移动和旋转。
4.3 配置参数

这里的Card预制体制作,可以参考我之前的文章:【unity实战】在 Unity 中实现卡牌翻转或者翻书的效果
spawnPoint卡牌生成位置,我定义在了屏幕的左上角位置
4.4 效果
按空格抽一张牌
参考
https://www.youtube.com/@thecodeotter
专栏推荐
完结
好了,我是向宇
,博客地址:https://xiangyu.blog.csdn.net,如果学习过程中遇到任何问题,也欢迎你评论私信找我。
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!