【Unity小技巧】unity2d平台制作一根三七调的鱼竿效果(附git源码)

文章目录

  • 前言
  • 素材
  • 开始
  • 源码
  • 参考
  • 完结

前言

今天我们做一个2d鱼竿的效果,先看一下效果成品效果
在这里插入图片描述

素材

鱼竿
在这里插入图片描述

开始

首先创建一个2D URP项目 ,创建一个空物体作为鱼竿,并创建两个子物体作为开始和结束点
配置层级如下
在这里插入图片描述
鱼竿和鱼线加Line Renderer
在这里插入图片描述
新增鱼竿材质
在这里插入图片描述
贝塞尔曲线基类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 贝塞尔曲线 动态.
/// </summary>
public class BezierHelper{// 一阶贝塞尔曲线,参数P0、P1、t对应上方原理内的一阶曲线参数.public static Vector3 Bezier(Vector3 p0, Vector3 p1, float t){return (1 - t) * p0 + t * p1;}// 二阶贝塞尔曲线,参数对应上方原理内的二阶曲线参数.Vector3 Bezier(Vector3 p0, Vector3 p1, Vector3 p2, float t){Vector3 p0p1 = (1 - t) * p0 + t * p1;Vector3 p1p2 = (1 - t) * p1 + t * p2;Vector3 temp = (1 - t) * p0p1 + t * p1p2;return temp;}// 三阶贝塞尔曲线,参数对应上方原理内的三阶曲线参数.public static  Vector3 Bezier(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t){Vector3 temp;Vector3 p0p1 = (1 - t) * p0 + t * p1;Vector3 p1p2 = (1 - t) * p1 + t * p2;Vector3 p2p3 = (1 - t) * p2 + t * p3;Vector3 p0p1p2 = (1 - t) * p0p1 + t * p1p2;Vector3 p1p2p3 = (1 - t) * p1p2 + t * p2p3;temp = (1 - t) * p0p1p2 + t * p1p2p3;return temp;}// 多阶贝塞尔曲线,使用递归实现.public static Vector3 Bezier(float t, List<Vector3> p){if (p.Count < 2)return p[0];List<Vector3> newp = new List<Vector3>();for (int i = 0; i < p.Count - 1; i++){Debug.DrawLine(p[i], p[i + 1]);Vector3 p0p1 = (1 - t) * p[i] + t * p[i + 1];newp.Add(p0p1);}return Bezier(t, newp);}
}

新建FishingRodCtrl脚本,使用贝塞尔曲线控制鱼竿弯曲

