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

最终效果

文章目录

前言

本文介绍了基于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)应用动画

使用 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,如果学习过程中遇到任何问题,也欢迎你评论私信找我。

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