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
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Align to Normal rotation issue

Discussion in 'Scripting' started by petey, Mar 7, 2017.

  1. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,771
    Hi all,

    Sorry I swear this will be the last normal related question ( for at least a week or two :) ).
    I set up this scene to demonstrate a problem I was having in a way more complicated scene.


    I'm aligning to the surface of this mesh but I'd like to remove that rotation that is occurring on the y axis. Is there a nice way to do that? I was thinking maybe if there was a way to calculate the in normals and additively apply it to the rotation... Maybe??

    Or maybe there are other ways to rotate to a normal. I've kinda hit a wall though, if anyone has any suggestions, it would be ace!

    Thanks
    Pete

    Here's the code I'm using in the example -
    Code (CSharp):
    1.     public Transform OriginObj;
    2.     public Transform AlignTarget;
    3.     public Vector3 ContactNormal;
    4.     public float SearchDist;
    5.  
    6.     void FixedUpdate(){
    7.         Vector3 forward = OriginObj.TransformDirection(new Vector3(0,-1,0)) * SearchDist;
    8.         Debug.DrawRay(transform.position, forward, Color.green);
    9.      
    10.         RaycastHit hit;
    11.         if (Physics.Raycast(OriginObj.position, OriginObj.TransformDirection(new Vector3(0,-1,0)), out hit, SearchDist)){
    12.             AlignTarget.position = hit.point;
    13.             AlignTarget.rotation = Quaternion.FromToRotation(new Vector3(0,1,0),hit.normal);
    14.         }
    15.     }
    And the scene as a package in case anyone wants to check it -
    http://www.peterleary.com/ForumFiles/Align Issue-BwFW3RHDe2.unitypackage
     
    Last edited: Mar 7, 2017
  2. booiljoung

    booiljoung

    Joined:
    May 12, 2013
    Posts:
    57
    The hit.normal looks on local coordinate system.

    Vector3 worldNormal = hit.collider.transform.localToWorldMatrix.MultiplyVector(hit.normal);
    AlignTarget.rotation = Quaternion.FromToRotation(new Vector3(0,1,0),worldNormal);
     
  3. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,077
    I found this in another post but it's useful code - it calculates the smoothed normal which might be handy for you:

    Code (CSharp):
    1. public static Vector3 SmoothedNormal(RaycastHit aHit)
    2. {
    3.      var MC = aHit.collider as MeshCollider;
    4.      if (MC == null)
    5.          return aHit.normal;
    6.      var M = MC.sharedMesh;
    7.      var normals = M.normals;
    8.      var indices = M.triangles;
    9.      var N0 = normals[indices[aHit.triangleIndex*3 + 0]];
    10.      var N1 = normals[indices[aHit.triangleIndex*3 + 1]];
    11.      var N2 = normals[indices[aHit.triangleIndex*3 + 2]];
    12.      var B = aHit.barycentricCoordinate;
    13.      var localNormal = (B[0] * N0 + B[1] * N1 + B[2] * N2).normalized;
    14.      return MC.transform.TransformDirection(localNormal);
    15. }
    Source: http://answers.unity3d.com/questions/395230/smooth-normals-in-raycast.html
     
    Last edited: Mar 7, 2017
  4. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,771
    Hey thanks tonemcbride. That is really great for smoothing the result movement across the normals but not the rotation on the axis that Im trying to avoid.
    Booiljoung, thanks for that, I tried adding that to my script and it turned out pretty much the same. :(
    I think I need to approach it in a totally different way. I have a little more energy for it this morning so I'll see what I can do!
    Thanks for all the help though.
     
  5. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,077
    If you change this:

    Code (CSharp):
    1. AlignTarget.rotation = Quaternion.FromToRotation(new Vector3(0,1,0),hit.normal);
    to use the Z axis instead:

    Code (CSharp):
    1. AlignTarget.rotation = Quaternion.FromToRotation(new Vector3(0,0,1),hit.normal);
    it might work more like you intended.
     
    petey likes this.