@Bane обновил ответ.
даю кривые Безье, используя код ниже, который я получил отВот, Я также сделалBezierPair
игровой объект с двумя кривыми Безье в качестве дочерних объектов.
Из соответствующих изображений ниже и BezierPair, гдеpoints[0]
...points[3]
представляется какP0
...P3
:
P0
каждой кривой Безье всегда остаются неизменными при перемещении. Другими словами, я хочу, чтобы они всегда двигались вместе, с возможностью отключить это движение.СказатьP1
обе кривые обособлены. Как я могу сделатьP1
каждой кривой двигаться в одном и том же направлении на одинаковом расстоянии?СказатьP2
обе кривые обособлены. Как я могу сделатьP2
одного кривого зеркалаP2
другой кривой вдоль линии, соединяющейP0
а такжеP3
? Обратите внимание, что зеркальная линия будет взята из кривой 1 в примере ниже, потому чтоcurve1
«sP2
перемещен Еслиcurve2
«sP2
перемещается, тогда линия зеркала будет взята изcurve2
«sP0P3
.Я не хочу делать это во время выполнения. Таким образом, пользовательский редактор должен быть использован. Я попытался решить 1. в приведенном ниже коде, но положение для второй кривой не изменилось бы без выбора BezierPair в окне иерархии
Безье:
public static class Bezier {
public static Vector3 GetPoint (Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) {
t = Mathf.Clamp01(t);
float oneMinusT = 1f - t;
return
oneMinusT * oneMinusT * oneMinusT * p0 +
3f * oneMinusT * oneMinusT * t * p1 +
3f * oneMinusT * t * t * p2 +
t * t * t * p3;
}
public static Vector3 GetFirstDerivative (Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) {
t = Mathf.Clamp01(t);
float oneMinusT = 1f - t;
return
3f * oneMinusT * oneMinusT * (p1 - p0) +
6f * oneMinusT * t * (p2 - p1) +
3f * t * t * (p3 - p2);
}
}
Кривая Безье:
[RequireComponent(typeof(LineRenderer))]
public class BezierCurve : MonoBehaviour {
public Vector3[] points;
LineRenderer lr;
public int numPoints = 49;
bool controlPointsChanged = false;
bool isMoving = false;
public void Reset () {
points = new Vector3[] {
new Vector3(1f, 0f, 0f),
new Vector3(2f, 0f, 0f),
new Vector3(3f, 0f, 0f),
new Vector3(4f, 0f, 0f)
};
}
void Start() {
lr = GetComponent<LineRenderer> ();
lr.positionCount = 0;
DrawBezierCurve ();
}
public Vector3 GetPoint (float t) {
return transform.TransformPoint(Bezier.GetPoint(points[0], points[1], points[2], points[3], t));
}
public void DrawBezierCurve () {
lr = GetComponent<LineRenderer> ();
lr.positionCount = 1;
lr.SetPosition(0, points[0]);
for (int i = 1; i < numPoints+1; i++) {
float t = i / (float)numPoints;
lr.positionCount = i+1;
lr.SetPosition(i, GetPoint(t));
}
}
public Vector3 GetVelocity (float t) {
return transform.TransformPoint(
Bezier.GetFirstDerivative(points[0], points[1], points[2], points[3], t)) - transform.position;
}
public Vector3 GetDirection (float t) {
return GetVelocity(t).normalized;
}
}
BezierCurveEditor:
[CustomEditor(typeof(BezierCurve))]
public class BezierCurveEditor : Editor {
private BezierCurve curve;
private Transform handleTransform;
private Quaternion handleRotation;
private const int lineSteps = 10;
private const float directionScale = 0.5f;
private void OnSceneGUI () {
curve = target as BezierCurve;
handleTransform = curve.transform;
handleRotation = Tools.pivotRotation == PivotRotation.Local ?
handleTransform.rotation : Quaternion.identity;
Vector3 p0 = ShowPoint(0);
Vector3 p1 = ShowPoint(1);
Vector3 p2 = ShowPoint(2);
Vector3 p3 = ShowPoint(3);
Handles.color = Color.gray;
Handles.DrawLine(p0, p1);
Handles.DrawLine(p2, p3);
Handles.DrawBezier(p0, p3, p1, p2, Color.white, null, 2f);
curve.DrawBezierCurve ();
if (GUI.changed) {
curve.DrawBezierCurve ();
EditorUtility.SetDirty( curve );
Repaint();
}
}
private void ShowDirections () {
Handles.color = Color.green;
Vector3 point = curve.GetPoint(0f);
Handles.DrawLine(point, point + curve.GetDirection(0f) * directionScale);
for (int i = 1; i <= lineSteps; i++) {
point = curve.GetPoint(i / (float)lineSteps);
Handles.DrawLine(point, point + curve.GetDirection(i / (float)lineSteps) * directionScale);
}
}
private Vector3 ShowPoint (int index) {
Vector3 point = handleTransform.TransformPoint(curve.points[index]);
EditorGUI.BeginChangeCheck();
point = Handles.DoPositionHandle(point, handleRotation);
if (EditorGUI.EndChangeCheck()) {
Undo.RecordObject(curve, "Move Point");
EditorUtility.SetDirty(curve);
curve.points[index] = handleTransform.InverseTransformPoint(point);
}
return point;
}
}
BezierPair:
public class BezierPair : MonoBehaviour {
public GameObject bez1;
public GameObject bez2;
public void setupCurves() {
bez1 = GameObject.Find("Bez1");
bez2 = GameObject.Find("Bez2");
}
}
BezierPairEditor:
[CustomEditor(typeof(BezierPair))]
public class BezierPairEditor : Editor {
private BezierPair bezPair;
public override void OnInspectorGUI()
{
bezPair = target as BezierPair;
if (bezPair.bez1.GetComponent<BezierCurve>().points[0] != bezPair.bez2.GetComponent<BezierCurve>().points[0])
{
Vector3 assignPoint0 = bezPair.bez1.GetComponent<BezierCurve>().points[0];
bezPair.bez2.GetComponent<BezierCurve>().points[0] = assignPoint0;
}
if (GUI.changed)
{
EditorUtility.SetDirty(bezPair.bez1);
EditorUtility.SetDirty(bezPair.bez2);
Repaint();
}
}