very specific question about rotating children opposite to rotation of parent using quaternions (or something like that)[solved]

ill have the script i use at the end of this, but its a spaghetti fest (seriously, its a nightmare down there you don’t have to help if you don’t want to). so ill simplify what i have so far; a main rigidbody which is using quaternion.slerp to rotate to the direction of the normal directly below it using a raycast (i don’t know how this works exactly but i multiply a part of it by the rigidbody’s rotation and another quaternion for rotation around the y axis and it just works) the rigidbody doesn’t have gravity and has a constant local force applied to its y axis. also there’s a camera as a child of the main rigidbody which only gets the x axis modified using quaternion.euler, in short that makes it work like a regular fps player sorta thing. what i want to do now is get the x rotation of the camera to not be effected by the rotation of the main rigidbody so it can look at something else while the main rigidbody changes its rotation. is this even possible? any advice?

		#region
        float xRot = Input.GetAxisRaw("Mouse X");

		float yRot = Input.GetAxisRaw ("Mouse Y");

        Vector3 rbRot = new Vector3(0f, xRot, 0f) * camsensitivity;

		Vector3 camRot = new Vector3((-yRot * 1.6f), 0f, 0f) * camsensitivity;
		//Debug.Log (camera.rotation);
		if (camera.localEulerAngles.x > 270f){
			//camera.rotation = Quaternion.Euler(90f, 0f, 0f);
			//Debug.Log("euler is greater than 270");
		}
		if (camera.localEulerAngles.x > 80f && camera.localEulerAngles.x < 300f){
			//camera.rotation = Quaternion.Euler(90f, 0f, 0f);
			//Debug.Log("euler is less than 90");
		}
		//Debug.Log(manualangle);

		//rotate towards normal
		RaycastHit normalchek;
		Physics.Raycast (transform.position, transform.TransformDirection(Vector3.down), out normalchek);
		//transform.rotation = Quaternion.FromToRotation(transform.up, normalchek.normal) * transform.rotation;
		if (normalchek.distance < 3f && normalchek.transform.gameObject.tag == "grappleable") {
			cantmove = false;
			//camera.localRotation = (camera.localRotation * Quaternion.Euler(camRot) * Quaternion.Inverse(Quaternion.FromToRotation (transform.up, normalchek.normal)));
			//camera.localRotation = (camera.localRotation * Quaternion.Euler(camRot));
			//transform.rotation = Quaternion.FromToRotation (transform.up, normalchek.normal) * transform.rotation * Quaternion.Euler (rbRot);
			//player.MoveRotation(player.rotation * Quaternion.Euler (rbRot));
			transform.rotation = Quaternion.Slerp(player.rotation * Quaternion.Euler (rbRot), Quaternion.FromToRotation (transform.up, normalchek.normal) * transform.rotation * Quaternion.Euler (rbRot), 0.4f);
		} else {
			player.MoveRotation(player.rotation * Quaternion.Euler (rbRot));
			//camera.Rotate (camRot);
		}

		//wanna rotate to where youre looking at?
		RaycastHit normalchek1;
		Physics.Raycast (camera.position, camera.transform.forward, out normalchek1);
		//Debug.Log(normalchek1.distance);
		if (Input.GetKeyDown(KeyCode.Mouse1) && !grounded && normalchek1.transform.gameObject.tag == "grappleable"){
			if (normalchek1.distance < grappledist) {
				cantmove = true;
				player.velocity = new Vector3 (0f, 0f, 0f);
				transform.rotation = Quaternion.FromToRotation (transform.up, -(normalchek1.point - camera.transform.position)) * transform.rotation;
				if (Random.Range (-1f, 1f) > 0f) {
					Instantiate (shock1, transform.position, transform.rotation);
				} else {
					Instantiate (shock2, transform.position, transform.rotation);
				}
			} else {
				Instantiate (shockfail, transform.position, transform.rotation);
			}
		}

		//moves the camera
		camera.Rotate (camRot);

		//the float with the "fake" angle
		manualangle += camRot.x;
		//Debug.Log(camera.localEulerAngles);

		if (manualangle > 90f){
			camera.localEulerAngles = new Vector3 (90f, 0f, 0f);
			manualangle = 90f;
		}
		if (manualangle < -90f){
			camera.localEulerAngles = new Vector3(-90f, 0f, 0f);
			manualangle = -90f;
		}
		#endregion

