# Get an objects transforms rotation base on player's POV

I am trying to get the rotation values of an object’s backside, frontside or leftside base on player’s POV. For example the first wall has (0,0,0) rotation and by just thinking I know that the backside is at (0,180,0) if my POV is facing it.
Now I also want to know how to do this with objects placed slanted like the second wall which I placed at (0,24,0), I want to know how to get the backsides rotation base on player’s pov.

If you know that rotation, can’t you just add 180 to it?

Yes but… that is if I know that I am facing the backside of the wall, I could just add 180. But what if the wall I am facing is the left side or right side?

Idk if this is what I really need to achieve my goal. But my goal is to make the player face the object at the same degrees the wall he is facing. For example in the first wall I want my player to have a rotation of (0,0,0) when facing the front, (0,180,0) when facing the back , same as for the second wall. transform.lookAt gives me weird result like (0,3.3,0) , (0,10,0).

Don’t really know what you’re asking, but can’t you just add 90 or 270?

Sorry, this didn’t really clear it up for me. Do you mean you want the player to always be parallel to the wall, no matter which way they’re looking at it?

Sorry to confuse you. English is not my first language. Posting my code and my problem might help clarify the misunderstunding.

I am trying to implement a simple rock climbing script without the use of rigidbody (my isKinetic flag is always set to true) so I can’t just use rigidbody addforce to stick to the wall.

``````private void WallRunInput()
{
if (Input.GetKey(KeyCode.LeftShift))
{
activeMoveSpeed = 4f;
}
else
{
activeMoveSpeed = 2f;
}

horizontalInput = Input.GetAxis("Horizontal");
verticalInput = Input.GetAxis("Vertical");

moveDir = new Vector3(horizontalInput, verticalInput, 0f);

movement = ((Vector3.right * moveDir.x) + (Vector3.up * moveDir.y)).normalized * activeMoveSpeed;

movement = Quaternion.Euler(latchedWall.localEulerAngles.x, latchedWall.localEulerAngles.y, latchedWall.localEulerAngles.z) * movement;

charCon.Move(movement * Time.deltaTime);
}
``````

the code I wrote above gives me the desired result only when climbing a wall/object’s frontside. If I try to climb the backside the controls are all inverted.

I see. Perhaps you could Raycast to the wall, and get the normal of the hit. This would give you a Vector3, which you can use some trig to calculate the angle of the wall. Some pseudocode

``````Vector3 direction = latchedWall.transform.position - transform.position;
// maybe want to layermask to only hit walls
if (Physics.Raycast(transform.position, direction, out hit))
{
float angle = Mathf.Atan2(hit.normal.x, hit.normal.z) * Mathf.Rad2Deg;
// stuff
}
``````

This should work with any object with any number of sides, supposing they have a Collider.

Okay, thanks alot. I will try this out early tomorrow. I don’t even know if this is the question I am supposed to be asking, I tried manually putting the float values on code but getting the angle only works on object that are not slanted like , 0 degrees or 180 degrees. Tried in the backside of the slanted wall and my character just falls off. Btw Thanks for your time reading my code.

