Search code examples
unity-game-enginerotationquaternions

Rotate object to target, while being rotated to match the terrain slope


alt text

In the image above

  • the red vector is the spider's forward vector
  • the blue vector is the vector representing the direction between the spider and it's target

In the code below, orientation is a vector that's representing the normal of the terrain, so that the spider gets aligned to it:

    Vector3 orientation = GetTerrainNormal();

    Quaternion rotationNeeded = Quaternion.FromToRotation(Vector3.up, orientation);

    transform.rotation = Quaternion.RotateTowards(
                transform.rotation,
                rotationNeeded,
                RotationSpeed * Time.deltaTime
    );

My issue is that I cannot manage to make the spider face its target... When I add any code that would make it rotate towards it, then it's not aligned with the terrain's normals anymore, it says straight...

So basically, how can I make the spider rotate on the Y world axis (I think), while still then being rotated to match the slope?


Full answer

In case it helps someone else, here's the full answer:

        Vector3 orientation = GetTerrainNormal();
        Vector3 directionToTarget = (target.position - transform.position).Y(0);
        float d = Vector3.Dot(directionToTarget, orientation);
        directionToTarget -= d * orientation;
        if (directionToTarget.sqrMagnitude > 0.00001f) {
            directionToTarget.Normalize();
            Quaternion rotationNeeded = Quaternion.LookRotation(directionToTarget, orientation);

            transform.rotation = Quaternion.RotateTowards(
                transform.rotation,
                rotationNeeded,
                xRotationSpeed * Time.deltaTime
            );
        }

This answer on the unity forums was extremely helpful: https://forum.unity.com/threads/look-at-object-while-aligned-to-surface.515743/


Solution

  • Try this

    Vector3 directionToTarget = target.transform.position - transform.position;
    Quaternion rotationNeeded = Quaternion.LookRotation(directionToTarget, orientation);