Problem: While attaching (parenting) the player to a moving platform, the player would snap to the parent’s rotation.
Desire: I wanted the player to rotate independently from the platform.
Attach script:
public class AttachPlayer : MonoBehaviour {
private void OnTriggerEnter(Collider other) {
if (other.CompareTag("Player")) {
other.transform.parent = transform;
}
}
private void OnTriggerExit(Collider other) {
if (other.CompareTag("Player")) {
if (other.gameObject.transform.parent == transform) {
other.transform.parent = null;
}
}
}
}
Player rotation is handled from the MouseLook script from the Standard Assets’ first person example. We have to remove the parent’s rotation with Quaternion.Inverse() when attaching and add the rotation when detatching.
Part of MouseLook:
Quaternion? parentRotation = null;
bool isParented = false;
public void Init(Transform character, Transform camera) {
m_CharacterTargetRot = character.localRotation;
m_CameraTargetRot = camera.localRotation;
}
public void LookRotation(Transform character, Transform camera, float? x = null, float? y = null) {
if (!x.HasValue || !y.HasValue) {
x = Input.GetAxis("R_XAxis") > deadzone || Input.GetAxis("R_XAxis") < -deadzone ?
Input.GetAxis("R_XAxis") : 0;
y = Input.GetAxis("R_YAxis") > deadzone || Input.GetAxis("R_YAxis") < -deadzone ?
Input.GetAxis("R_YAxis") : 0;
}
float yRot = x < 0 ? -(Mathf.Abs(Mathf.Pow(x.Value, RotPower) * XSensitivity)) : Mathf.Abs(Mathf.Pow(x.Value, RotPower) * XSensitivity);
float xRot = y < 0 ? -(Mathf.Abs(Mathf.Pow(y.Value, RotPower) * YSensitivity)) : Mathf.Abs(Mathf.Pow(y.Value, RotPower) * YSensitivity);
if (!isVerticalActive) {
xRot = 0;
}
m_CharacterTargetRot *= Quaternion.Euler(0f, yRot, 0f);
m_CameraTargetRot *= Quaternion.Euler(-xRot, 0f, 0f);
if (character.parent != null && !isParented) {
// got a parent
isParented = true;
parentRotation = character.parent.rotation;
m_CharacterTargetRot *= Quaternion.Inverse(parentRotation.Value);
} else if (character.parent == null && parentRotation != null) {
// removed parent
m_CharacterTargetRot *= parentRotation.Value;
parentRotation = null;
isParented = false;
}
if (clampVerticalRotation)
m_CameraTargetRot = ClampRotationAroundXAxis(m_CameraTargetRot);
if (smooth) {
character.localRotation = Quaternion.Slerp(character.localRotation, m_CharacterTargetRot,
smoothTime * Time.deltaTime);
camera.localRotation = Quaternion.Slerp(camera.localRotation, m_CameraTargetRot,
smoothTime * Time.deltaTime);
} else {
character.localRotation = m_CharacterTargetRot;
camera.localRotation = m_CameraTargetRot;
}
UpdateCursorLock();
}
I had a bit of an issue with this so I hope it saves someone else some time.