简体   繁体   中英

Rotate in the y axis Quaternion

I am controlling an object's rotation with the function Quaternion.FromToRotation . But unfortunately it is rotating in all 3 axes. Can someone help me so I can rotate only in the y axis and x & z should not be affected?

private Quaternion currentRot;
private Vector3 startPos;
private bool offsetSet;

public GameObject Ball;

void Update()
{
        SetOffsets();
 
        Vector3 closestPoint = Vector3.Normalize(transform.position - Ball.transform.position);
        robot.transform.rotation = Quaternion.FromToRotation(startPos, closestPoint) * currentRot;
    
}

void SetOffsets()
    {
        if (offsetSet)
            return;
 
        startPos = Vector3.Normalize(transform.position - Ball.transform.position);
        currentRot = Ball.transform.rotation;
 
        offsetSet = true;
    }

A different approach is needed. Instead of keeping a direction to indicate your starting offset, keep a signed angle to the local forward from a particular direction related to the ball, rotated around the local up. That particular direction is the direction of the ball, projected on the plane normal to robot's up, or in other words, "flattened" so it is no longer locally above or below the robot.

private Quaternion startRot; // currentRot is a misleading name
private float startAngleOffset;
private bool offsetSet;

[SerializeField] GameObject Ball;

void SetOffsets()
{
    if (offsetSet)
        return;
 
    Vector3 thisToBall = Ball.transform.position - transform.position;
    Vector3 robotUp = robot.transform.up;
    Vector3 flattenedToBall = Vector3.ProjectOnPlane(thisToBall, robotUp);
    Vector3 startAngleOffset = Vector3.SignedAngle(flattenedToBall, 
            robot.transform.forward, robotUp);
        
    currentRot = Ball.transform.rotation;
 
    offsetSet = true;
}

Then, when it comes time to set the rotation, do another projection of the ball's direction, then use this signed angle to find the direction forward should be . Then use Quaternion.LookRotation to set the rotation accordingly.

Altogether:

private Quaternion startRot;
private float startAngleOffset;
private bool offsetSet;

[SerializeField] GameObject Ball;

void Update()
{
    SetOffsets();

    Vector3 robotUp = robot.transform.up;
    Vector3 flattenedToBall = GetFlattenedToBall();
    Vector3 robotForwardDir = Quaternion.AngleAxis(startAngleOffset, robotUp)
            * flattenedToBall;

    robot.transform.rotation = LookRotation(robotForwardDir, robotUp);
}


void SetOffsets()
{
    if (offsetSet)
        return;
 
    Vector3 flattenedToBall = GetFlattenedToBall();
    Vector3 startAngleOffset = Vector3.SignedAngle(flattenedToBall, 
            robot.transform.forward, robot.transform.up);
    
    currentRot = Ball.transform.rotation;
 
    offsetSet = true;
}

Vector3 GetFlattenedToBall()
{
    Vector3 thisToBall = Ball.transform.position - transform.position;
    Vector3 flattenedToBall = Vector3.ProjectOnPlane(thisToBall, robot.transform.up);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM