/// <summary> /// 根据重力更新摄像机变换参考系 /// </summary> void UpdateGravityAlignment() { // 1. 计算当前相机在当前重力下的旋转 Vector3 fromUp = m_gravityAlignment * Vector3.up; // 由当前重力纵轴确定 Vector3 toUp = CustomGravity.GetUpAxis(m_focusPoint); // 由注视点的重力确定 // 2. 得到旋转的角度值 float dot = Mathf.Clamp(Vector3.Dot(fromUp, toUp), -1f, 1f); // 精度问题可能会超出有效范围,造成非预期后果所以clamp之 float angle = Mathf.Acos(dot) * Mathf.Rad2Deg; // 3. 计算当前帧最大旋转速度 float maxAngle = m_upAlignmentSpeed * Time.deltaTime; // 4。由两个纵轴插值和起始旋转求得目标旋转 Quaternion newAlignment = Quaternion.FromToRotation(fromUp, toUp) * m_gravityAlignment; // 5. 如果所需旋转角不大于旋转速度,则不进行旋转 if (angle <= maxAngle) { m_gravityAlignment = newAlignment; } // 6. 如果所需旋转角大于旋转速度,则进行旋转 else { m_gravityAlignment = Quaternion.SlerpUnclamped(m_gravityAlignment, newAlignment, maxAngle / angle); // 由于插值比例保证合理,所以“Unclamped” } }
void UpdateGravityAlignment() { Vector3 fromUp = gravityAlignment * Vector3.up; Vector3 toUp = CustomGravity.GetUpAxis(focusPoint); float dot = Mathf.Clamp(Vector3.Dot(fromUp, toUp), -1f, 1f); float angle = Mathf.Acos(dot) * Mathf.Rad2Deg; float maxAngle = upAlignmentSpeed * Time.deltaTime; Quaternion newAlignment = Quaternion.FromToRotation(fromUp, toUp) * gravityAlignment; if (angle <= maxAngle) { gravityAlignment = newAlignment; } else { gravityAlignment = Quaternion.SlerpUnclamped(gravityAlignment, newAlignment, maxAngle / angle); } }
void LateUpdate() { gravityAlignment = Quaternion.FromToRotation( gravityAlignment * Vector3.up, CustomGravity.GetUpAxis(focusPoint) ) * gravityAlignment; UpdateFocusPoint(); if (ManualRotation() || AutomaticRotation()) { ConstrainAngles(); orbitRotation = Quaternion.Euler(orbitAngles); } Quaternion lookRotation = gravityAlignment * orbitRotation; Vector3 lookDirection = lookRotation * Vector3.forward; Vector3 lookPosition = focusPoint - lookDirection * distance; Vector3 rectOffset = lookDirection * regularCamera.nearClipPlane; Vector3 rectPosition = lookPosition + rectOffset; Vector3 castFrom = focus.position; Vector3 castLine = rectPosition - castFrom; float castDistance = castLine.magnitude; Vector3 castDirection = castLine / castDistance; if (Physics.BoxCast( castFrom, CameraHalfExtends, castDirection, out RaycastHit hit, lookRotation, castDistance, obstructionMask )) { rectPosition = castFrom + castDirection * hit.distance; lookPosition = rectPosition - rectOffset; } transform.SetPositionAndRotation(lookPosition, lookRotation); }
private void LateUpdate() { ////5.1.4 自定义重力下对齐轨道摄像机 //gravityAlignment = Quaternion.FromToRotation(gravityAlignment * Vector3.up, -Physics.gravity.normalized) * gravityAlignment; //5.2.2 应用自定义重力 gravityAlignment = Quaternion.FromToRotation(gravityAlignment * Vector3.up, CustomGravity.GetUpAxis(focusPoint)) * gravityAlignment; ////2.2 控制轨道 ////Vector3 focusPoint = focus.position; //UpdateFocusPoint(); //ManualRotation(); //Quaternion lookRotation = Quaternion.Euler(orbitAngles); ////Vector3 lookDirection = transform.forward; //Vector3 lookDirection = lookRotation * Vector3.forward; ////transform.localPosition = focusPoint - lookDirection * distance; //Vector3 lookPosition = focusPoint - lookDirection * distance; //transform.SetPositionAndRotation(lookPosition, lookRotation); //2.3 约束角度 UpdateFocusPoint(); //Quaternion lookRotation; if (ManualRotation() || AutomaticRotation()) { ConstrainAngles(); orbitRotation = Quaternion.Euler(orbitAngles); } //else //{ // lookRotation = transform.localRotation; //} Quaternion lookRotation = gravityAlignment * orbitRotation; Vector3 lookDirection = lookRotation * Vector3.forward; Vector3 lookPosition = focusPoint - lookDirection * distance; ////4.1减少外观距离 //if (Physics.Raycast(focusPoint, -lookDirection, out RaycastHit hit, distance)) //{ // lookPosition = focusPoint - lookDirection * hit.distance; //} ////4.2保持近平面清晰 采用盒子投射 //if (Physics.BoxCast(focusPoint, CameraHalfExtends, -lookDirection, out RaycastHit hit, lookRotation, distance - regularCamera.nearClipPlane)) //{ // lookPosition = focusPoint - lookDirection * (hit.distance + regularCamera.nearClipPlane); //} //4.3聚焦半径 Vector3 rectOffset = lookDirection * regularCamera.nearClipPlane; Vector3 rectPosition = lookPosition + rectOffset; Vector3 castFrom = focus.position; Vector3 castLine = rectPosition - castFrom; float castDistance = castLine.magnitude; Vector3 castDirection = castLine / castDistance; if (Physics.BoxCast(castFrom, CameraHalfExtends, castDirection, out RaycastHit hit, lookRotation, castDistance, obstructionMask)) { //lookPosition = focusPoint - lookDirection * (hit.distance + regularCamera.nearClipPlane); rectPosition = castFrom + castDirection * hit.distance; lookPosition = rectPosition - rectOffset; } transform.SetPositionAndRotation(lookPosition, lookRotation); }