Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Help simplifying trigonometry

Discussion in 'Scripting' started by ItsShiZZa, Feb 28, 2020.

  1. ItsShiZZa

    ItsShiZZa

    Joined:
    Dec 30, 2019
    Posts:
    3
    Code (CSharp):
    1. var halfScreenWidth = Screen.width / 2;
    2. var halfScreenHeight = Screen.height / 2;
    3. var xFromCenter = Input.mousePosition.x - halfScreenWidth;
    4. var yFromCenter = Input.mousePosition.y - halfScreenHeight;
    5. var distance = Mathf.Sqrt(xFromCenter * xFromCenter + yFromCenter * yFromCenter);
    6.  
    7. var angle = Mathf.Rad2Deg;
    8.  
    9. if (xFromCenter >= 0)
    10. {
    11. angle *= Mathf.Asin(yFromCenter / distance);
    12. rigidbody.MoveRotation(Quaternion.Inverse(Quaternion.Euler(0, angle + 45f, 0)));
    13. } else
    14. {
    15. angle *= Mathf.Asin(-yFromCenter / distance);
    16. rigidbody.MoveRotation(Quaternion.Inverse(Quaternion.Euler(0, angle + 225f, 0)));
    17. }
    This code is working seamlessly, through trial and error and very basic trigonometry knowledge. However, I don't know enough to simplify it any further even though I'm almost positive it is overly complex. The purpose of the code is to rotate the rigidbody to an angle based on the center of the screen, and as I said it does seem to work. The parts that are most confusing to me are why I need to add angles (45 degrees / 225 degrees) and why I need to use Quaternion.Inverse. Thanks.
     
  2. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    if you imagine a sphere with a needle sticking out of its center, a quaternion represents the angular position of this needle in 4D space (don't bother with deciphering its actual values intuitively however, it's fairly complex). Quaternion.Inverse will simply find the needle exactly opposite to that placement. it will simply negate all the components of quaternion (except W) and make sure that it's a valid, unit quaternion in the end.

    you don't have to bother with it, it's a very fast transformation, very similar to how -Vector3.right will give you a vector that points to the left.

    the rest of your question are implementation details that are specific to what you're doing. I'm sure there is some reasoning behind it. probably because arc sine gives values that are biased in some way, so these corrections make sure it turns into some sort of a diagonal.

    if you want to simplify this further, why don't you simply use an existing method like Transform.LookAt or Quaternion.AngleAxis?
     
  3. ItsShiZZa

    ItsShiZZa

    Joined:
    Dec 30, 2019
    Posts:
    3
    I assume that's what I need to do, but all these functions deal with vectors/transforms in world space and I don't know how to convert from the mouse position to that. I previously used raycasts to the terrain and moved the rigidbody towards that position, and it worked, however I want a movement system that is independent of anything that is going on in the terrain.

    I want to rotate the rigidbody to the angle that the mouse position is from the center of the screen. So if the mouse is at (10, 10) from the center, I want to rotate 45 degrees, and if it's at (0, 10), rotate to 90 degrees (with 0 degrees being facing right).
     
  4. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    to get a vector between any two points, start and end, all you need to do is to subtract the points.
    it's very simple vector math, if you know about trigonometry, surely you can wrap your head around this.

    Code (csharp):
    1. var vector = end - start; // just a simple 'arrow' from start to end
    ScreenToWorldPoint will help you get the mouse coordinates in world space, check the examples

    when working with directions, you normally want to turn your vector into a vector of 'unit' length. that means it has a length of 1 regardless of how you obtained it. this is useful for directions because you can then multiply such a vector with a scalar value and get a vector of a certain magnitude. if you then add this vector to a point, you can turn that into a required offset or movement.

    you get unit vectors by dividing them by their own magnitude.
    a vector (5, 5, 5) that has a magnitude of 8.66 (imagine a grand cube diagonal), now becomes (0.5773, 0.5773, 0.5773), a congruent vector but with a magnitude of exactly 1.

    use normalized on any vector to achieve this, but be mindful about it, it's not incredibly cheap because it involves a square root and three divisions. it's ubiquitous however in working with linear algebra and 3D geometry in general.

    Code (csharp):
    1. var direction = (end - start).normalized;
    when it comes to quaternion, most often than not you have everything you need about them in the libraries already.
    especially consider whatever is at your disposal in transform. transform is basically just a child node element of a hierarchical tree system with linear transformation matrices.

    consider that you can always manually apply any quaternion to any vector by multiplying the two. be wary that quaternion needs to be on the left.

    Code (csharp):
    1. var direction = myQuaternion * Vector3.forward;
     
    eses likes this.
  5. ItsShiZZa

    ItsShiZZa

    Joined:
    Dec 30, 2019
    Posts:
    3
    Let's say I create a "fake" vector which assumes my character is at the center of the screen and uses the x and y mouse offset from the center of the screen:

    Code (CSharp):
    1. Vector3 direction = new Vector3(rigidbody.position.x + centerOffsetX, 0, rigidbody.Position.z + centerOffsetY);
    I cannot figure out how to rotate the rigidbody to face that vector. I'm thinking that the problem is that this "fake" vector does not account for the rotation that the rigidbody is already at, and that's why rotating to it does not work. Can you tell me how to rotate my fake vector to align with the rigidbody's rotation, and then I should be able to rotate to that?
     
  6. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,386
    Sounds like a unit vector, so you can just set the transform.forward to that vector. There is an example in the docs:
    https://docs.unity3d.com/ScriptReference/Transform-forward.html
    is that what you are talking about?
     
  7. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Code (csharp):
    1. var finalVector = transform.rotation * yourVector;
    what I said in the previous post is pretty much the general case of applying a quaternion to a vector.

    and yes, you can just Transform.forward if that's applicable to your case.
    it basically does transform.rotation * Vector3.forward for you.
     
  8. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @Euphorigenic

    Just interested, not sure if I can help or if you already got everything solved with above help.

    What exactly do you mean by:
    "The purpose of the code is to rotate the rigidbody to an angle based on the center of the screen, and as I said it does seem to work."

    Based on the center of the screen how? As center is there and doesn't move ever, do you mean how the rb is positioned relative to the center? And what are you trying to achieve (visually).