我正在尝试寻找一种聪明的方法来创建像下一个曲线一样的曲线(使用 Unity3d 2D 部分(不使用网格对撞机))),但我没有找到
任何帮助,将不胜感激。
我正在尝试寻找一种聪明的方法来创建像下一个曲线一样的曲线(使用 Unity3d 2D 部分(不使用网格对撞机))),但我没有找到
任何帮助,将不胜感激。
看到最后一个答案(已删除)不符合我的要求。我使用 2 点和 EdgeCollider2D 之间的贝塞尔曲线制作了 BezierCollider2D 。
版本 1
BezierCollider2D.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[RequireComponent (typeof (EdgeCollider2D))]
public class BezierCollider2D : MonoBehaviour
{
public Vector2 firstPoint;
public Vector2 secondPoint;
public Vector2 handlerFirstPoint;
public Vector2 handlerSecondPoint;
public int pointsQuantity;
Vector3 CalculateBezierPoint(float t,Vector3 p0,Vector3 handlerP0,Vector3 handlerP1,Vector3 p1)
{
float u = 1.0f - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;
Vector3 p = uuu * p0; //first term
p += 3f * uu * t * handlerP0; //second term
p += 3f * u * tt * handlerP1; //third term
p += ttt * p1; //fourth term
return p;
}
public Vector2[] calculate2DPoints()
{
List<Vector2> points = new List<Vector2>();
points.Add(firstPoint);
for(int i=1;i<pointsQuantity;i++)
{
points.Add(CalculateBezierPoint((1f/pointsQuantity)*i,firstPoint,handlerFirstPoint,handlerSecondPoint,secondPoint));
}
points.Add(secondPoint);
return points.ToArray();
}
}
BezierCollider2DEditor.cs
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomEditor(typeof(BezierCollider2D))]
public class BezierCollider2DEditor : Editor
{
BezierCollider2D bezierCollider;
EdgeCollider2D edgeCollider;
int lastPointsQuantity = 0;
Vector2 lastFirstPoint = Vector2.zero;
Vector2 lastHandlerFirstPoint = Vector2.zero;
Vector2 lastSecondPoint = Vector2.zero;
Vector2 lastHandlerSecondPoint = Vector2.zero;
public override void OnInspectorGUI()
{
bezierCollider = (BezierCollider2D) target;
edgeCollider = bezierCollider.GetComponent<EdgeCollider2D>();
if (edgeCollider != null)
{
bezierCollider.pointsQuantity = EditorGUILayout.IntField ("curve points",bezierCollider.pointsQuantity, GUILayout.MinWidth(100));
bezierCollider.firstPoint = EditorGUILayout.Vector2Field ("first point",bezierCollider.firstPoint, GUILayout.MinWidth(100));
bezierCollider.handlerFirstPoint = EditorGUILayout.Vector2Field ("handler first Point",bezierCollider.handlerFirstPoint, GUILayout.MinWidth(100));
bezierCollider.secondPoint = EditorGUILayout.Vector2Field ("second point",bezierCollider.secondPoint, GUILayout.MinWidth(100));
bezierCollider.handlerSecondPoint = EditorGUILayout.Vector2Field ("handler secondPoint",bezierCollider.handlerSecondPoint, GUILayout.MinWidth(100));
EditorUtility.SetDirty(bezierCollider);
if (bezierCollider.pointsQuantity > 0 && !bezierCollider.firstPoint.Equals(bezierCollider.secondPoint) &&
(
lastPointsQuantity != bezierCollider.pointsQuantity ||
lastFirstPoint != bezierCollider.firstPoint ||
lastHandlerFirstPoint != bezierCollider.handlerFirstPoint ||
lastSecondPoint != bezierCollider.secondPoint ||
lastHandlerSecondPoint != bezierCollider.handlerSecondPoint
))
{
edgeCollider.points = bezierCollider.calculate2DPoints();
}
}
}
}
样本:
版本 2(在检查器中带有视觉处理程序和隐藏的边缘对撞机)
BezierCollider2D.cs
using UnityEngine;
using System.Collections.Generic;
[RequireComponent (typeof (EdgeCollider2D))]
public class BezierCollider2D : MonoBehaviour
{
public Vector2 firstPoint;
public Vector2 secondPoint;
public Vector2 handlerFirstPoint;
public Vector2 handlerSecondPoint;
public int pointsQuantity;
Vector3 CalculateBezierPoint(float t,Vector3 p0,Vector3 handlerP0,Vector3 handlerP1,Vector3 p1)
{
float u = 1.0f - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;
Vector3 p = uuu * p0; //first term
p += 3f * uu * t * handlerP0; //second term
p += 3f * u * tt * handlerP1; //third term
p += ttt * p1; //fourth term
return p;
}
public Vector2[] calculate2DPoints()
{
List<Vector2> points = new List<Vector2>();
points.Add(firstPoint);
for(int i=1;i<pointsQuantity;i++)
{
points.Add(CalculateBezierPoint((1f/pointsQuantity)*i,firstPoint,handlerFirstPoint,handlerSecondPoint,secondPoint));
}
points.Add(secondPoint);
return points.ToArray();
}
}
BezierCollider2DEditor.cs
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(BezierCollider2D))]
public class BezierCollider2DEditor : Editor
{
BezierCollider2D bezierCollider;
EdgeCollider2D edgeCollider;
int lastPointsQuantity = 0;
Vector2 lastFirstPoint = Vector2.zero;
Vector2 lastHandlerFirstPoint = Vector2.zero;
Vector2 lastSecondPoint = Vector2.zero;
Vector2 lastHandlerSecondPoint = Vector2.zero;
public override void OnInspectorGUI()
{
bezierCollider = (BezierCollider2D) target;
edgeCollider = bezierCollider.GetComponent<EdgeCollider2D>();
if (edgeCollider.hideFlags != HideFlags.HideInInspector)
{
edgeCollider.hideFlags = HideFlags.HideInInspector;
}
if (edgeCollider != null)
{
bezierCollider.pointsQuantity = EditorGUILayout.IntField ("curve points",bezierCollider.pointsQuantity, GUILayout.MinWidth(100));
bezierCollider.firstPoint = EditorGUILayout.Vector2Field ("first point",bezierCollider.firstPoint, GUILayout.MinWidth(100));
bezierCollider.handlerFirstPoint = EditorGUILayout.Vector2Field ("handler first Point",bezierCollider.handlerFirstPoint, GUILayout.MinWidth(100));
bezierCollider.secondPoint = EditorGUILayout.Vector2Field ("second point",bezierCollider.secondPoint, GUILayout.MinWidth(100));
bezierCollider.handlerSecondPoint = EditorGUILayout.Vector2Field ("handler secondPoint",bezierCollider.handlerSecondPoint, GUILayout.MinWidth(100));
EditorUtility.SetDirty(bezierCollider);
if (bezierCollider.pointsQuantity > 0 && !bezierCollider.firstPoint.Equals(bezierCollider.secondPoint) &&
(
lastPointsQuantity != bezierCollider.pointsQuantity ||
lastFirstPoint != bezierCollider.firstPoint ||
lastHandlerFirstPoint != bezierCollider.handlerFirstPoint ||
lastSecondPoint != bezierCollider.secondPoint ||
lastHandlerSecondPoint != bezierCollider.handlerSecondPoint
))
{
lastPointsQuantity = bezierCollider.pointsQuantity;
lastFirstPoint = bezierCollider.firstPoint;
lastHandlerFirstPoint = bezierCollider.handlerFirstPoint;
lastSecondPoint = bezierCollider.secondPoint;
lastHandlerSecondPoint = bezierCollider.handlerSecondPoint;
edgeCollider.points = bezierCollider.calculate2DPoints();
}
}
}
void OnSceneGUI ()
{
if (bezierCollider != null)
{
Handles.color = Color.grey;
Handles.DrawLine(bezierCollider.transform.position+(Vector3)bezierCollider.handlerFirstPoint,bezierCollider.transform.position+(Vector3)bezierCollider.firstPoint);
Handles.DrawLine(bezierCollider.transform.position+(Vector3)bezierCollider.handlerSecondPoint,bezierCollider.transform.position+(Vector3)bezierCollider.secondPoint);
bezierCollider.firstPoint = Handles.FreeMoveHandle(bezierCollider.transform.position+((Vector3)bezierCollider.firstPoint),Quaternion.identity,0.04f*HandleUtility.GetHandleSize(bezierCollider.transform.position+((Vector3)bezierCollider.firstPoint)),Vector3.zero,Handles.DotCap) - bezierCollider.transform.position;
bezierCollider.secondPoint = Handles.FreeMoveHandle(bezierCollider.transform.position+((Vector3)bezierCollider.secondPoint),Quaternion.identity,0.04f*HandleUtility.GetHandleSize(bezierCollider.transform.position+((Vector3)bezierCollider.secondPoint)),Vector3.zero,Handles.DotCap) - bezierCollider.transform.position;
bezierCollider.handlerFirstPoint = Handles.FreeMoveHandle(bezierCollider.transform.position+((Vector3)bezierCollider.handlerFirstPoint),Quaternion.identity,0.04f*HandleUtility.GetHandleSize(bezierCollider.transform.position+((Vector3)bezierCollider.handlerFirstPoint)),Vector3.zero,Handles.DotCap) - bezierCollider.transform.position;
bezierCollider.handlerSecondPoint = Handles.FreeMoveHandle(bezierCollider.transform.position+((Vector3)bezierCollider.handlerSecondPoint),Quaternion.identity,0.04f*HandleUtility.GetHandleSize(bezierCollider.transform.position+((Vector3)bezierCollider.handlerSecondPoint)),Vector3.zero,Handles.DotCap) - bezierCollider.transform.position;
if (GUI.changed)
{
EditorUtility.SetDirty (target);
}
}
}
}
好好享受。