【Unity】用Lerp()实现类杀戮尖塔手牌变化
Lerp的种类
- math类里的Lerp函数可以对很多种数据类型进行插值,这里主要用的是Vector3的,因为变换position、scale都要用
- 这里的难点是rotation,我试了用Quaternion.Lerp但是放弃了,因为参数必须也是Quaternion类型的(注意大写),
`public static Quaternion Lerp(Quaternion a, Quaternion b, float t);`
所以transform.rotation是不能作为参数的,quaternion.Eular(transform.eularangle)转换成的欧拉角同样也是用不了的,所以只能从欧拉角或借助LookRotation函数里加Lerp来变换
Hover时手牌强调动画
- 强调分三部分:放大、向上移动、取消原有的旋转,既然是Lerp做平滑,就一定是在update里,但是获取鼠标悬浮事件又需要OnMouseEnter,我的解决方法是用bool类型控制update中Lerp的开启或关闭
//鼠标进入if (zoomIn && !zoomOut){Focus();}//鼠标退出if (zoomOut && !zoomIn){UnFocus();}
- 放大和向上移动很简单,注意transform.position就已经是世界坐标了,OnMouseExit的动画其实也就是lerp的一二两个参数对调一下
lerpTime += Time.deltaTime * zoomSpeed;if (lerpTime <= 1){transform.localScale = math.lerp(originscale, originscale * scaleRate, lerpTime);transform.position = math.lerp(originPosition, originPosition + Vector3.up * moveDistance, lerpTime);transform.localRotation = quaternion.LookRotationSafe(Vector3.forward,math.lerp(Vector3.up,originEular,lerpTime)); //Debug.Log(transform.localEulerAngles);}
- 注意旋转值插值的lerp我放在了lookRotation里面,为什么不直接用欧拉角Lerp呢?毕竟它就是Vector3,理论上可以。因为Lerp对欧拉角的Lerp有坑,例如明明一开始欧拉角是(0,0,-15),要Lerp到(0,0,0),但是过程中会出现(0,0,200),查了半天也不知道怎么会有这种问题,所以最后用的是在(0,0,15)和(0,1,0)间的插值,插值的结果再进入lookRotation,实现卡牌被hover时摆正的效果
- 在lookRotation的使用中,理解起来还挺抽象的,表示三维空间的朝向为什么要两个三维向量呢?例如希望卡牌欧拉角为(0,0,0),正对摄像机,那么lookRotation就是(Vector3.forward,Vector3.up)。我的理解是,想象卡牌是个人,你想让它看着你,那就是面对着你(forward),头顶朝天(up),刚才我的旋转插值本质上就是在卡牌头顶正对天和斜对天进行插值
- 比较容易被忽略的是,Lerp的插值插值其实并不能保证变换的程度完全是设置的程度,例如一次缩放结束后,可能和变换前有0.01的误差,虽然它很小,但积累起来就麻烦了,那怎么办呢?保险起见我在每次Lerp的最后加了一个直接变换
transform.localScale = originscale;transform.position = originPosition;
动态生成数量不同的手牌
基础位置也就是手牌区正中间我已经定好了,在此基础上计算每张卡的xy相对位移
private Vector3 CalTargetPos(int cardIndex,int cardTotal){//发的手牌数为奇数if(cardTotal % 2 == 1){var xPos = Vector3.left * (math.ceil(cardTotal / 2)) + Vector3.right * cardIndex;var yPos = Vector3.down * math.abs(math.ceil(cardTotal / 2) - cardIndex);return transform.position + CardXSpace * (xPos) + CardYSpace * (yPos);}//为偶数else{var xPos = Vector3.left * ((cardTotal / 2) - 0.5f) + Vector3.right * cardIndex;var yPos = Vector3.down * math.abs(cardTotal / 2 - cardIndex - 0.5f);return transform.position + CardXSpace * (xPos) + CardYSpace * (yPos);}private quaternion CalTargetQua(int cardIndex,int cardTotal){//发的手牌数为奇数if (System.DelivercardNum % 2 == 1){ return quaternion.LookRotation(Vector3.forward,Vector3.up + CardEular * Vector3.right * (cardIndex - math.ceil(cardTotal / 2)));}//为偶数else{return quaternion.LookRotation(Vector3.forward, Vector3.up + CardEular * Vector3.right * (cardIndex - ((cardTotal / 2) - 0.5f))); ;}}}
- 每局发牌的数量多少和奇偶性都会对卡牌位置的计算产生影响,如果是奇数,那就一张卡在中间,旁边的依次排开,如果是偶数,就是对称分布,所以要先判断此局发牌数的奇偶性
- 公式比较好理解,就不细讲了
- 注意旋转的函数,虽然这里可以用rotate,但是为了避免四元数和欧拉角转换过程中可能的问题,还是用LookRotation
手牌数量减少后的重新布局
本质上还是运用上述的计算公式,在有卡牌被销毁时重新计算,但是难点在于,在原有的脚本调用顺序中,无论如何也只能在卡牌被销毁之前获取消息,那么此时关卡中的卡牌总数还未变化(因为还未销毁),所以计算的结果没变化,我的解决方案就是
- 把将删除的卡的tag改了
- 按tag查找不会被销毁的卡、
- 如果还有卡
- 调用重计算位置的方法
- 否则不调用
当卡牌的运动状态过多时用枚举类型避免混乱
现在卡牌已经有了好几种行为了:放大、缩小、发牌时移动、重布局时移动……,为了避免卡牌移动时被hover可能产生的问题,需要在lerp之前加入判断,但是都设置个bool值就太麻烦了,这时候就需要枚举类型,我是在brackey的类宝可梦回合制教程里学会的,这是B站视频链接
最后在Updete里用switch判断状态,再调用封装好的函数,比用bool清晰整洁多了
public enum BattleCardState { zoomIn, zoomOut, returning, dragging, move, settle }
void Update(){if (!GameObject.FindGameObjectWithTag("CardView")){switch (cardState){//拖拽状态case BattleCardState.dragging :{Vector3 mousePos = MouseInWorldCoords();da.OnDraggingInUpdate();break;}//松开后返回状态case (BattleCardState.returning):{LerpToOrigin();break;}//放大状态case (BattleCardState.zoomIn):{Focus();break;}//缩小状态case (BattleCardState.zoomOut):{UnFocus();break;}//移动状态case (BattleCardState.move):{Debug.Log("move");transform.position = math.lerp(transform.position, originPosition, Time.deltaTime * 3);transform.localRotation = quaternion.LookRotationSafe(Vector3.forward, math.lerp(Vector3.up, originEular, Time.deltaTime * 3));if ((transform.position - originPosition).magnitude < 0.1f){cardState = BattleCardState.settle;transform.position = originPosition;transform.eulerAngles = originEular;}break;}}}}
【Unity】用Lerp()实现类杀戮尖塔手牌变化相关推荐
- 【Unity】类杀戮尖塔手牌系统实现(初始卡组、随机抽牌、卡牌绘制)
制作初始卡组 在DontDestroyOnLoad 的物体下挂不会被销毁的Global脚本,用于跨场景调用玩家当前手牌 制作ScriptableObject类型的卡资源,这样策划可以直接在Unity编 ...
- unity开发 斗地主算法—比较两个手牌的大小
牌型的定义在http://blog.csdn.net/csdn_cjt/article/details/78593140 第一章 这是第二章 下面是代码 #region isSelectCardCan ...
- 在Godot中制作杀戮尖塔的箭头
杀戮尖塔的卡牌箭头 杀戮尖塔里面使用卡牌时的箭头是这样的: 贝塞尔曲线 箭头的形态非常符合贝塞尔曲线. PS 中的钢笔工具就是用的贝塞尔曲线: 如图,一条贝塞尔曲线需要用四个点来确定,一个起点,一个终 ...
- 斗地主手牌最少手数的搜索
基本思路: 1) 先确定火箭:判断是否有大小王. 2) 再确定炸弹:判明是否有四头. 3) 再确定三条和三顺:在已经确定的三条中判断是否包含相邻的三条,如果有,则将其组成三顺.注意 ...
- 写一个杀戮尖塔存档修改器
软件及源码下载 1. 前言 之前杀戮尖塔打折了,然后 买了这个游戏,游戏很好玩,所以我简单研究了一下游戏.游戏是java写的,那么几乎可以看到他的完整源码了. 这个软件前前后后我差不多我写了一周了.所 ...
- 杀戮尖塔有android版本吗,杀戮尖塔安卓版
杀戮尖塔安卓版尚未上线,很多小伙伴都不想错过这款高人气的卡牌游戏,因为它独特的游戏玩法和经典的魔幻场景无一不说明游戏的制作精良,玩过的小伙伴都不想弃玩了,不信你就来试试吧~ (杀戮尖塔目前仅登陆ios ...
- 修改jar中的class:杀戮尖塔修改教程
缘起 作为一只程序猿,游戏自然是标配.自从入了杀戮尖塔的坑,几年来陆陆续续玩了几百小时.然而steam上的成就至今没刷完,发牌员和各路小怪次次都在针对我.在第nn{n^n}nn次死于通往进阶20的三层 ...
- STEAM 97%好评,体验堪比《杀戮尖塔》,为什么玩家说这是2020年上半年最超值的游戏?
当我们感叹<怪物火车>优秀地继承并创新了类<杀戮尖塔>的Roguelike DBG(卡牌构筑游戏,Deck Building Game)玩法时,或许不会想到在短短一个月后,又有 ...
- 杀戮尖塔(Slay the Spire) mod制作 --- 1
偶然间发现了杀戮尖塔是用java写的(震撼我一分钟),然后秉着试一试java准备尝试杀戮尖塔mod制作. 这篇文章主要是靠知乎上的文章和反编译其他现有的mod摸摸索索凑出来的,主要给有一定基础的人大致 ...
最新文章
- jQuery操作Select
- 如何用体验赢取用户信任?让 Waymo 来教教你
- 皮一皮:如何识别对方回复话术的真实目的?
- YOLOv2/YOLO9000 《YOLO9000: Better, Faster, Stronger》论文笔记
- 帆软获取上月的第一天与最后一天_《原神》岩港打工第一天怎么玩 岩港打工第一天玩法攻略...
- Andrew Ng教你如何引领公司进入AI时代
- Win7提示文件太大无法放入回收站怎么办
- 更新maven卡在18不动_Android Studio maven-metadata.xml 卡着不动原因和解决方法
- 基于springboot+vue的智慧教室预约系统(前后端分离)
- 使用百度Android地图SDK显示地图定位
- PCQQ - 发送自定义的XML卡片消息
- 算法设计技巧: Primal-Dual
- 计算机管理上移动硬盘显示其他设备,win7系统拔出移动硬盘提示“该设备正在使用”怎么处理...
- 如何用excel做多元回归分析
- 游戏AI行为选择算法一览
- AutoWare install
- 深度学习的权重衰减是什么_权重衰减和L2正则化是一个意思吗?它们只是在某些条件下等价...
- ZooKeeper之分布式环境搭建
- C++的Json解析库:jsoncpp
- Pycharm更换清华、阿里、豆瓣软件源提高依赖包下载速度