How to rotate an UI in World Space to player view direction?

Hi there,

I’m building a 3D test game. I use a first person camera, so the view of the player follows the mouse movement. The main camera is a child of the player object. (I say this because I don’t know if that is important for the answer to my question.)

When the player hits an enemy with a shot, the points are shown in an UI that is rendered in World Space at the hit point location. That works pretty well, but my problem is that I don’t know how to rotate the UI so it’s shown in the correct angle to the player.

Script for first person camera movement:

using UnityEngine;
using System.Collections;

public class PlayerCamera : MonoBehaviour {

	Vector2 _mouseAbsolute;
	Vector2 _smoothMouse;

	public Vector2 clampInDegrees = new Vector2(360, 180);
	public bool cursorVisible;
	public Vector2 sensitivity = new Vector2(2, 2);
	public Vector2 smoothing = new Vector2(3, 3);
	public Vector2 targetDirection;
	public Vector2 targetCharacterDirection;

	// Assign this if there's a parent object controlling motion, such as a Character Controller.
	// Yaw rotation will affect this object instead of the camera if set.
	public GameObject characterBody;

	void Start()
	{
		// Set target direction to the camera's initial orientation.
		targetDirection = transform.localRotation.eulerAngles;

		// Set target direction for the character body to its inital state.
		if (characterBody) targetCharacterDirection = characterBody.transform.localRotation.eulerAngles;
	}

	void Update()
	{
		// Ensure the cursor is always locked when set
		if (Input.GetMouseButton (0) && cursorVisible) {
			cursorVisible = false;
		}
		else if (Input.GetKeyDown(KeyCode.Escape) && cursorVisible == false) {
			cursorVisible = true;
		}

		Cursor.visible = cursorVisible;

		// Allow the script to clamp based on a desired target value.
		var targetOrientation = Quaternion.Euler(targetDirection);
		var targetCharacterOrientation = Quaternion.Euler(targetCharacterDirection);

		// Get raw mouse input for a cleaner reading on more sensitive mice.
		var mouseDelta = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));

		// Scale input against the sensitivity setting and multiply that against the smoothing value.
		mouseDelta = Vector2.Scale(mouseDelta, new Vector2(sensitivity.x * smoothing.x, sensitivity.y * smoothing.y));

		// Interpolate mouse movement over time to apply smoothing delta.
		_smoothMouse.x = Mathf.Lerp(_smoothMouse.x, mouseDelta.x, 1f / smoothing.x);
		_smoothMouse.y = Mathf.Lerp(_smoothMouse.y, mouseDelta.y, 1f / smoothing.y);

		// Find the absolute mouse movement value from point zero.
		_mouseAbsolute += _smoothMouse;

		// Clamp and apply the local x value first, so as not to be affected by world transforms.
		if (clampInDegrees.x < 360)
			_mouseAbsolute.x = Mathf.Clamp(_mouseAbsolute.x, -clampInDegrees.x * 0.5f, clampInDegrees.x * 0.5f);

		var xRotation = Quaternion.AngleAxis(-_mouseAbsolute.y, targetOrientation * Vector3.right);
		transform.localRotation = xRotation;

		// Then clamp and apply the global y value.
		if (clampInDegrees.y < 360)
			_mouseAbsolute.y = Mathf.Clamp(_mouseAbsolute.y, -clampInDegrees.y * 0.5f, clampInDegrees.y * 0.5f);

		transform.localRotation *= targetOrientation;

		// If there's a character body that acts as a parent to the camera
		if (characterBody)
		{
			var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, characterBody.transform.up);
			characterBody.transform.localRotation = yRotation;
			characterBody.transform.localRotation *= targetCharacterOrientation;
		}
		else
		{
			var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, transform.InverseTransformDirection(Vector3.up));
			transform.localRotation *= yRotation;
		}
	}

}

I use Physics.Raycast() to check if a shot hits an enemy, so I have the hit point location as a Vector 3.

My idea was something like this, but it doesn’t work:

Vector3 direction = (player.transform.position - hitPoint).normalized;
Instantiate (pointsUI, hitPoint, Quaternion.Euler (direction));

Try Transform.LookAt.

Sometimes the answer is so easy, thanks! :slight_smile: That works pretty well.