Ok, I’ve attempted to solve this on my own but for some reason its all glichy. heres the concept, store the transform.up direction before the rotation and then store another one in a different variable after the rotation. set the x values of both to zero (so vector3.angle cant measure any angles that deviate to the side or anything), and use Vector3.Angle to get the angle between them. then check if the z of the second direction (the direction after the rotation) is positive or negative and use that in an if statement to rotate by the angle negatively, or positively. but when i try this it doesn’t work, maybe i’m setting the local x axis wrong? maybe i just don’t understand direction vectors. here’s the code snippet;

//rotate towards normal
		RaycastHit normalchek;
		Physics.Raycast (transform.position, transform.TransformDirection(Vector3.down), out normalchek);
		//transform.rotation = Quaternion.FromToRotation(transform.up, normalchek.normal) * transform.rotation;
		if (normalchek.distance < 3f && normalchek.transform.gameObject.tag == "grappleable") {
			cantmove = false;

			var storedir1 = transform.up;
			transform.rotation = Quaternion.FromToRotation (transform.up, normalchek.normal) * transform.rotation * Quaternion.Euler (rbRot);
			var storedir2 = transform.up;

			storedir1.x = 0f;
			storedir2.x = 0f;

			var angle = Vector3.Angle(storedir1, storedir2);

			//just to visualize it
			if (angle > 0f){
			Debug.DrawRay(transform.position, storedir1, Color.red, 5f);
			Debug.DrawRay(transform.position, storedir2, Color.blue, 5f);
			}

			if (storedir2.z < 0f){
				camera.Rotate(new Vector3(angle, 0f, 0f));
			} else {
				camera.Rotate(new Vector3(-angle, 0f, 0f));
			}
		} else {
			player.MoveRotation(player.rotation * Quaternion.Euler (rbRot));
			//camera.Rotate (camRot);
		}

Alright everyone. after like a month, and many nights of randomly thinking about how to solve this issue i figured it out. its currently 3 am and I’m far too tired to understand why it works,and for some reason it also does some funky rotation stuff sometimes which doesn’t look right but whatever. here you go:

//rotate towards normal
		RaycastHit normalchek;
		Physics.Raycast (transform.position, transform.TransformDirection(Vector3.down), out normalchek);
		//transform.rotation = Quaternion.FromToRotation(transform.up, normalchek.normal) * transform.rotation;
		if (normalchek.distance < 3f && normalchek.transform.gameObject.tag == "grappleable") {
			cantmove = false;

			var storedir1 = transform.up;
			var beforetransform = transform;

			transform.rotation = Quaternion.FromToRotation (transform.up, normalchek.normal) * transform.rotation * Quaternion.Euler (rbRot);

			storedir1 = beforetransform.InverseTransformDirection(storedir1);

			var storedir2 = transform.up;

			storedir2 = transform.InverseTransformDirection(storedir2);

			storedir1.x = 0f;
			storedir2.x = 0f;

			storedir1 = transform.TransformDirection(storedir1);
			storedir2 = transform.TransformDirection(storedir2);

			var angle = Vector3.Angle(storedir1, storedir2);

			//just to visualize it
			if (angle > 0f){
				Debug.DrawRay(transform.position, storedir1, Color.red, 5f);
				Debug.DrawRay(transform.position, storedir2, Color.blue, 5f);
			}

			if (angle > 0f){
				Debug.Log(angle);
			}
			if ((transform.InverseTransformDirection(storedir1).z > 0f)){
				camera.Rotate(new Vector3(angle, 0f, 0f));
				manualangle += angle;
			} else {
				camera.Rotate(new Vector3(-angle, 0f, 0f));
				manualangle += -angle;
			}
			//transform.rotation = Quaternion.FromToRotation (transform.up, normalchek.normal) * transform.rotation * Quaternion.Euler (rbRot);

		} else {
			player.MoveRotation(player.rotation * Quaternion.Euler (rbRot));
			//camera.Rotate (camRot);
		}