How to update one Bezier curve as another is moved using a custom editor

前端 未结 2 2081
悲哀的现实
悲哀的现实 2021-02-18 22:25

I am creating Bézier curves using the code below which I got from here. I have also made a BezierPair game object which has two Bézier curves as child objects.

2条回答
  •  梦谈多话
    2021-02-18 22:44

    I tried solving 1. in the code below but the position for the second curve wouldn’t update without my selecting BezierPair in the hierarchy window

    This is because you are using OnInspectorGUI() callback inside your BezierPairEditor class. It is only executed when the inspector of BezierPairEditor is shown on your editor window. Thus if you do not click on the GameObject with the BezierPair component, the BezierPair's inspector is not shown, and the callback does not trigger.

    Instead, use the EditorApplication.update delegate. Inside your BezierPairEditor class:

    void OnEnable() {
        EditorApplication.update += OnUpdate; //Register to the update callback
    }
    
    void OnUpdate() {
        //Implement your code to update positions here
    }
    

    Secondly, try caching your BezierCurve references. This is because you don't really want to run GetComponent inside every update loop, as it is costly. Again, inside your BezierPairEditor class (I will omit the code above for clarity, merge it yourself):

    BezierCurve bez1C;
    BezierCurve bez2C;
    
    void OnEnable() {
        BezierPair pair = target as BezierPair;
        bez1C = pair.bez1.GetComponent();
        bez2C = pair.bez2.GetComponenet();
    }
    
    void OnUpdate() {
        //Do something with bez1C and bez2C here
    }
    

    Finally, to solve points 1 to 3, since you did not specify, I shall assume that you are moving bez1 manually, and bez2 should follow. In the case where either one can be moved manually and the other should follow, I would recommend you to implement an isChanged check in your BezierCurve class. Then in your BezierPairEditor class, you can check which one has moved, and update the other one accordingly.

    Inside BezierPairEditor class (again, I will omit the code above for clarity, merge it yourself):

    Vector2 bez1CPrev1;
    
    void OnEnable() {
        bez1CPrev1 = bez1C.points[1];
    
        //Ensure that they have the same starting point
        //Either you shift just points[0] of bez2 to be the same as bez1, or you shift every point. Implement this yourself.
    }
    
    void OnUpdate() {
        Vector2 disp = bez1C.points[1] - bez1CPrev1;
    
        //1. 
        bez2C.points[0] = bez1C.points[0];
    
        //2.
        bez2C.points[1] = bez2C.points[1] + disp;
    
        //3. Here, we are gonna use Vector2.Reflect(). Why? 
        //Imagine throwing a ball from newP2(curve1) to P3(curve1).
        //If the 'surface' that the ball hits has a normal of P0(curve1)-P3(curve1), you will have the ball bounce back to reach newP2(curve2).
        //Effectively: newP2(curve2) = P3(curve1) + [newP2(curve2) - P3(curve1)]. The term in the square brackets, we will do it with Vector2.Reflect().
        bez2C.points[2] = bez1C.points[3] + Vector2.Reflect(bez1C.points[3] - bez1C.points[2], (bez1C.points[0] - bez1C.points[3]).normalized);
    
        //Draw your bezier curve etc. here
    
        bez1CPrev1 = bez1C.points[1];
    }
    

提交回复
热议问题