当前位置: 首页 > news >正文

【unity实战】使用Splines+DOTween制作弯曲手牌和抽牌动画效果

最终效果

在这里插入图片描述

文章目录

  • 最终效果
  • 前言
  • 实战
    • 1、Splines的使用
    • 2、绘制样条线
    • 3、DOTween安装和使用
    • 4、基于样条曲线(Spline)的手牌管理系统
      • 4.1 代码实现
      • 4.2 解释:
        • (1)计算第一张卡牌的位置(居中排列)
        • (1)关键旋转计算:
        • (3)应用动画
      • 4.3 配置参数
      • 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 实现卡牌移动和旋转的平滑动画。

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)计算第一张卡牌的位置(居中排列)
float firstCardPosition = 0.5f - (handCards.Count - 1) * cardSpacing / 2;
  • 目的是让所有卡牌以样条曲线的中点(0.5)对称分布。
  • 例如 3 张卡牌时,第一张卡牌位置为 0.3,后续卡牌依次为 0.5、0.7。
(1)关键旋转计算:
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)应用动画

使用 DOTweenDOMoveDOLocalRotateQuaternion 实现平滑移动和旋转。

4.3 配置参数

在这里插入图片描述
这里的Card预制体制作,可以参考我之前的文章:【unity实战】在 Unity 中实现卡牌翻转或者翻书的效果

spawnPoint卡牌生成位置,我定义在了屏幕的左上角位置

4.4 效果

按空格抽一张牌
在这里插入图片描述


专栏推荐

地址
【unity游戏开发入门到精通——C#篇】
【unity游戏开发入门到精通——unity通用篇】
【unity游戏开发入门到精通——unity3D篇】
【unity游戏开发入门到精通——unity2D篇】
【unity实战】
【制作100个Unity游戏】
【推荐100个unity插件】
【实现100个unity特效】
【unity框架/工具集开发】
【unity游戏开发——模型篇】
【unity游戏开发——InputSystem】
【unity游戏开发——Animator动画】
【unity游戏开发——UGUI】
【unity游戏开发——联网篇】
【unity游戏开发——优化篇】
【unity游戏开发——shader篇】
【unity游戏开发——编辑器扩展】
【unity游戏开发——热更新】
【unity游戏开发——网络】

完结

好了,我是向宇,博客地址:https://xiangyu.blog.csdn.net,如果学习过程中遇到任何问题,也欢迎你评论私信找我。

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!
在这里插入图片描述

http://www.lryc.cn/news/618504.html

相关文章:

  • 有限元方法中的数值技术:行列式、求逆、矩阵方程
  • 【bug 解决】串口输出字符乱码的问题
  • 【Datawhale夏令营】多模态RAG学习
  • 【Bug经验分享】由jsonObject-TypeReference引发的序列化问题
  • 【昇腾】关于Atlas 200I A2加速模块macro0配置3路PCIE+1路SATA在hboot2中的一个bug_20250812
  • STM32_bug总结(TIM定时中断进不去和只进1次)
  • 高性能web服务器Nginx
  • 【Android】【bug】Json解析错误Expected BEGIN_OBJECT but was STRING...
  • linux 开机进入initramfs无法开机
  • 跨设备开发不再难:HarmonyOS 分布式任务管理应用全解析
  • 《Fast Automatic White Balancing Method by Color Histogram Stretching》论文笔记
  • 让齿轮与斑马线共舞:汽车文化驿站及安全教育基地的展陈实践
  • 农业智慧大屏系统 - Flask + Vue实现
  • 安全合规5--终端安全检测和防御技术
  • Python初学者笔记第二十二期 -- (JSON数据解析)
  • 【智慧城市】2025年湖北大学暑期实训优秀作品(3):基于WebGIS的南京市古遗迹旅游管理系统
  • 机器学习 [白板推导](十)[马尔可夫链蒙特卡洛法]
  • js高阶-总结精华版
  • [ 数据结构 ] 时间和空间复杂度
  • 机器学习之TF-IDF文本关键词提取
  • 机器学习-决策树(上)
  • HCIP项目之OSPF综合实验
  • 《算法导论》第 21 章-用于不相交集合的数据结构
  • Linux下命名管道和共享内存
  • django celery 动态添加定时任务后不生效问题
  • 自建知识库,向量数据库 体系建设(二)之BERT 与.NET 8
  • “生成式UI革命”:Tambo AI如何让你的应用“开口说话、动手搭界面” | 全面深剖、案例实践与未来展望
  • 深度学习自动并行技术:突破计算瓶颈的智能调度艺术
  • 每日任务day0812:小小勇者成长记之挤牛奶
  • 13-docker的轻量级私有仓库之docker-registry