using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using UnityEngine;
using System.Linq;
using UnityEngine.UIElements;[System.Serializable] // 序列化类,使其在Unity编辑器中可见
public class CtrlPointInfo{ // 控制点信息类public float DiffH; // 水平偏移量public float DiffV; // 垂直偏移量}
public class FishingRodCtrl : MonoBehaviour
{private LineRenderer mLr; // 线渲染器private LineRenderer mLr_line;//鱼线的线渲染器private Transform mBeginTran; // 钓鱼竿开始的位置private Transform mEndTran; // 钓鱼竿结束的位置private float mStrength; // 钓鱼竿的受力大小private Transform mTarget; // 钓鱼竿的目标位置public List<CtrlPointInfo> CtrlPointInfos;//控制点的偏移信息列表void Start(){mLr = GetComponent<LineRenderer>();; // 获取线渲染器组件mBeginTran = transform.GetChild(0); // 获取第一个子物体的Transform组件,即钓鱼竿开始的位置mEndTran = transform.GetChild(1); // 获取第二个子物体的Transform组件,即钓鱼竿结束的位置mTarget = GameObject.Find("Target").GetComponent<Transform>(); // 找到名为"Target"的游戏对象,并获取其Transform组件,即钓鱼竿的目标位置mLr_line = GameObject.Find("鱼线").GetComponent<LineRenderer>(); // 找到名为"鱼线"的游戏对象,并获取其线渲染器组件}void Update(){DrawFishingRod();DrawFishingLine();}//绘制鱼竿private void DrawFishingRod(){var drawPoints = GetDarwFishingRodPoints(); // 获取绘制钓鱼竿的点mLr.positionCount = drawPoints.Count; // 设置线渲染器的顶点数mLr.SetPositions(drawPoints.ToArray()); // 设置线渲染器的所有顶点的位置}//绘制鱼线private void DrawFishingLine(){Vector3[] points = new Vector3[2]{mEndTran.position, mTarget.position}; // 创建一个包含钓鱼竿结束的位置和目标位置的向量数组mLr_line.positionCount = 2; // 设置鱼线的线渲染器的顶点数为2mLr_line.SetPositions(points); // 设置鱼线的线渲染器的所有顶点的位置}//获取绘制鱼竿的点private List<Vector3> GetDarwFishingRodPoints(){mStrength = Mathf.Clamp(Vector2.Distance(mEndTran.position, mTarget.position) - 5, 0, 100) * 0.2f; // 计算力的大小,通过目标位置和钓鱼竿结束的位置的距离,然后减去5,最后乘以0.2List<Vector3> points = new List<Vector3>(); // 创建一个新的向量列表,用于存储点//获取控制点List<Vector3> mCtrlPoints = new List<Vector3>();mCtrlPoints.Add(mBeginTran.position); // 将钓鱼竿开始的位置添加到控制点列表中//循环创建控制点for (int i = 0; i < CtrlPointInfos.Count; i++) // 遍历控制点的偏移信息列表{Vector3 ctrlPoint = mBeginTran.position + (mEndTran.position - mBeginTran.position) * CtrlPointInfos[i].DiffH; // 计算控制点的位置,首先进行水平方向的偏移ctrlPoint = ctrlPoint + (Vector3)Vector2.Perpendicular(mEndTran.position - mBeginTran.position) * CtrlPointInfos[i].DiffV * -1 * mStrength; // 然后进行垂直方向的偏移mCtrlPoints.Add(ctrlPoint); // 将计算出的控制点添加到控制点列表中}//最好一个控制点单独控制,从鱼竿竿稍 向力的反方向偏移,可以使曲线顺滑Vector3 lastCtrlPoint = mEndTran.position + (mEndTran.position - mTarget.position).normalized * CtrlPointInfos.Last().DiffV * mStrength;mCtrlPoints.Add(mEndTran.position); // 将钓鱼竿结束的位置添加到控制点列表中for (int i = 0; i < 100; i++){ // 遍历100次points.Add(BezierHelper.Bezier(i/100f, mCtrlPoints)); // 使用贝塞尔曲线算法计算点的位置,并添加到点列表中}return points; // 返回点列表}
}

挂载脚本,配置参数
在这里插入图片描述
运行效果

在这里插入图片描述

源码

https://gitcode.net/unity1/unity2d-fishing
在这里插入图片描述

参考

【视频】https://www.bilibili.com/video/BV1QL411q7Tr

完结

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

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/84135.html

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

相关文章

k8s之工作负载、Deployment、DaemonSet、StatefulSet、Job、CronJob及GC

文章目录 1、工作负载1.1、定义1.2、分类 2、Deployment2.1、定义2.2、Deployment创建2.3、Deployment 更新机制2.3.1、比例缩放&#xff08;Proportional Scaling&#xff09;2.3.2、HPA&#xff08;动态扩缩容&#xff09;2.3.2.1、需要先安装metrics-server2.3.2.2、配置hpa…

JavaScript(笔记)

目录 Hello World JavaScript 的变量 JavaScript 动态类型 隐式类型转换 JavaScript 数组 JavaScript 函数 JavaScript 中变量的作用域 对象 DOM 选中页面元素 事件 获取 / 修改元素内容 获取 / 修改元素属性 获取 / 修改 表单元素属性 获取 / 修改样式属性 新…

<C++> 内存管理

1.C/C内存分布 让我们先来看看下面这段代码 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";char *pChar3 "abcd";int *ptr1 (int *) mal…

3D姿态相关的损失函数

loss_mpjpe: 计算预测3D关键点与真值之间的平均距离误差(MPJPE)。 loss_n_mpjpe: 计算去除尺度后预测3D关键点误差(N-MPJPE),评估结构误差。 loss_velocity: 计算3D关键点的速度/移动的误差,评估运动的平滑程度。 loss_limb_var: 计算肢体长度的方差,引导生成合理的肢体长度…

vue 简单实验 v-model 变量和htm值双向绑定

1.代码 <script src"https://unpkg.com/vuenext" rel"external nofollow" ></script> <div id"two-way-binding"><p>{{ message }}</p><input v-model"message" /> </div> <script>…

Django REST framework实现api接口

drf 是Django REST framework的简称&#xff0c;drf 是基于django的一个api 接口实现框架&#xff0c;REST是接口设计的一种风格。 一、 安装drf pip install djangorestframework pip install markdown # Markdown support for the browsable API. pip install …

Java 时间日期处理,工作必用(建议收藏)

工作中经常会遇到对时间日期进行处理的业务&#xff0c;像日期类的API个人觉得不需要背&#xff0c;需要的时候去查资料就行。我整理了Java8之前及之后日期类常用的时间日期处理方法&#xff0c;方便工作需要时查找&#xff0c;觉得有用的朋友可以收藏。 一、日期格式化和解析 …

分布式事务-seata框架

文章目录 分布式事务0.学习目标1.分布式事务问题1.1.本地事务1.2.分布式事务1.3.演示分布式事务问题 2.理论基础2.1.CAP定理2.1.1.一致性2.1.2.可用性2.1.3.分区容错2.1.4.矛盾 2.2.BASE理论2.3.解决分布式事务的思路 3.初识Seata3.1.Seata的架构3.2.部署TC服务3.3.微服务集成S…

C++避坑——most vexing parse问题

1."坑"的问题是什么&#xff1f; 先看一段代码&#xff1a; class Functor { public:void operator()(){std::cout << "我是线程的初始函数" << std::endl;} };int main() {std::thread t(Functor());// 强制高速编译器这是一个构造函数!t.j…

前端进阶之———浏览器调试巧技

有幸的参加了一次腾讯的面试&#xff0c;被面试官问到了JS能不能在浏览器上import依赖已经遇到一个错误函数应该怎么解决。之前的经验是做一些简单的html&#xff0c;css样式调试以及他的报错信息&#xff0c;忽略了浏览器js调试的强大功能。觉得还是非常有必要的&#xff0c;很…

锁的相关策略

乐观锁vs悲观锁 指的不是具体的锁,是一个抽象的概念,描述的是锁的特性,描述的是一类锁 乐观锁 假设数据一般情况下不会产生并发冲突,所以在数据进行提交更新的时候,才会正式对数据是否产生并发冲突进行检测,如果发现并发冲突了,就让返回用户错误的信息,让用户决定如何去做.(…

从爬楼梯到斐波那契数列:解密数学之美

题目描述 我们来看看力扣的一道经典问题70. 爬楼梯 递归 假设n级台阶有climbStairs(n)种方法爬到楼梯顶。如果有n级台阶&#xff0c;如果第一次往上爬1级台阶&#xff0c;就会剩下n-1级台阶&#xff0c;这n-1级台阶就有climbStairs(n-1)种方法爬到楼梯顶&#xff1b;如果第一…