I got the angle by adding 180. Thanks.
But my worst fear came…It didn’t solve my wallrunning/rock climbing. my script only works when the wall is not slanted like 0 degree or 180 (haven’t tried 90 or 270)…

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WallRunV2 : MonoBehaviour
{
public float wallDirection = 0;

public CharacterController charCon;
public MovementController movementCon;
public Animator anim;
public AimController aimCon;
public Transform cameraRoot;

private bool isWallRunning = false;
public float maxWallRunTime = 5f;
public Vector3 targetAngle = new Vector3(-30f, 0f, 0f);
public Vector3 returnAngle = new Vector3(0f, 0f, 0f);

private float horizontalInput, verticalInput;
public Vector3 moveDir, movement;
private float activeMoveSpeed;
public float moveSpeed = 5f, runSpeed = 8f;

private float wallRunTime = 0;
private Vector3 currentAngle;
private Vector3 currentCameraAngle;
private Vector3 originalCameraPos;
private Vector3 originalCameraRot;
private Transform latchedWall;

MovementBaseState currentState;

public IdleState Idle = new IdleState();
public WalkingState Walking = new WalkingState();
public RunningState Running = new RunningState();
// Start is called before the first frame update
void Start()
{
wallRunTime = maxWallRunTime;
originalCameraPos = cameraRoot.position;
originalCameraRot = cameraRoot.rotation.eulerAngles;
}

// Update is called once per frame
void Update()
{
if (isWallRunning)
{
WallRunTimer();
WallRunInput();
if (wallRunTime <= 0)
{
StopWallWalk();
}
}
}

private void WallRunTimer()
{
wallRunTime -= Time.deltaTime;
}

private void WallRunInput()
{
if (Input.GetKey(KeyCode.LeftShift))
{
activeMoveSpeed = runSpeed;
}
else
{
activeMoveSpeed = moveSpeed;
}

horizontalInput = Input.GetAxis("Horizontal");
verticalInput = Input.GetAxis("Vertical");

moveDir = new Vector3(horizontalInput, verticalInput, 0f);

movement = ((Vector3.right * moveDir.x) + (Vector3.up * moveDir.y)).normalized * activeMoveSpeed;

movement = Quaternion.Euler(latchedWall.localEulerAngles.x, latchedWall.localEulerAngles.y, latchedWall.localEulerAngles.z) * movement;

// this line here messes up the slanted wall rock climbing, but fixes the inverted controls when climbing the backside of walls.
movement = Quaternion.Euler(transform.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z) * movement;

charCon.Move(movement * Time.deltaTime);
}

private void OnTriggerEnter(Collider other)
{
if (other.gameObject.layer == LayerMask.NameToLayer("Grappable"))
{
latchedWall = other.transform;
CheckIfCanLatch();
}
}

private void OnTriggerExit(Collider other)
{
if (other.gameObject.layer == LayerMask.NameToLayer("Grappable"))
{
latchedWall = null;
StopWallWalk();
}
}

private void CheckIfCanLatch()
{
if (CanWallWalk())
{
StartWallWalk();
}
}

private void StartWallWalk()
{
aimCon.enabled = false;
movementCon.enabled = false;
isWallRunning = true;

Vector3 direction = latchedWall.transform.position - transform.position;
// maybe want to layermask to only hit walls
RaycastHit hit;
if (Physics.Raycast(transform.position, direction, out hit, Mathf.Infinity))
{
float angle = Mathf.Atan2(hit.normal.x, hit.normal.z) * Mathf.Rad2Deg;
angle += 180f;

transform.rotation = Quaternion.Euler(0f, angle, 0f);
}
}

private bool CanWallWalk()
{
return !movementCon.isGrounded;
}

private void StopWallWalk()
{
aimCon.enabled = true;
movementCon.enabled = true;
isWallRunning = false;
wallRunTime = maxWallRunTime;
transform.eulerAngles = new Vector3(0f, transform.eulerAngles.y, transform.eulerAngles.z);
}

void Animate()
{
anim.SetFloat("Horizontal Input", horizontalInput);
anim.SetFloat("Vertical Input", verticalInput);
}
}
``````

I put a comment on WallRunInput()'s problematic area. Any inputs are well appreciated but if it might out of topic now since you helped me already with my question. Anyways thanks for your time !

Why do you still multiply by the wall’s angle in the line above, when the character should already be in the correct angle? Seems a little redundant, I would think that’s the problem. It’s a little hard to tell what the problem is though, since I can’t see what it’s doing.

@RadRedPanda Thank you, that solved it for me. That was my monkey fix earlier and after some time I just mistaken it for a necessary part of my code. Damn these vectors got hands. LOL.