- Home /
Rotating a GameObject based on another GameObject's y-axis
I have been in the process of making my own custom character controller so it can move at different speeds that vary depending on the direction movement is being applied. I added a SmoothMouseLook script I found and have been trying to get the capsule's rotation on the y-axis to match up with the camera the SmoothMouseLook was applied to. This is so that the character moves forward relative to the camera and not to the world. The camera is parented to the capsule gameObject (player). Here is the PlayerController script: using UnityEngine; using System.Collections;
public class PlayerController : MonoBehaviour {
private CharacterController player;
public float forwardMult = 1;
public float backwardMult = 1;
public float sidewaysMult = 1;
public float gravity = -2;
public float jumpHeight = 10;
private float jump = 0;
private Rigidbody rb_player;
private Camera firstCam;
void Start () {
player = gameObject.GetComponent<CharacterController> ();
rb_player = gameObject.GetComponent<Rigidbody> ();
firstCam = gameObject.GetComponentInChildren<Camera> ();
}
void FixedUpdate () {
float moveVertical = Input.GetAxis ("Vertical");
float moveHorizontal = Input.GetAxis ("Horizontal");
//Applies forward/backward multipliers
if (moveVertical > 0) {
moveVertical *= forwardMult;
}else if (moveVertical < 0){
moveVertical *= backwardMult;
}
//Applies Rotation Defined by Camera Look
float yRotation = firstCam.transform.rotation.y;
gameObject.transform.Rotate (new Vector3 (0.0f, yRotation, 0.0f));
yRotation = 0;
//Defines player movement
Vector3 verticalMovement = transform.forward * moveVertical * Time.deltaTime;
Vector3 horizontalMovement = transform.right * moveHorizontal * Time.deltaTime * sidewaysMult;
//Moves Player
player.Move (verticalMovement + horizontalMovement);
player.Move (new Vector3(0.0f, gravity, 0.0f));
}
}
I have tried many things to get the rotation to match up such as gameObject.transform.rotation = firstCam.transform.rotation (Unity says something about me trying to convert Vector3s into quaternions) and trying to rotate the capsule as is in the script currently(the player keeps on spinning indefinately). Here is the SmoothMouseLook script which I don't understand well:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[AddComponentMenu("Camera-Control/Smooth Mouse Look")]
public class SmoothMouseLook : MonoBehaviour {
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumY = -60F;
public float maximumY = 60F;
float rotationX = 0F;
float rotationY = 0F;
private List<float> rotArrayX = new List<float>();
float rotAverageX = 0F;
private List<float> rotArrayY = new List<float>();
float rotAverageY = 0F;
public float frameCounter = 20;
Quaternion originalRotation;
void Update ()
{
if (axes == RotationAxes.MouseXAndY)
{
rotAverageY = 0f;
rotAverageX = 0f;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotArrayY.Add(rotationY);
rotArrayX.Add(rotationX);
if (rotArrayY.Count >= frameCounter) {
rotArrayY.RemoveAt(0);
}
if (rotArrayX.Count >= frameCounter) {
rotArrayX.RemoveAt(0);
}
for(int j = 0; j < rotArrayY.Count; j++) {
rotAverageY += rotArrayY[j];
}
for(int i = 0; i < rotArrayX.Count; i++) {
rotAverageX += rotArrayX[i];
}
rotAverageY /= rotArrayY.Count;
rotAverageX /= rotArrayX.Count;
rotAverageY = ClampAngle (rotAverageY, minimumY, maximumY);
rotAverageX = ClampAngle (rotAverageX, minimumX, maximumX);
Quaternion yQuaternion = Quaternion.AngleAxis (rotAverageY, Vector3.left);
Quaternion xQuaternion = Quaternion.AngleAxis (rotAverageX, Vector3.up);
transform.localRotation = originalRotation * xQuaternion * yQuaternion;
}
else if (axes == RotationAxes.MouseX)
{
rotAverageX = 0f;
rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotArrayX.Add(rotationX);
if (rotArrayX.Count >= frameCounter) {
rotArrayX.RemoveAt(0);
}
for(int i = 0; i < rotArrayX.Count; i++) {
rotAverageX += rotArrayX[i];
}
rotAverageX /= rotArrayX.Count;
rotAverageX = ClampAngle (rotAverageX, minimumX, maximumX);
Quaternion xQuaternion = Quaternion.AngleAxis (rotAverageX, Vector3.up);
transform.localRotation = originalRotation * xQuaternion;
}
else
{
rotAverageY = 0f;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotArrayY.Add(rotationY);
if (rotArrayY.Count >= frameCounter) {
rotArrayY.RemoveAt(0);
}
for(int j = 0; j < rotArrayY.Count; j++) {
rotAverageY += rotArrayY[j];
}
rotAverageY /= rotArrayY.Count;
rotAverageY = ClampAngle (rotAverageY, minimumY, maximumY);
Quaternion yQuaternion = Quaternion.AngleAxis (rotAverageY, Vector3.left);
transform.localRotation = originalRotation * yQuaternion;
}
}
void Start ()
{
if (GetComponent<Rigidbody>())
GetComponent<Rigidbody>().freezeRotation = true;
originalRotation = transform.localRotation;
}
public static float ClampAngle (float angle, float min, float max)
{
angle = angle % 360;
if ((angle >= -360F) && (angle <= 360F)) {
if (angle < -360F) {
angle += 360F;
}
if (angle > 360F) {
angle -= 360F;
}
}
return Mathf.Clamp (angle, min, max);
}
}
Any help is appreciated and maybe even a quick summary of how the SmoothMouseLook works.
Answer by Torigas · Jul 24, 2015 at 09:36 AM
http://docs.unity3d.com/ScriptReference/Transform.RotateAround.html
Using this method you can rotate any gameobject around a point and an axis. Perhaps this would help?
I was looking at the mouse look script and the method it was using and then noticed this was how it achieved the rotation: transform.localRotation = originalRotation * yQuaternion; I thought I could somehow access the yQuaternion variable and use it in my PlayerController script the same way. However, when I tried to make the yQuaternion public, there was a compile error, is there any way I can get access to it from the other script? Would I have to use a property to make it accessible?
Care to post the code where you make the yQuaternion public? Currently it is being initialized within the scope of a function. I assume you did something like this?
public Quaternion yQuaternion;
void Update ()
{
if (axes == RotationAxes.$$anonymous$$ouseXAndY)
{
//...
yQuaternion = Quaternion.AngleAxis (rotAverageY, Vector3.left); //note that you have to remove the type Quaternion so it writes the value into the global variable and does not create a local one here.
Quaternion xQuaternion = Quaternion.AngleAxis (rotAverageX, Vector3.up);
transform.localRotation = originalRotation * xQuaternion * yQuaternion;
}
//...
}
Yes, but then I realized there were many other yQuaternion variables declared out of that scope. The main problem is I don't understand quaternions well or much less the Smooth$$anonymous$$ouseLook code that well. When I did try this, declaring the quaternion at the start of the code and using it in my PlayerController script, my character could look one direction and move and then the character would roll over sideways, this is probably because of the way quaternions should not be set indipendanttly right? If I wanted the different values to be independent of one another, would I have to use Euler angles?