最终效果

在这里插入图片描述

文章目录

  • 最终效果
  • 前言
  • 实战
    • 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 效果

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

参考

https://www.youtube.com/@thecodeotter


专栏推荐

地址
【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.pswp.cn/bicheng/93191.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/93191.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/93191.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flask模板注入梳理

从模板开始介绍&#xff1a;Flask中有许多不同功能的模板&#xff0c;他们之间是相互隔离的地带&#xff0c;可供引入和使用。Flask中的模块&#xff1a;flask 主模块&#xff1a;包含框架的核心类和函数&#xff0c;如 Flask&#xff08;应用实例&#xff09;、request&#x…

企业级的即时通讯平台怎么保护敏感行业通讯安全?

聊天记录存在第三方服务器、敏感文件被误发至外部群组、离职员工仍能查看历史消息.对于金融、医疗、政务等对数据安全高度敏感的行业而言&#xff0c;“沟通效率与”信息安全”的矛盾&#xff0c;从未像今天这样尖锐。企业即时通讯怎么保护敏感行业通讯安全&#xff1f;这个问题…

Java Spring框架最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡

Java Spring框架最新版本及发展史详解&#xff08;截至2025年8月&#xff09;-优雅草卓伊凡引言今天有个新项目 客户问我为什么不用spring 4版本&#xff0c;卓伊凡我今天刚做完项目方案&#xff0c;我被客户这一句问了有点愣住&#xff0c;Java Spring框架最新版本及发展史详解…

Android实现Glide/Coil样式图/视频加载框架,Kotlin

Android实现Glide/Coil样式图/视频加载框架&#xff0c;Kotlin <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE" /><uses-permiss…

【k8s】pvc 配置的两种方式volumeClaimTemplates 和 PersistentVolumeClaim

pvc配置实例 实例1在Deployment中配置 template:xxxxxxvolumeClaimTemplates:- metadata:name: dataspec:accessModes:- ReadWriteOnceresources:requests:storage: 1GistorageClassName: nfsdev-storageclass (创建好的storageClassName)实例2#先创建一个pvc 然后在 Deploym…

Logistic Loss Function|逻辑回归代价函数

----------------------------------------------------------------------------------------------- 这是我在我的网站中截取的文章&#xff0c;有更多的文章欢迎来访问我自己的博客网站rn.berlinlian.cn&#xff0c;这里还有很多有关计算机的知识&#xff0c;欢迎进行留言或…

计算机网络技术-知识篇(Day.1)

一、网络概述 1、网络的概念 两个不在同一地理位置的主机&#xff0c;通过传输介质和通信协议&#xff0c;实现通信和资源共享。 2、网络发展史 第一阶段&#xff08;20世纪60年代&#xff09; 标志性事件&#xff1a;ARPANET的诞生关键技术&#xff1a;分组交换技术 第二…

工业元宇宙:迈向星辰大海的“玄奘之路”

一、从认知革命到工业革命&#xff1a;文明跃迁的底层逻辑1.1 认知革命&#xff1a;人类协作的基石时间线&#xff1a;约7万年前&#xff0c;智人通过语言和想象力构建共同虚拟现实&#xff0c;形成部落协作模式。核心突破&#xff1a;虚构能力&#xff1a;创造神、国家、法律等…

9. React组件生命周期

2. React组件生命周期 2.1. 认识生命周期 2.1.1. 很多事物都有从创建到销毁的整个过程&#xff0c;这个过程称之为生命周期&#xff1b;2.1.2. React组件也有自己的生命周期&#xff0c;了解生命周期可以让我们在最合适的地方完成想要的功能2.1.3. 生命周期和生命周期函数的关系…

【单板硬件开发】关于复位电路的理解

阅读紫光同创供应商提供的FPGA单板硬件开发手册&#xff0c;发现复位电路他们家解释的很通俗易懂&#xff0c;所以分享一下。如下图&#xff0c;RST_N 是低有效的异步全芯片复位信号&#xff0c;一般外部连接电路有 3 种形式如图 3–2&#xff0c;可根据实际需要选择合适的电路…

《Unity Shader入门精要》学习笔记一

