Search Unity

Question Move Cube Along Curved Object

Discussion in 'Scripting' started by DanielRodriguesIST, Apr 20, 2021.

  1. DanielRodriguesIST

    DanielRodriguesIST

    Joined:
    Nov 16, 2020
    Posts:
    4
    Hi everyone :)!

    I'm trying to create this assembly line behaviour where the object is moving on top on another objects. My main problem is rotating and moving smoothly the object along the curve. You can check what I desire in following image:


    I've tried two other approaches (rotateTowards and moving along the direction while rotating the cube on Yaxis). Right now, the transform.RotateAround is the one producing the best results but the transition from the curve to the straight rectangle isn't smooth and it's weird (because it rotates to fast when starts colliding with rectangle object).


    To achieve this I'm doing the following:

    Rectangles Objects:
    Code (CSharp):
    1.  
    2. void OnTriggerStay(Collider other)
    3. {
    4.     var cube = other.gameObject;
    5.     direction = endPoint.position - startPoint.position;
    6.     cube.GetComponent<Rigidbody>().MovePosition(cube.transform.position +
    7.     (direction.normalized * speed * Time.deltaTime));
    8.     cube.transform.rotation = Quaternion.LookRotation(direction);
    9. }
    10.  
    Curve Object:
    Code (CSharp):
    1.  
    2. void OnTriggerStay(Collider other)
    3. {
    4.     var cube = other.gameObject;
    5.     float angle = degree * Time.deltaTime;
    6.     curveOrientation = -1; // -1 rotate to the left +1 rotate to the right
    7.     cube.transform.RotateAround(pointO.position, new Vector3(0, curveOrientation, 0), angle);
    8. }
    9.  
    I also thought in having the object following the tangent direction of the curve but at this point I don't have a clue on how to start. Sorry for the long post, I hope you can help me find a better solution for this problem.
    Here's a small gif for better illustration:
     
  2. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    well it does not rotate "too fast", it rotates instantly

    thats because of this line:

    cube.transform.rotation = Quaternion.LookRotation(direction);
    this does not smoothly rotate the object, but instead instantly sets the rotation to look in the direction of the conveyor

    which is exactly what happens in your video, it just jumps from being slowly rotated by the curve to being instantly rotated by the rectangle as soon as the corner of the cube touches the trigger of the rectangle

    a solution would be:
    - allow the cube to ignore the rectangles trigger while it is also triggering the curved object
    - ensure that the curved object rotates fast enough to let the cube reach the orientation the conveyor wants from it (or dont let the rectangles object rotate the cube at all)
     
    Last edited: Apr 21, 2021
    DanielRodriguesIST likes this.
  3. MikeUpchat

    MikeUpchat

    Joined:
    Sep 24, 2010
    Posts:
    1,056
    I use MegaShapes to do something similar in one of my projects. It has a walk loft component that allows you to move objects along the surface of a loft mesh. For example all the cows in this video are controlled by two float values one saying how far along the loft and the other how far across the loft

    And another example where all the cubes and rocks use the same system.
     
  4. DanielRodriguesIST

    DanielRodriguesIST

    Joined:
    Nov 16, 2020
    Posts:
    4
    Thanks for the insights!
    Regarding the second topic of your solution, what would be the best way to ensure that? Clamp the rotation angle? Because if I'm correct, rotating too fast will also be a problem because the cube won't be facing the orientation of the conveyor.

    I've to think about this.

    @MikeUpchat
    Thanks for sharing I wasn't aware of this asset. I'll look into it as last resort.
     
    Last edited: Apr 21, 2021
  5. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    tbh nvm what I said there, since you are defining your rotation as a circular motion around point0, and your curve lies on that circle, you are already ensuring that you rotate the cube to meet exactly what the rectangle object afterwards wants

    changing the rotation speed wont help there, i just didnt think my answer through there correctly ^^

    all you have to do to fix your problem is to somehow prevent the rectangles trigger function to take effect while the curves trigger function is still moving the cube

    one way to do this would be to:
    give the cube a script like MovingObject : MonoBehaviour
    which has a
    public bool isBeingMovedByCurve = false;



    than in your cuve script do:

    Code (CSharp):
    1. void OnTriggerEnter(Collider other)
    2. {
    3.     MovingObject cube = other.gameObject.GetComponent<MovingObject>();
    4.     if(cube != null)
    5.        cube.isBeingMovedByCurve = true;
    6. }
    7.  
    8. void OnTriggerExit(Collider other)
    9. {
    10.     MovingObject cube = other.gameObject.GetComponent<MovingObject>();
    11.     if(cube != null)
    12.        cube.isBeingMovedByCurve = false;
    13. }
    14.  
    with that you can simply change your rectangle object script to:

    Code (CSharp):
    1. void OnTriggerStay(Collider other)
    2. {
    3.     MovingObject cube = other.gameObject.GetComponent<MovingObject>();
    4.     if(cube != null && !cube.isBeingMovedByCurve)
    5.     {
    6.        direction = endPoint.position - startPoint.position;
    7.        cube.GetComponent<Rigidbody>().MovePosition(cube.transform.position +
    8.        (direction.normalized * speed * Time.deltaTime));
    9.        cube.transform.rotation = Quaternion.LookRotation(direction);
    10.     }
    11. }
    which will prevent it being moved by the rectangle while it is still being moved by the curve

    this should fully solve your problem
     
    DanielRodriguesIST likes this.
  6. chengwang2077

    chengwang2077

    Joined:
    Nov 23, 2019
    Posts:
    131
    The board should not be used to drive the cube to move, because the cube may touch two boards at the same time
    It’s better to use Unity’s own physical system to simulate this behavior
     
    DanielRodriguesIST likes this.
  7. DanielRodriguesIST

    DanielRodriguesIST

    Joined:
    Nov 16, 2020
    Posts:
    4
    Ok I tried your suggestion and the result is better indeed but still not perfectly smooth :(!


    Which got me thinking about your other suggestion regarding the line:
    Code (csharp):
    1. cube.transform.rotation = Quaternion.LookRotation(direction);
    So I decided to remove it and the result is way better in my opinion however the cube after the curve is not fully aligned with the rectangle :(


    Note: I also increased the rotation speed for both tests, previously was 5 degrees/second now it's 30/s which corresponds to the curvature angle of the curve.
     
  8. DanielRodriguesIST

    DanielRodriguesIST

    Joined:
    Nov 16, 2020
    Posts:
    4
    Indeed, I'm aware of that but I can't see the issue there.
    How should I do that? Could you detail more please :)?
     
    Last edited: Apr 22, 2021
  9. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    For the physics system you would steer the movement of your object using the rigidbody component it has attached, isntead of changing its transform directly

    like to move your object
    rigidBody.AddForce(<the direction it should move with magnitude being the speed>)
    and to rotate your object you could do:
    rigidBody.MoveRotatio(<the new rotation to which it should smoothly rotate>)

    thus if the cube touches 2 conveyors at once, both will add up forces and 2 forces will pull at your cube at the same time (as I imagine you want It to)
     
    DanielRodriguesIST likes this.