// Copyright (C) 2023 Nicholas Maltbie // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and // associated documentation files (the "Software"), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, publish, distribute, // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. using nickmaltbie.OpenKCC.Character; using nickmaltbie.TestUtilsUnity; using UnityEngine; using UnityEngine.InputSystem; namespace nickmaltbie.OpenKCC.cinemachine.CameraControls { public class CameraRotater : MonoBehaviour { public IUnityService unityService = UnityService.Instance; /// /// Object to rotate for camera to follow. /// public GameObject followTarget; /// /// Action to rotate camera. /// [Tooltip("Player look action to rotate camera.")] [SerializeField] public InputActionReference lookActionReference; /// /// Override for the look action of the network camera controller. /// private InputAction overrideLookAction; /// /// Gest or sets the look action associated with this network camera controller. /// public InputAction LookAction { get => overrideLookAction ?? lookActionReference?.action; set => overrideLookAction = value; } [Header("Rotation Bounds")] /// /// Maximum pitch for rotating character camera in degrees /// public float maxPitch = 90; /// /// Minimum pitch for rotating character camera in degrees /// public float minPitch = -90; /// /// Rotation rate of camera in degrees per second per one unit of axis movement /// public float rotationRate = 180; /// /// Current pitch of the camera. /// public float Pitch { get; private set; } /// /// Current Yaw of the camera. /// public float Yaw { get; private set; } public void Awake() { Pitch = followTarget.transform.rotation.eulerAngles.x; Yaw = followTarget.transform.rotation.eulerAngles.y; } public void Update() { float deltaTime = unityService.deltaTime; Vector2 look = LookAction?.ReadValue() ?? Vector2.zero; look *= PlayerInputUtils.mouseSensitivity; float yawChange = look.x; float pitchChange = look.y; // bound pitch between -180 and 180 Pitch = (Pitch % 360 + 180) % 360 - 180; // Only allow rotation if player is allowed to move if (PlayerInputUtils.playerMovementState == PlayerInputState.Allow) { yawChange = rotationRate * deltaTime * yawChange; Yaw += yawChange; Pitch += rotationRate * deltaTime * -1 * pitchChange; } // Clamp rotation of camera between minimum and maximum specified pitch Pitch = Mathf.Clamp(Pitch, minPitch, maxPitch); // Set the player's rotation to be that of the camera's yaw // transform.rotation = Quaternion.Euler(0, yaw, 0); // Set pitch to be camera's rotation followTarget.transform.rotation = Quaternion.Euler(Pitch, Yaw, 0); } } }