效果、源码下载

视频展示,源码及demo下载

gif演示

(千束是刻意起飞的,不是bug)

前言

我之前在看到网上有人实现了网页版的sakana,感觉超级有意思,于是动手用unity实现了一下。

整个代码就弹簧效果上实现起来稍微麻烦一点,用了点数学物理的知识。Unity原本有个弹簧关节 (Spring Joint)插件可以实现弹簧效果。但是我试了一下,用不会、不好用,还是自己查资料、动手写来的方便、自由。

虽然这个效果看起来很简单,但是做起来实在是容易踩坑。

另外,此项目的代码是对弹簧进行简单的模拟,简化版的弹簧运动,仅用到了高中物理或者说大物的知识,不是硬核地模拟真实的弹簧。

本文对代码思路进行简单地阐述,源代码已经写了很多注释了。

效果拆分


我把最终效果拆分成一下几个部分:

  1. 鼠标拖动
  2. 物体相对弹簧的径向运动
  3. 物体相对弹簧的摆动
  4. 物体朝向
void FixedUpdate(){//鼠标拖动OnMouseDown();//物体朝向//3D项目用transform.LookAt就可以简单实现朝向,2D的话就得自己手动来了Look2D();//鼠标松开OnMouseUp();if (start){          //沿弹簧方向的运动SpringMove();//弹簧的左右摆动SpringSwing();}}

有个小细节,我把流程代码放在FixedUpdate而不是Update里面,是因为不同平台运行代码时候帧率不一样,通过Time.deltaTime计算出来的运动效果会有差别。FixedUpdate是固定时间执行一次,就能在不同平台达到相近的效果。

鼠标拖动

使用协程OnMouseDow来检测鼠标的动作,这个方法只会检测挂了此脚本的物体。

屏幕坐标和世界坐标之间的转换

另外添加了limit限制拖动范围

//鼠标拖动IEnumerator OnMouseDown()    //使用协程{Vector3 targetScreenPos = Camera.main.WorldToScreenPoint(transform.position);//三维物体坐标转屏幕坐标//将鼠标屏幕坐标转为三维坐标,再计算物体位置与鼠标之间的距离var offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, targetScreenPos.z));while (Input.GetMouseButton(0)){start = false;//将鼠标位置二维坐标转为三维坐标Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, targetScreenPos.z);//将鼠标转换的三维坐标再转换成世界坐标+物体与鼠标位置的偏移量var targetPos = Camera.main.ScreenToWorldPoint(mousePos) + offset;//限制拖动范围if (Vector3.Distance(targetPos, oriPosition) <= limit){transform.position = targetPos;}yield return new WaitForFixedUpdate();//循环执行}     }

物体相对弹簧地径向运动

物体直线运动公式

x = v * dt + 0.5f * a * dt * dt (代码里面不要写1 / 2,因为 1 / 2 等于0)

代码中的time是Time.fixedDeltaTime,相当于公式中的dt,另外,本段代码的运算采用的是矢量,所以速度用了个向量。

在SpringMove()中先计算当前速度的位移,在AddForce()中计算力作用下的位移,力来源于弹簧,设弹簧的劲度系数为k, scalarF = k *(dAB.magnitude - L),设置了一个bottom点,表示弹簧的另外一段(没有连接运动物体的那一段)(这个bottom还会用来计算摆动)。

//x = v * dt + 0.5f * a * dt * dt//沿弹簧方向的运动void SpringMove(){transform.position += v * time;//速度产生的位移v *= aS;//空气阻力会使速度减小//AddForce(new Vector3(0, 9.8f, 0));//重力Vector3 dAB = transform.position - bottom;//向量float scalarF = k * (dAB.magnitude - L);//产生的力的大小AddForce(-dAB.normalized * scalarF);     }void AddForce(Vector3 force){Vector3 a = force / rb.mass;//此力作用于当前质点上产生的加速度v += a * time;//加速度对质点速度的作用:用来加速度transform.position += 0.5f * a * Mathf.Pow(time, 2);//加速度产生的位移}

物体相对弹簧的摆动

摆动我是让物体绕着一个点做摆动,再用transform.RotateAround方法来计算,参数是旋转轴,旋转点,旋转位移。

向量求叉积可以判断当前物体运动到原点左边还是右边,所以求了旋转轴和一个axis,这样能计算运动方向。

//弹簧的左右摆动void SpringSwing(){//半径float r = Vector3.Distance(transform.position, targetObject.position);//水平lfloat l = Vector3.Distance( new Vector3(targetObject.position.x, transform.position.y, transform.position.z), transform.position);//叉积的向量用来和旋转轴相乘,判断物体是正向还是反向运动Vector3 axis = Vector3.Cross( transform.position -  targetObject.position, Vector3.down);if( Vector3.Dot(axis, rotateAxi) < 0){l = -l;}//角加速度float alpha = (-g) * l / Mathf.Pow(r, 2);ow += alpha * time;ow *= aR;//衰减//求角位移(乘以180/PI 是为了将弧度转换为角度)float thelta = ow * time * 180.0f / Mathf.PI / 2;//绕targetObject圆点,rotateAxi旋转轴,旋转位移theltatransform.RotateAround(targetObject.position, rotateAxi, thelta);//print("ow:" + ow + " alpha:"+alpha + "r:"+ r + " l:"+l);}

物体朝向

为了让物体看起来不那么生硬,更有弹簧旋转起来的效果,我让物体始终朝向bottom点。

在3d里面有LookAt直接用,但是2d要自己实现一下.

用物体的坐标与bottom(被看向的点)两个点的出一个向量,让物体的旋转性保持这个向量的方向即可。

//朝向void Look2D(){Vector3 v = targetObject.position - transform.position;v.z = 0;Quaternion rotation = Quaternion.FromToRotation(Vector3.up, -v);transform.rotation = rotation;}

其他代码

  Rigidbody2D rb;Vector3 v;//速度float p;//速率Vector3 bottom;//弹簧底部坐标float k;//弹簧劲度系数float L;//弹簧原长float aS;//衰减float aR;//旋转的衰减bool start;//监测是否开始运动public Transform targetObject;//朝向float g = 10000.8f;//向上的加速度,仅对摆动有效float ow = 0;//角速度Vector3 rotateAxi;//旋转轴float time;//时间float limit;//拖动限制范围Vector3 oriPosition;//物体起始位置AudioSource audio;// Start is called before the first frame updatevoid Start(){rb = gameObject.GetComponent<Rigidbody2D>();bottom = targetObject.transform.position;k = 300f;L = gameObject.transform.position.y - bottom.y;limit = 0.8f*L;oriPosition = transform.position;//PC,Update时候//aS = 0.9995f;//aR = 0.995f;aS = 0.9999f;aR = 0.97f;//An,因为帧率的影响,这是放在update时候//aS = 0.9999f;//aR = 0.9f;start = false;//targetObject = GameObject.Find("Bottom1").transform;//旋转轴//注意!!!,gameobjec和target在世界中需要错开一点角度,如果都在一条竖线上的出来的旋转轴是0向量,无法继续计算rotateAxi = Vector3.Cross((transform.position - targetObject.position), Vector3.down);rb.gravityScale = 0;//关闭重力time = Time.fixedDeltaTime;audio = GetComponent<AudioSource>();}
IEnumerator OnMouseUp(){if (Input.GetMouseButtonUp(0)){start = true;audio.Play();yield return new WaitForFixedUpdate();}}

Lycoris Recoil再现!Unity实现Sakana~,代码思路解析,代码开源,Unity弹簧效果相关推荐

  1. 2023电工杯数学建模竞赛A题思路解析+代码+论文

    电工杯A题:电采暖负荷参与电力系统功率调节的技术经济分析 建设以新能源为主体的新型电力系统是应对全球气候变化挑战的重要举措.高比例新能源接入导致电力系统调节能力稀缺,亟需开发新的调节资源,如火电深度调 ...

  2. 2023电工杯数学建模竞赛B题思路解析+代码+论文

    电工杯B题 人工智能对大学生学习影响的评价 人工智能简称AI,最初由麦卡锡.明斯基等科学家于1956年在美国达特茅斯学院开会研讨时提出. 2016年,人工智能AlphaGo 4:1战胜韩国围棋高手李世 ...

  3. 2023五一杯数学建模竞赛ABC题思路解析+代码+论文

    AB题见文末,下面是C C题:"双碳"目标下低碳建筑研究 "双碳"即碳达峰与碳中和的简称,我国力争2030年前实现碳达峰,2060年前实现碳中和."双 ...

  4. LeetCode面试刷题技巧-二分查找算法代码思路解析

    二分查找的思想 提及二分查找算法,我想大部分人都不陌生,就算不是学计算机的,基本上也都使用过二分查找的思想,不信的话,且听我慢慢为你道来. 不知道你有没有玩过这样一个游戏,猜数字.就是说一个人心里想了 ...

  5. [新手必备]Unity推箱子小游戏C#代码详解(第一篇-代码部分)

    完整项目请参考博客:https://blog.csdn.net/qq_41676090/article/details/96300302 本文为推箱子小游戏C#代码详解第一篇的代码部分,主要讲解 Sy ...

  6. Unity性能优化分析思路

    1)Unity性能优化分析思路 ​2)Unity2020后Paticle子节点旋转并把ScalingMode设置为Hierarchy后,对根节点进行缩放时表现不正常 3)FBX默认会冗余lit.mat ...

  7. python登录代码思路_用python登录Dr.com思路以及代码分享

    用python登录Dr.com思路以及代码分享 发布于 2014-08-28 22:31:52 | 192 次阅读 | 评论: 0 | 来源: 网友投递 Python编程语言Python 是一种面向对 ...

  8. 最全中文leetcode解题攻略:思路知识点代码...搞定AI大厂笔试

    本文经AI新媒体量子位(公众号ID:qbitai)授权转载,转载请联系出处. 本文约多图,建议阅读5分钟. 本文为你分享中文leetcode解题攻略,助你通过AI大厂笔试. 当代程序员的困惑可能大致分 ...

  9. Android自定义Adapter的ListView的思路及代码

    Android自定义Adapter的ListView的思路及代码,需要的朋友可以参考一下 width="650" height="200" align=&quo ...

  10. AT串口抽象层的设计思路及代码实现

    文章目录 1 AT串口抽象层的设计思路及代码实现 1.1 AT串口抽象层的设计思路 1.2 AT串口抽象层的代码实现 1 AT串口抽象层的设计思路及代码实现 1.1 AT串口抽象层的设计思路 我们先来 ...

最新文章

  1. 干货丨三大特征选择策略,有效提升你的机器学习水准
  2. 在Windows系统安装Nodejs
  3. 自定义控件android特效,Android自定义控件eBook实现翻书效果实例详解
  4. 159挑战 | 1:59:40,基普乔格打开人类新时代!
  5. SQL创建数据库– PostgreSQL,MySQL,SQL Server
  6. ios开发--企业帐号发布
  7. Lost Found
  8. Kotlin 的静态代码分析工具
  9. 基于巴法云平台的天猫精灵控制开关
  10. ov5640摄像头使用心得
  11. CI/DI持续集成部署
  12. PGM-Explainer
  13. 平凡的世界 田晓霞的日记 摘抄
  14. Node+Vue3.0+Mongodb实现完美解决高并发的购物平台管理系统
  15. Android Vendor Test Suite (VTS) 的概念、作用及测试方法
  16. 小球碰壁反弹加分_用Java实现小球碰壁反弹的简单实例(算法十分简单)
  17. Linux下BMP图片添加水印
  18. Java之Java特点
  19. 一个超简单的反编译任务(IDAPro、X32dbg)
  20. 【java】函数式接口和Stream

热门文章

  1. 乐动手环app下载安装_乐动手环app下载安装
  2. 哪种程序员最挣钱?平均月薪30.8K,网友说这是掌握世界的技术!
  3. 技术干货:Linux Shell 编程基础,看这一篇就够了!
  4. python 定时发送微信,利用python在微信中实现一个定时发送消息的功能
  5. 大数据运维架构师培训(5):大数据管理平台(Cloudera CM/CDH/CDP)
  6. Kubernetes架构基础知识
  7. nbiot模块联网问题排查
  8. C语言 输入一个不大于五位的数字,先判断是几位数字,然后将其数字顺序输出和逆序输出
  9. 郸城二高2021年高考成绩查询,郸城几所高中高考成绩汇总!有你们村的没?
  10. 单调队列java_单调队列单调栈