文章目录
- 前言
- 素材
- 开始
- 源码
- 参考
- 完结
前言
今天我们做一个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; // 设置鱼线的线渲染器的顶点数为2
mLr_line.SetPositions(points); // 设置鱼线的线渲染器的所有顶点的位置
}
//获取绘制鱼竿的点
private List<Vector3> GetDarwFishingRodPoints(){
mStrength = Mathf.Clamp(Vector2.Distance(mEndTran.position, mTarget.position) - 5, 0, 100) * 0.2f; // 计算力的大小,通过目标位置和钓鱼竿结束的位置的距离,然后减去5,最后乘以0.2
List<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。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~