1、本书的源代码 https://github.com/candycat1992/Unity_Shaders_Book 2、第1章 Shader是面向GPU的工作方式 3、第2章 渲染流水线 Shader&#xff1a;着色器 渲染流水线&#xff1a;目标是渲染一张二维纹理&#xff0c;输入是一个虚拟摄像机、一些光源、一些Shader以及纹…

从零到一:TCP 回声服务器与客户端的完整实现与原理详解

目录 一、TCP 通信的核心逻辑 二、TCP 服务器编程步骤 步骤 1&#xff1a;创建监听 Socket 步骤 2&#xff1a;绑定地址与端口&#xff08;bind&#xff09; 步骤 3&#xff1a;设置监听状态&#xff08;listen&#xff09; 步骤 4&#xff1a;接收客户端连接&#xff08…

MyBatis-Plus核心内容

MyBatis-Plus MyBatis-Plus 是一个基于 MyBatis的增强工具&#xff0c;旨在简化开发过程&#xff0c;减少重复代码。它在MyBatis的基础上增加了CRUD操作封装&#xff0c;条件构造器、代码生成器等功能。 一、核心特性与优势 1. 核心特性 无侵入&#xff1a;只做增强不做改变&am…

计算机网络摘星题库800题笔记 第4章 网络层

第4章 网络层4.1 网络层概述题组闯关1.在 Windows 的网络配置中&#xff0c;“默认网关” 一般被设置为 ( ) 的地址。 A. DNS 服务器 B. Web 服务器 C. 路由器 D. 交换机1.【参考答案】C 【解析】只有在计算机上正确安装网卡驱动程序和网络协议&#xff0c;并正确设置 IP 地址信…

非root用户在linux中配置zsh(已解决ncurses-devel报错)

Zsh&#xff08;Z Shell&#xff09;是一款功能强大的交互式 Unix shell&#xff0c;以其高度可定制性和丰富的功能著称&#xff0c;被视为 Bash 的增强替代品。它支持智能补全、主题美化、插件扩展&#xff08;如 Oh My Zsh 框架&#xff09;、自动纠错、全局别名等特性&#…

《Foundations and Recent Trends in Multimodal Mobile Agents: A Survey》论文精读笔记

论文链接&#xff1a;https://arxiv.org/pdf/2411.02006 摘要 文章首先介绍了核心组件&#xff0c;并探讨了移动基准和交互环境中的关键代表性作品&#xff0c;旨在全面理解研究重点及其局限性。 接着&#xff0c;将这些进展分为两种主要方法&#xff1a; 基于提示的方法&a…

npm安装时一直卡住的解决方法

npm install 卡住通常是由于网络问题或缓存问题导致的。以下是几种解决方法&#xff1a; 方法1&#xff1a;清理npm缓存 npm cache clean --force npm install方法2&#xff1a;删除node_modules和package-lock.json重新安装 rm -rf node_modules package-lock.json npm instal…

[密码学实战]使用Java生成国密SM2加密证书等(四十三)

[密码学实战]使用Java生成国密SM2加密证书等(四十三) 本文将详细介绍如何通过Java代码生成符合国密标准的SM2加密证书,包括密钥对生成、证书扩展属性配置、PEM格式保存等关键步骤。 一. 运行结果示例 二. 国密算法与加密证书 国密算法(SM系列)是中国自主研发的密码算法体…

从零开始之stm32之CAN通信

从小白的视角了解并实现简单的STM32F103的CAN通信&#xff0c;直接上手。一、CAN协议简介CAN总线上传输的信息称为报文&#xff0c;当总线空闲时任何连接的单元都可以开始发送新的报文&#xff0c;有5种类型的帧&#xff1a;数据帧、遥控帧、错误帧、过载帧、帧间隔。数据帧有两…

Java 课程,每天解读一个简单Java之利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示, * 60分以下

package ytr250812;/*题目&#xff1a;利用条件运算符的嵌套来完成此题&#xff1a;学习成绩>90分的同学用A表示&#xff0c;60-89分之间的用B表示&#xff0c;* 60分以下*/import java.util.Scanner;public class GradeEvaluator {public static void main(String[] args) …