I am trying to solve an equation in Unity which involves physics and I am completely stumped. Please help

I have a have a ball with a rigidbody attached and I am adding torque to the ball based on the angle of a third person camera (always looking at the ball) witch rotates around the ball. I am trying to change the direction of the ball based on the position of the camera in its rotation around the ball. I am using Vector3.right for forward and reverse torque and Vector3.back for right and left. I have the forward/reverse value, rightVal working but I have been working on the left/right value, backVal for three days and am at a loss. Here is how I am trying to accomplish this.

 void CalcRightVal()
        {
             float degrees = Camera.main.transform.localEulerAngles.y;
            if (degrees > 0 && degrees < 180.0f)
            {
                rightVal = (-degrees / 360) * 4 + 1;
            }
    
    
            if (degrees > 180.0f && degrees < 360.0f) //
            {
                rightVal = (-degrees / 360) * 4 + 1;
    
                if (rightVal < -1.0f)
                {
                    rightVal = (degrees / 360) * 4 - 3;
                }
            }
    
        }
    
        void ApplyTorque()
        {
            Vector3 dir = new Vector3(rightVal, 0, backVal);
            ball.AddTorque(dir * ballAcceleration);
        }

In ApplyTorque() I need the backVal to go from 0 to -1 i.e. Vector3.back when degrees == 90. Then backVal should increase in value to 0 when degrees == 180 then up to 1 when degrees == 270 then back to 0 when degrees == 360. This will apply torque to the right when the camera is at 90 degrees and left when the camera is at 270 degrees. The Idea is that the user will add input to forward i.e. KeyCode.W to add acceleration and reverse or KeyCode.S for breaks. The camera will be responsible for changing the direction of the force. I am not terrible at math but this one has me beat.

While rightVal is at 1 or -1, backVal needs to be at 0 and vice versa. That way when the camera is directly behind the ball or 0 degrees the torque applied will be Vector3.right or (1, 0, 0) and when the camera is at 90 degrees or on the left of the ball, torque applied will be Vector3.back or (0, 0, -1). This will apply torque to make the ball turn right. Basically wherever the camera is the ball rolls forward from the point of view of the user. Thank you for the help, and all help is always appreciated.

Here is a graphic to help out.
CameraValues
Thank You.

I would love to help but I was having a similar issue myself.
I wish this forum would be more active!

Great job laying out the issue tho. If you have figured it out could you please post how you resolved it? If not, when/if I figure out the solution I will let you know!

1 Like

I wish this forum would be more active!

There is a big difference between activity and ability to help.

It would be a bit daft if each of the 24,000+ members of the forum posted saying “Sorry, I don’t know” wouldn’t it :slight_smile:

1 Like

This seems to work but I’m not even sure if my math/logic is correct.

private Vector2 CalcCirclePos(Vector2 cameraPos, Vector2 objectPos) {
    Vector2 myPos = cameraPos - objectPos;                                          //Get position relative to object
    Vector2 myPos_Norm = myPos.normalized;                                          //Get positions with magnitude of 1
    float posSize = Mathf.Abs(myPos_Norm.x) + Mathf.Abs(myPos_Norm.y);              //Find the total size of all elements
    Vector2 linePos = new Vector2(myPos_Norm.x / posSize, myPos_Norm.y / posSize);  //Adjust these relative to each other
    return linePos;
}

This will return you a vector 2(though it should be easily adjusted for 3D space) with your right ad back components you’re looking for.

1 Like

Sorry for the late reply on this matter, if @Martyn_Stewart solution doesn’t work, I suggest you try using quaternions for that.

Vectors aren’t suited to handle rotations, they have many characteristics that make them suboptimal for that, you can probably solve this issue using Quaternion.AngleAxis along with the camera.transform.rotation (which is also a quat); I haven’t looked at your code (sorry, I’m little out of time today), but theoretically you could multiply the Quaternion.AngleAxis(0/90/180/270, Vector3.up) * camera.gameObject.transform.rotation by your movementVector and it should return each one of the relatives to the camera vectors. Take a look at this video to have a better understanding of quats:

1 Like

Why doesn’t my solution work? :slight_smile:

I’m only using the position data for objects. The issue you’re referring to is rotation of objects but we don’t need to do that as far as I can see. We’re just looking for a position on the red line for where the camera is to the ball. Since the camera is always looking directly at we don’t need to worry about the angles involved since they’ll all be perpendicular to the axis.

The way I understand it is if I normalise the delta so that the magnitude is = 1. As per the diagram above that would put the position on the thin red line. The only issue is that the bottom left isn’t (0.5, -0.5) since the magnitude of that would be Sqrt(0.5^2+(-0.5^2)) ~= 0.71. The correct position on the circle would be (1/sqrt(2), -1/sqrt(2)) So what I’ve added is a divisor by the sum of the components to turn this relative to each other and so they always sum to 1 as the OP needs.

The only thing to note is that my solution takes the upper right quadrant as positive whereas in the OP this is the lower right so you’d have to multiply my x position by -1.

Here’s some examples I tested and seem to return logical solutions.

Take the ball in {3,8} and the camera is at {7,12} then relative to the ball the cameras position is {4,4}. Normalising this gives {1/sqrt(2), 1/sqrt(2)}. Divide each part by 2/sqrt(2) and you get {0.5,0.5} adjusted to {-0.5,0.5}

Take the ball at {124,69} and the camera at {124,52} then relative to the ball the camera is at {0,-17}. Normalisation gives {0,-1} and dividing it by 1 gives {0,-1}

Take the ball at {5,7} and the camera at {0,4} then relative to the ball the camera is at {-5,-3}. Normalisation gives {-5 / sqrt(34), -3/sqrt(34)} and dividing it by 8/sqrt(34) gives {-0.625,-0.375} adjusted to {0.625,-0.375}


In fact looking at this again this morning you don’t even need to normalise the vector at all. This will return the same answers and by passing the norms.

private Vector2 CalcCirclePos(Vector2 cameraPos, Vector2 objectPos) {
    Vector2 myPos = cameraPos - objectPos;                                          //Get position relative to object
    float posSize = Mathf.Abs(myPos.x) + Mathf.Abs(myPos.y);              //Find the total size of all elements
    Vector2 linePos = new Vector2(myPos.x / posSize, myPos.y / posSize);  //Adjust these relative to each other
    return linePos;
}
2 Likes

I haven’t said that your solution doesn’t work, I just said IF it doesn’t work. Your logic seems correct to me, I pointed that there are some ways to do it using inbuilt unity methods and some of them will even be calculated by side threads, saving performance.

There are many ways to solve this issue, I usually use something similar to what I described. Quaternions are better suited to handle rotations (related to the original post script) because it doesn’t cause gimbal locks, are additive etc., OP could even make the camera child of the ball and use the camera local transform.forward / transform.right etc. to apply torque (which will result in the already rotated vector).

1 Like

Privacy & Terms