Skip to content

Instantly share code, notes, and snippets.

@devzl
Created April 20, 2026 02:59
Show Gist options
  • Select an option

  • Save devzl/4a13bda9f39f5621ab06c8165b0b55e0 to your computer and use it in GitHub Desktop.

Select an option

Save devzl/4a13bda9f39f5621ab06c8165b0b55e0 to your computer and use it in GitHub Desktop.
HackyCamera to zoom in and pitch with Third Person Controller
namespace DustboundD.Gameplay.Camera
{
using System.Collections.Generic;
using System.Collections;
using System.Reflection;
using Opsive.Shared.Input;
using Opsive.Shared.Utility;
using Opsive.UltimateCharacterController.Camera;
using Opsive.UltimateCharacterController.Character;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
using TopDownView = Opsive.UltimateCharacterController.ThirdPersonController.Camera.ViewTypes.TopDown;
using AdventureMovementType = Opsive.UltimateCharacterController.ThirdPersonController.Character.MovementTypes.Adventure;
using TopDownMovementType = Opsive.UltimateCharacterController.ThirdPersonController.Character.MovementTypes.TopDown;
[DisallowMultipleComponent]
public class TopDownCameraHackController : MonoBehaviour
{
[Header("Zoom")]
[SerializeField] private float m_MinViewDistance = 10f;
[SerializeField] private float m_MaxViewDistance = 30f;
[SerializeField] private float m_MouseWheelZoomStep = 3f;
[SerializeField] private KeyCode m_MouseWheelZoomModifierKey = KeyCode.V;
[SerializeField] private float m_KeyboardZoomSpeed = 14f;
[SerializeField] private float m_ControllerZoomSpeed = 18f;
[SerializeField] private float m_ZoomSmoothSpeed = 10f;
[Header("Pitch")]
[SerializeField] private float m_ZoomedInPitch = 56f;
[SerializeField] private float m_ZoomedOutPitch = 78f;
[SerializeField] private float m_PitchSmoothSpeed = 8f;
[SerializeField] private float m_MaxPitchLimit = 89f;
[Header("Aim")]
[SerializeField] private bool m_SwitchToTopDownMovementWhileAiming = true;
[SerializeField] private string m_AimInputName = "Fire2";
[SerializeField] private bool m_EnableControllerAimMode;
[SerializeField] private float m_ControllerAimThreshold = 0.2f;
[SerializeField] private float m_ControllerRotateSpeed = 180f;
[SerializeField] private bool m_UseSmoothedMouseAimRotation = true;
[SerializeField] private float m_MouseAimRotateSpeed = 720f;
[SerializeField] private float m_MinMouseAimDistance = 0.35f;
[SerializeField] private bool m_ForceTopDownRelativeCameraMovement = true;
[SerializeField] private bool m_ForceTopDownLookAtCursor = true;
[Header("Discovery")]
[SerializeField] private bool m_ForceTopDownViewIfFound;
[SerializeField] private bool m_DisableBuiltInRightClickZoom = true;
[SerializeField] private bool m_KeepMouseVisible = true;
[Header("Debug")]
[SerializeField] private bool m_ShowDebugGui = true;
[SerializeField] private float m_DebugTriggerPressedThreshold = 0.5f;
private CameraController m_CameraController;
private CameraControllerHandler m_CameraControllerHandler;
private TopDownView m_TopDownView;
private TopDownMovementType m_TopDownMovementType;
private UltimateCharacterLocomotion m_CharacterLocomotion;
private IPlayerInput m_PlayerInput;
private string m_AdventureMovementTypeFullName;
private string m_TopDownMovementTypeFullName;
private string m_OriginalZoomInputName;
private float m_TargetViewDistance;
private float m_CurrentPitchMin;
private float m_PitchRange = 10f;
private bool m_AimMovementActive;
private bool m_Configured;
private CursorLockMode m_PreviousCursorLockMode;
private bool m_PreviousCursorVisible;
private bool m_CursorStateCached;
private readonly List<Component> m_CursorManagedComponents = new List<Component>();
private readonly List<bool> m_PreviousDisableCursorValues = new List<bool>();
private readonly List<bool> m_PreviousEnableCursorWithEscapeValues = new List<bool>();
private static readonly BindingFlags c_InstanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
private static readonly string c_AdventureMovementTypeFullName = typeof(AdventureMovementType).FullName;
private static readonly string c_TopDownMovementTypeFullName = typeof(TopDownMovementType).FullName;
private GUIStyle m_DebugLabelStyle;
private GUIStyle m_DebugBoxStyle;
private Coroutine m_CursorEnforcementCoroutine;
private void Awake()
{
TryInitializeDefaultMovement(forceRefresh: true);
}
private void OnEnable()
{
TryInitializeDefaultMovement(forceRefresh: true);
if (m_CursorEnforcementCoroutine == null) {
m_CursorEnforcementCoroutine = StartCoroutine(EnforceCursorVisibilityAtEndOfFrame());
}
}
private void Start()
{
TryInitializeDefaultMovement(forceRefresh: true);
}
private void Update()
{
if (!ResolveReferences(forceRefresh: false)) {
return;
}
UpdateZoom();
UpdateMovementMode();
UpdateMouseAimRotation();
UpdateControllerRotation();
MaintainMouseVisibility();
}
private void LateUpdate()
{
if (!ResolveReferences(forceRefresh: false)) {
return;
}
if (!IsAimActiveThisFrame()) {
RestoreDefaultMovementType();
}
}
private void OnDisable()
{
if (m_CursorEnforcementCoroutine != null) {
StopCoroutine(m_CursorEnforcementCoroutine);
m_CursorEnforcementCoroutine = null;
}
RestoreZoomInputName();
RestoreDefaultMovementType();
RestoreCursorConfiguration();
}
private void OnGUI()
{
if (!m_ShowDebugGui) {
return;
}
EnsureDebugGuiStyles();
var debugLines = BuildDebugLines();
var lineHeight = m_DebugLabelStyle.lineHeight + 2f;
var width = 280f;
var height = 12f + (debugLines.Count * lineHeight);
var rect = new Rect(Screen.width - width - 16f, 16f, width, height);
GUI.Box(rect, GUIContent.none, m_DebugBoxStyle);
var contentRect = new Rect(rect.x + 10f, rect.y + 8f, rect.width - 20f, rect.height - 16f);
for (int i = 0; i < debugLines.Count; ++i) {
var lineRect = new Rect(contentRect.x, contentRect.y + (i * lineHeight), contentRect.width, lineHeight);
GUI.Label(lineRect, debugLines[i], m_DebugLabelStyle);
}
}
private void TryInitializeDefaultMovement(bool forceRefresh)
{
if (!ResolveReferences(forceRefresh)) {
return;
}
RestoreDefaultMovementType();
}
private bool ResolveReferences(bool forceRefresh)
{
if (!forceRefresh && m_CameraController != null && m_TopDownView != null && m_CharacterLocomotion != null) {
return true;
}
m_CameraController = FindActiveCameraController();
if (m_CameraController == null) {
return false;
}
m_CameraControllerHandler = m_CameraController.GetComponent<CameraControllerHandler>();
m_CharacterLocomotion = FindPlayerCharacterLocomotion();
if (m_CharacterLocomotion == null) {
m_CharacterLocomotion = m_CameraController.CharacterLocomotion;
}
if (m_CharacterLocomotion == null && m_CameraController.Character != null) {
m_CharacterLocomotion = m_CameraController.Character.GetComponent<UltimateCharacterLocomotion>();
}
if (m_CharacterLocomotion == null) {
return false;
}
m_PlayerInput = m_CharacterLocomotion.GetComponent<IPlayerInput>();
m_TopDownView = FindTopDownView(m_CameraController);
if (m_TopDownView == null) {
return false;
}
if (m_ForceTopDownViewIfFound && !(m_CameraController.ActiveViewType is TopDownView)) {
m_CameraController.SetViewType(typeof(TopDownView), false);
}
CacheMovementTypeNames();
CacheMovementTypeInstances();
ConfigureInitialZoomState();
DisableBuiltInRightClickZoom();
ConfigureCursorMode();
RestoreDefaultMovementType();
m_Configured = true;
return true;
}
private CameraController FindActiveCameraController()
{
var mainCamera = Camera.main;
if (mainCamera != null) {
var mainCameraController = mainCamera.GetComponentInParent<CameraController>();
if (mainCameraController != null && mainCameraController.isActiveAndEnabled) {
return mainCameraController;
}
}
var cameraControllers = FindObjectsByType<CameraController>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
for (int i = 0; i < cameraControllers.Length; ++i) {
var cameraController = cameraControllers[i];
var cameraComponent = cameraController.GetComponent<Camera>();
if (cameraComponent != null && cameraComponent.isActiveAndEnabled) {
return cameraController;
}
}
return cameraControllers.Length > 0 ? cameraControllers[0] : null;
}
private UltimateCharacterLocomotion FindPlayerCharacterLocomotion()
{
GameObject player = null;
try {
player = GameObject.FindGameObjectWithTag("Player");
} catch (UnityException) {
return null;
}
if (player == null) {
return null;
}
var locomotion = player.GetComponent<UltimateCharacterLocomotion>();
if (locomotion != null) {
return locomotion;
}
locomotion = player.GetComponentInChildren<UltimateCharacterLocomotion>();
if (locomotion != null) {
return locomotion;
}
return player.GetComponentInParent<UltimateCharacterLocomotion>();
}
private TopDownView FindTopDownView(CameraController cameraController)
{
if (cameraController.ActiveViewType is TopDownView activeTopDown) {
return activeTopDown;
}
var viewTypes = cameraController.ViewTypes;
if (viewTypes == null) {
return null;
}
for (int i = 0; i < viewTypes.Length; ++i) {
if (viewTypes[i] is TopDownView topDown) {
return topDown;
}
}
return null;
}
private void CacheMovementTypeNames()
{
if (!string.IsNullOrEmpty(m_AdventureMovementTypeFullName) && !string.IsNullOrEmpty(m_TopDownMovementTypeFullName)) {
return;
}
var movementTypes = m_CharacterLocomotion.MovementTypes;
for (int i = 0; i < movementTypes.Length; ++i) {
if (string.IsNullOrEmpty(m_AdventureMovementTypeFullName) && movementTypes[i] is AdventureMovementType) {
m_AdventureMovementTypeFullName = c_AdventureMovementTypeFullName;
}
if (movementTypes[i] is TopDownMovementType) {
m_TopDownMovementTypeFullName = c_TopDownMovementTypeFullName;
}
}
}
private void CacheMovementTypeInstances()
{
if (m_TopDownMovementType != null) {
return;
}
var movementTypes = m_CharacterLocomotion.MovementTypes;
for (int i = 0; i < movementTypes.Length; ++i) {
if (movementTypes[i] is TopDownMovementType topDownMovementType) {
m_TopDownMovementType = topDownMovementType;
break;
}
}
ConfigureTopDownMovementType();
}
private void ConfigureInitialZoomState()
{
if (m_Configured) {
return;
}
m_TargetViewDistance = Mathf.Clamp(m_TopDownView.ViewDistance, m_MinViewDistance, m_MaxViewDistance);
m_TopDownView.ViewDistance = m_TargetViewDistance;
m_PitchRange = Mathf.Max(0f, m_TopDownView.PitchLimit.MaxValue - m_TopDownView.PitchLimit.MinValue);
m_CurrentPitchMin = m_TopDownView.PitchLimit.MinValue;
}
private void DisableBuiltInRightClickZoom()
{
if (!m_DisableBuiltInRightClickZoom || m_CameraControllerHandler == null) {
return;
}
if (m_OriginalZoomInputName == null) {
m_OriginalZoomInputName = m_CameraControllerHandler.ZoomInputName;
}
m_CameraControllerHandler.ZoomInputName = "__DisabledByTopDownCameraHack__";
m_CameraController.TryZoom(false);
}
private void RestoreZoomInputName()
{
if (m_CameraControllerHandler == null || m_OriginalZoomInputName == null) {
return;
}
m_CameraControllerHandler.ZoomInputName = m_OriginalZoomInputName;
}
private void UpdateZoom()
{
var deltaTime = Time.unscaledDeltaTime;
var zoomInput = GetZoomInput(deltaTime);
if (!Mathf.Approximately(zoomInput, 0f)) {
m_TargetViewDistance = Mathf.Clamp(m_TargetViewDistance - zoomInput, m_MinViewDistance, m_MaxViewDistance);
}
m_TopDownView.ViewDistance = Mathf.Lerp(m_TopDownView.ViewDistance, m_TargetViewDistance, 1f - Mathf.Exp(-m_ZoomSmoothSpeed * deltaTime));
var zoomT = Mathf.InverseLerp(m_MaxViewDistance, m_MinViewDistance, m_TargetViewDistance);
var targetPitchMin = Mathf.Lerp(m_ZoomedOutPitch, m_ZoomedInPitch, zoomT);
m_CurrentPitchMin = Mathf.Lerp(m_CurrentPitchMin, targetPitchMin, 1f - Mathf.Exp(-m_PitchSmoothSpeed * deltaTime));
var targetPitchMax = Mathf.Clamp(m_CurrentPitchMin + m_PitchRange, m_CurrentPitchMin, m_MaxPitchLimit);
m_TopDownView.PitchLimit = new MinMaxFloat(m_CurrentPitchMin, targetPitchMax);
}
private float GetZoomInput(float deltaTime)
{
var zoomInput = 0f;
#if ENABLE_INPUT_SYSTEM
if (Mouse.current != null) {
var allowMouseWheelZoom = true;
if (m_MouseWheelZoomModifierKey != KeyCode.None) {
allowMouseWheelZoom = Keyboard.current != null && IsModifierKeyPressed(Keyboard.current, m_MouseWheelZoomModifierKey);
}
if (allowMouseWheelZoom) {
zoomInput += Mouse.current.scroll.ReadValue().y * m_MouseWheelZoomStep * 0.05f;
}
}
if (Keyboard.current != null) {
if (Keyboard.current.equalsKey.isPressed || Keyboard.current.numpadPlusKey.isPressed) {
zoomInput += m_KeyboardZoomSpeed * deltaTime;
}
if (Keyboard.current.minusKey.isPressed || Keyboard.current.numpadMinusKey.isPressed) {
zoomInput -= m_KeyboardZoomSpeed * deltaTime;
}
}
if (Gamepad.current != null) {
zoomInput += Gamepad.current.rightStick.ReadValue().y * m_ControllerZoomSpeed * deltaTime;
}
#else
if (m_MouseWheelZoomModifierKey == KeyCode.None || Input.GetKey(m_MouseWheelZoomModifierKey)) {
zoomInput += Input.mouseScrollDelta.y * m_MouseWheelZoomStep;
}
if (Input.GetKey(KeyCode.Equals) || Input.GetKey(KeyCode.KeypadPlus)) {
zoomInput += m_KeyboardZoomSpeed * deltaTime;
}
if (Input.GetKey(KeyCode.Minus) || Input.GetKey(KeyCode.KeypadMinus)) {
zoomInput -= m_KeyboardZoomSpeed * deltaTime;
}
#endif
return zoomInput;
}
private void UpdateMovementMode()
{
if (!m_SwitchToTopDownMovementWhileAiming) {
RestoreDefaultMovementType();
return;
}
var targetMovementTypeFullName = GetAimMovementTypeFullName();
var shouldAim = !string.IsNullOrEmpty(targetMovementTypeFullName);
if (!shouldAim) {
m_AimMovementActive = false;
RestoreDefaultMovementType();
return;
}
if (shouldAim == m_AimMovementActive && m_CharacterLocomotion.MovementTypeFullName == targetMovementTypeFullName) {
return;
}
m_AimMovementActive = shouldAim;
ApplyMovementType(targetMovementTypeFullName);
}
private void RestoreDefaultMovementType()
{
if (m_CharacterLocomotion == null) {
return;
}
if (string.IsNullOrEmpty(m_AdventureMovementTypeFullName)) {
return;
}
m_AimMovementActive = false;
SetThirdPersonMovementType(m_AdventureMovementTypeFullName, true);
}
private void UpdateMouseAimRotation()
{
if (!m_UseSmoothedMouseAimRotation || !IsMouseAimHeld() || m_CameraController == null || m_CharacterLocomotion == null) {
return;
}
var cameraTransform = m_CameraController.CameraTransform;
if (cameraTransform == null) {
return;
}
Vector2 mousePosition;
#if ENABLE_INPUT_SYSTEM
if (Mouse.current == null) {
return;
}
mousePosition = Mouse.current.position.ReadValue();
#else
mousePosition = Input.mousePosition;
#endif
var ray = cameraTransform.GetComponent<Camera>().ScreenPointToRay(mousePosition);
var characterPosition = m_CharacterLocomotion.transform.position;
var aimPlane = new Plane(m_CharacterLocomotion.Up, characterPosition);
if (!aimPlane.Raycast(ray, out var distance)) {
return;
}
var aimPoint = ray.GetPoint(distance);
var aimDirection = Vector3.ProjectOnPlane(aimPoint - characterPosition, m_CharacterLocomotion.Up);
if (aimDirection.sqrMagnitude < m_MinMouseAimDistance * m_MinMouseAimDistance) {
return;
}
var targetRotation = Quaternion.LookRotation(aimDirection.normalized, m_CharacterLocomotion.Up);
var smoothedRotation = Quaternion.RotateTowards(m_CharacterLocomotion.Rotation, targetRotation, m_MouseAimRotateSpeed * Time.deltaTime);
m_CharacterLocomotion.SetRotation(smoothedRotation, false);
}
private void UpdateControllerRotation()
{
var horizontalAim = GetControllerHorizontalAimInput();
if (Mathf.Abs(horizontalAim) < m_ControllerAimThreshold) {
return;
}
var currentRotation = m_CharacterLocomotion.Rotation;
var targetRotation = currentRotation * Quaternion.AngleAxis(horizontalAim * m_ControllerRotateSpeed * Time.deltaTime, m_CharacterLocomotion.Up);
m_CharacterLocomotion.SetRotation(targetRotation, false);
}
private bool IsMouseAimHeld()
{
if (m_PlayerInput != null && !string.IsNullOrEmpty(m_AimInputName)) {
return m_PlayerInput.GetButton(m_AimInputName);
}
#if ENABLE_INPUT_SYSTEM
if (Mouse.current != null && Mouse.current.rightButton.isPressed) {
return true;
}
#endif
return Input.GetMouseButton(1);
}
private float GetControllerHorizontalAimInput()
{
#if ENABLE_INPUT_SYSTEM
if (Gamepad.current != null) {
return Gamepad.current.rightStick.ReadValue().x;
}
#endif
return 0f;
}
private string GetAimMovementTypeFullName()
{
if (IsMouseAimHeld()) {
return !string.IsNullOrEmpty(m_TopDownMovementTypeFullName) ? m_TopDownMovementTypeFullName : null;
}
if (m_EnableControllerAimMode && Mathf.Abs(GetControllerHorizontalAimInput()) >= m_ControllerAimThreshold) {
return !string.IsNullOrEmpty(m_TopDownMovementTypeFullName) ? m_TopDownMovementTypeFullName : null;
}
return null;
}
private bool IsAimActiveThisFrame()
{
return !string.IsNullOrEmpty(GetAimMovementTypeFullName());
}
private void ApplyMovementType(string movementTypeFullName)
{
if (m_CharacterLocomotion == null || string.IsNullOrEmpty(movementTypeFullName)) {
return;
}
ConfigureTopDownMovementType();
SetThirdPersonMovementType(movementTypeFullName, false);
}
private void SetThirdPersonMovementType(string movementTypeFullName, bool forceActivate)
{
if (m_CharacterLocomotion == null || string.IsNullOrEmpty(movementTypeFullName)) {
return;
}
if (m_CharacterLocomotion.ThirdPersonMovementTypeFullName != movementTypeFullName) {
m_CharacterLocomotion.ThirdPersonMovementTypeFullName = movementTypeFullName;
}
if (forceActivate || m_CharacterLocomotion.MovementTypeFullName != movementTypeFullName || NeedsMovementTypeSwitch(movementTypeFullName)) {
m_CharacterLocomotion.SetMovementType(movementTypeFullName);
}
}
private bool NeedsMovementTypeSwitch(string movementTypeFullName)
{
if (m_CharacterLocomotion == null || string.IsNullOrEmpty(movementTypeFullName)) {
return false;
}
var activeMovementType = m_CharacterLocomotion.ActiveMovementType;
if (activeMovementType == null) {
return true;
}
return activeMovementType.GetType().FullName != movementTypeFullName;
}
private void ConfigureTopDownMovementType()
{
if (m_TopDownMovementType == null) {
return;
}
if (m_ForceTopDownRelativeCameraMovement) {
m_TopDownMovementType.RelativeCameraMovement = true;
}
if (m_ForceTopDownLookAtCursor) {
m_TopDownMovementType.LookInMoveDirection = false;
}
}
private void ConfigureCursorMode()
{
if (!m_KeepMouseVisible || m_CharacterLocomotion == null) {
return;
}
if (!m_CursorStateCached) {
m_PreviousCursorLockMode = Cursor.lockState;
m_PreviousCursorVisible = Cursor.visible;
m_CursorStateCached = true;
}
CacheAndOverrideCursorProperties(m_CharacterLocomotion.GetComponents<MonoBehaviour>());
CacheAndOverrideCursorProperties(m_CharacterLocomotion.GetComponentsInChildren<MonoBehaviour>(true));
CacheAndOverrideCursorProperties(m_CharacterLocomotion.GetComponentsInParent<MonoBehaviour>(true));
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
private void MaintainMouseVisibility()
{
if (!m_KeepMouseVisible) {
return;
}
if (!Cursor.visible || Cursor.lockState != CursorLockMode.None) {
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
}
private void RestoreCursorConfiguration()
{
for (int i = 0; i < m_CursorManagedComponents.Count; ++i) {
var component = m_CursorManagedComponents[i];
if (component == null) {
continue;
}
SetBoolProperty(component, "DisableCursor", m_PreviousDisableCursorValues[i]);
SetBoolProperty(component, "EnableCursorWithEscape", m_PreviousEnableCursorWithEscapeValues[i]);
}
m_CursorManagedComponents.Clear();
m_PreviousDisableCursorValues.Clear();
m_PreviousEnableCursorWithEscapeValues.Clear();
if (!m_CursorStateCached) {
return;
}
Cursor.lockState = m_PreviousCursorLockMode;
Cursor.visible = m_PreviousCursorVisible;
m_CursorStateCached = false;
}
private void CacheAndOverrideCursorProperties(MonoBehaviour[] components)
{
for (int i = 0; i < components.Length; ++i) {
var component = components[i];
if (component == null) {
continue;
}
if (!TryGetBoolProperty(component, "DisableCursor", out var disableCursorValue)) {
continue;
}
if (m_CursorManagedComponents.Contains(component)) {
continue;
}
var enableCursorWithEscapeValue = false;
TryGetBoolProperty(component, "EnableCursorWithEscape", out enableCursorWithEscapeValue);
m_CursorManagedComponents.Add(component);
m_PreviousDisableCursorValues.Add(disableCursorValue);
m_PreviousEnableCursorWithEscapeValues.Add(enableCursorWithEscapeValue);
SetBoolProperty(component, "DisableCursor", false);
SetBoolProperty(component, "EnableCursorWithEscape", true);
}
}
private IEnumerator EnforceCursorVisibilityAtEndOfFrame()
{
while (true) {
yield return new WaitForEndOfFrame();
if (!m_KeepMouseVisible) {
continue;
}
if (m_CharacterLocomotion != null) {
ConfigureCursorMode();
}
if (!Cursor.visible || Cursor.lockState != CursorLockMode.None) {
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
}
}
private bool TryGetBoolProperty(Component component, string propertyName, out bool value)
{
value = false;
if (component == null) {
return false;
}
var property = component.GetType().GetProperty(propertyName, c_InstanceFlags);
if (property == null || property.PropertyType != typeof(bool) || !property.CanRead) {
return false;
}
value = (bool)property.GetValue(component);
return true;
}
private void SetBoolProperty(Component component, string propertyName, bool value)
{
if (component == null) {
return;
}
var property = component.GetType().GetProperty(propertyName, c_InstanceFlags);
if (property == null || property.PropertyType != typeof(bool) || !property.CanWrite) {
return;
}
property.SetValue(component, value);
}
private void EnsureDebugGuiStyles()
{
if (m_DebugLabelStyle == null) {
m_DebugLabelStyle = new GUIStyle(GUI.skin.label) {
alignment = TextAnchor.UpperLeft,
fontSize = 13,
normal = { textColor = Color.white }
};
}
if (m_DebugBoxStyle == null) {
var backgroundTexture = new Texture2D(1, 1, TextureFormat.RGBA32, false);
backgroundTexture.SetPixel(0, 0, new Color(0f, 0f, 0f, 0.72f));
backgroundTexture.Apply();
m_DebugBoxStyle = new GUIStyle(GUI.skin.box);
m_DebugBoxStyle.normal.background = backgroundTexture;
}
}
private List<string> BuildDebugLines()
{
var lines = new List<string>(8) {
"Controller Debug"
};
#if ENABLE_INPUT_SYSTEM
var gamepad = Gamepad.current;
if (gamepad == null) {
lines.Add("Connected: no");
lines.Add("Left Stick: (0.00, 0.00)");
lines.Add("Right Stick: (0.00, 0.00)");
lines.Add("L2: 0.00 | pressed: no");
lines.Add("R2: 0.00 | pressed: no");
return lines;
}
var leftStick = gamepad.leftStick.ReadValue();
var rightStick = gamepad.rightStick.ReadValue();
var leftTrigger = gamepad.leftTrigger.ReadValue();
var rightTrigger = gamepad.rightTrigger.ReadValue();
lines.Add("Connected: yes");
lines.Add($"Name: {gamepad.displayName}");
lines.Add($"Left Stick: ({leftStick.x:F2}, {leftStick.y:F2}) | mag {leftStick.magnitude:F2}");
lines.Add($"Right Stick: ({rightStick.x:F2}, {rightStick.y:F2}) | mag {rightStick.magnitude:F2}");
lines.Add($"L2: {leftTrigger:F2} | pressed: {BoolToYesNo(leftTrigger >= m_DebugTriggerPressedThreshold)}");
lines.Add($"R2: {rightTrigger:F2} | pressed: {BoolToYesNo(rightTrigger >= m_DebugTriggerPressedThreshold)}");
#else
var joystickNames = Input.GetJoystickNames();
var connected = joystickNames != null && joystickNames.Length > 0 && !string.IsNullOrEmpty(joystickNames[0]);
var leftStick = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
var rightStick = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
lines.Add($"Connected: {BoolToYesNo(connected)}");
lines.Add($"Name: {(connected ? joystickNames[0] : "n/a")}");
lines.Add($"Left Stick: ({leftStick.x:F2}, {leftStick.y:F2}) | mag {leftStick.magnitude:F2}");
lines.Add($"Right Stick: ({rightStick.x:F2}, {rightStick.y:F2}) | mag {rightStick.magnitude:F2}");
lines.Add("L2: n/a");
lines.Add("R2: n/a");
#endif
return lines;
}
private string BoolToYesNo(bool value)
{
return value ? "yes" : "no";
}
#if ENABLE_INPUT_SYSTEM
private bool IsModifierKeyPressed(Keyboard keyboard, KeyCode keyCode)
{
if (keyboard == null) {
return false;
}
switch (keyCode) {
case KeyCode.V:
return keyboard.vKey.isPressed;
case KeyCode.LeftShift:
return keyboard.leftShiftKey.isPressed;
case KeyCode.RightShift:
return keyboard.rightShiftKey.isPressed;
case KeyCode.LeftControl:
return keyboard.leftCtrlKey.isPressed;
case KeyCode.RightControl:
return keyboard.rightCtrlKey.isPressed;
case KeyCode.LeftAlt:
return keyboard.leftAltKey.isPressed;
case KeyCode.RightAlt:
return keyboard.rightAltKey.isPressed;
case KeyCode.Space:
return keyboard.spaceKey.isPressed;
default:
return false;
}
}
#endif
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment