[Puzzles][Input] Update input handling to not mistakingly miss frames. Add debug frame input debugging.

This commit is contained in:
Michal Pikulski
2025-09-03 16:55:21 +02:00
parent 93242b2702
commit 1dfcee3d2c
9 changed files with 196 additions and 26 deletions

8
Assets/Resources.meta Normal file
View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cfa619a4e508a184588b500e8b34ac81
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 42111873997850f4cbced0be4400e7f9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,28 @@
fileFormatVersion: 2
guid: d7cffddcbc0cc8f4ebe6e28eb9804082
TrueTypeFontImporter:
externalObjects: {}
serializedVersion: 4
fontSize: 16
forceTextureCase: -2
characterSpacing: 0
characterPadding: 1
includeFontData: 1
fontNames:
- Square
fallbackFontReferences: []
customCharacters:
fontRenderingMode: 0
ascentCalculationMode: 1
useLegacyBoundsCalculation: 0
shouldRoundAdvanceValue: 1
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 216954
packageName: Fatality FPS Gaming Font
packageVersion: 1.0
assetPath: Assets/FPSFont/FPS Gaming Font/Square-Black.ttf
uploadId: 490185

View File

@@ -776,6 +776,85 @@ PrefabInstance:
m_AddedGameObjects: [] m_AddedGameObjects: []
m_AddedComponents: [] m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} m_SourcePrefab: {fileID: 100100000, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
--- !u!1 &1255598765
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1255598768}
- component: {fileID: 1255598767}
- component: {fileID: 1255598766}
m_Layer: 0
m_Name: EventSystem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1255598766
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1255598765}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
m_Name:
m_EditorClassIdentifier:
m_SendPointerHoverToParent: 1
m_MoveRepeatDelay: 0.5
m_MoveRepeatRate: 0.1
m_XRTrackingOrigin: {fileID: 0}
m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_PointAction: {fileID: -1654692200621890270, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_MoveAction: {fileID: -8784545083839296357, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_SubmitAction: {fileID: 392368643174621059, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_CancelAction: {fileID: 7727032971491509709, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_LeftClickAction: {fileID: 3001919216989983466, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_MiddleClickAction: {fileID: -2185481485913320682, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_RightClickAction: {fileID: -4090225696740746782, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_ScrollWheelAction: {fileID: 6240969308177333660, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_TrackedDevicePositionAction: {fileID: 6564999863303420839, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_TrackedDeviceOrientationAction: {fileID: 7970375526676320489, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_DeselectOnBackgroundClick: 1
m_PointerBehavior: 0
m_CursorLockBehavior: 0
m_ScrollDeltaPerTick: 6
--- !u!114 &1255598767
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1255598765}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 10
--- !u!4 &1255598768
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1255598765}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &1309036670 stripped --- !u!4 &1309036670 stripped
Transform: Transform:
m_CorrespondingSourceObject: {fileID: 3823830588451517910, guid: 301b4e0735896334f8f6fb9a68a7e419, type: 3} m_CorrespondingSourceObject: {fileID: 3823830588451517910, guid: 301b4e0735896334f8f6fb9a68a7e419, type: 3}
@@ -22995,3 +23074,4 @@ SceneRoots:
- {fileID: 1950557796102186365} - {fileID: 1950557796102186365}
- {fileID: 638340961} - {fileID: 638340961}
- {fileID: 218805561} - {fileID: 218805561}
- {fileID: 1255598768}

View File

@@ -31,15 +31,23 @@ public class DebugUIMessage : MonoBehaviour
textGO.transform.SetParent(canvas.transform); textGO.transform.SetParent(canvas.transform);
messageText = textGO.AddComponent<Text>(); messageText = textGO.AddComponent<Text>();
messageText.alignment = TextAnchor.MiddleCenter; messageText.alignment = TextAnchor.MiddleCenter;
messageText.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); // Try to load a custom font from Resources/Fonts/DebugFont.ttf
messageText.fontSize = 32; Font customFont = Resources.Load<Font>("Fonts/DebugFont");
if (customFont != null)
messageText.font = customFont;
else
messageText.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
messageText.fontSize = 16;
messageText.color = Color.yellow; messageText.color = Color.yellow;
var outline = textGO.AddComponent<Outline>();
outline.effectColor = Color.black;
outline.effectDistance = new Vector2(2, -2);
var rect = messageText.GetComponent<RectTransform>(); var rect = messageText.GetComponent<RectTransform>();
rect.anchorMin = new Vector2(0.5f, 0.1f); rect.anchorMin = new Vector2(0.5f, 0.5f);
rect.anchorMax = new Vector2(0.5f, 0.1f); rect.anchorMax = new Vector2(0.5f, 0.5f);
rect.pivot = new Vector2(0.5f, 0.5f); rect.pivot = new Vector2(0.5f, 0.5f);
rect.anchoredPosition = Vector2.zero; rect.anchoredPosition = Vector2.zero;
rect.sizeDelta = new Vector2(800, 100); rect.sizeDelta = new Vector2(400, 40);
messageText.text = ""; messageText.text = "";
} }
@@ -59,4 +67,3 @@ public class DebugUIMessage : MonoBehaviour
messageText.enabled = false; messageText.enabled = false;
} }
} }

View File

@@ -4,22 +4,41 @@ using System;
public class InputManager : MonoBehaviour public class InputManager : MonoBehaviour
{ {
public static InputManager Instance { get; private set; } private static InputManager _instance;
public static InputManager Instance
{
get
{
if (_instance == null)
{
_instance = FindAnyObjectByType<InputManager>();
if (_instance == null)
{
var go = new GameObject("InputManager");
_instance = go.AddComponent<InputManager>();
DontDestroyOnLoad(go);
}
}
return _instance;
}
}
private PlayerInput playerInput; private PlayerInput playerInput;
private InputAction touchPressAction; private InputAction touchPressAction;
private InputAction touchPositionAction; private InputAction touchPositionAction;
private ITouchInputConsumer defaultConsumer; private ITouchInputConsumer defaultConsumer;
private bool isTouchHeld = false; private bool isTouchHeld = false;
private bool lastFrameInteracted = false;
void Awake() void Awake()
{ {
if (Instance != null && Instance != this) if (_instance != null && _instance != this)
{ {
Destroy(gameObject); Destroy(gameObject);
return; return;
} }
Instance = this; _instance = this;
DontDestroyOnLoad(gameObject); DontDestroyOnLoad(gameObject);
playerInput = GetComponent<PlayerInput>(); playerInput = GetComponent<PlayerInput>();
if (playerInput == null) if (playerInput == null)
@@ -62,17 +81,20 @@ public class InputManager : MonoBehaviour
private void OnTouchPressStarted(InputAction.CallbackContext ctx) private void OnTouchPressStarted(InputAction.CallbackContext ctx)
{ {
// Touch started (finger down) // Touch started (finger down)
isTouchHeld = true;
Vector3 _screenPos = Camera.main.ScreenToWorldPoint(touchPositionAction.ReadValue<Vector2>()); Vector3 _screenPos = Camera.main.ScreenToWorldPoint(touchPositionAction.ReadValue<Vector2>());
Vector2 screenPos = new Vector2(_screenPos.x, _screenPos.y); Vector2 screenPos = new Vector2(_screenPos.x, _screenPos.y);
if (!TryDelegateToInteractable(screenPos)) lastFrameInteracted = TryDelegateToInteractable(screenPos);
if (!lastFrameInteracted)
defaultConsumer?.OnTouchPress(screenPos); defaultConsumer?.OnTouchPress(screenPos);
isTouchHeld = true;
} }
private void OnTouchPressCanceled(InputAction.CallbackContext ctx) private void OnTouchPressCanceled(InputAction.CallbackContext ctx)
{ {
// Touch released (finger up) // Touch released (finger up)
isTouchHeld = false; isTouchHeld = false;
// Reset lastFrameInteracted for next frame
lastFrameInteracted = false;
// Optionally, you can notify consumers of release if needed // Optionally, you can notify consumers of release if needed
} }
@@ -84,11 +106,8 @@ public class InputManager : MonoBehaviour
// Convert to world position // Convert to world position
Vector3 worldPos = Camera.main.ScreenToWorldPoint(pos); Vector3 worldPos = Camera.main.ScreenToWorldPoint(pos);
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y); Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
defaultConsumer?.OnTouchPress(worldPos2D); // Move continuously to finger position if (!lastFrameInteracted)
} defaultConsumer?.OnTouchPress(worldPos2D); // Move continuously to finger position
else
{
defaultConsumer?.OnTouchPosition(pos); // For drag or hover
} }
} }
@@ -100,7 +119,8 @@ public class InputManager : MonoBehaviour
Vector2 pos = touchPositionAction.ReadValue<Vector2>(); Vector2 pos = touchPositionAction.ReadValue<Vector2>();
Vector3 worldPos = Camera.main.ScreenToWorldPoint(pos); Vector3 worldPos = Camera.main.ScreenToWorldPoint(pos);
Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y); Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y);
defaultConsumer?.OnTouchPress(worldPos2D); if (!lastFrameInteracted)
defaultConsumer?.OnTouchPress(worldPos2D);
} }
} }

View File

@@ -10,20 +10,21 @@ public class ObjectiveStepBehaviour : MonoBehaviour
void Awake() void Awake()
{ {
interactable = GetComponent<Interactable>(); interactable = GetComponent<Interactable>();
}
void OnEnable()
{
if (interactable == null)
interactable = GetComponent<Interactable>();
if (interactable != null) if (interactable != null)
{
interactable.Interacted += OnInteracted; interactable.Interacted += OnInteracted;
}
// Register with PuzzleManager
PuzzleManager.Instance?.RegisterStepBehaviour(this); PuzzleManager.Instance?.RegisterStepBehaviour(this);
} }
void OnDestroy() void OnDisable()
{ {
if (interactable != null) if (interactable != null)
{
interactable.Interacted -= OnInteracted; interactable.Interacted -= OnInteracted;
}
PuzzleManager.Instance?.UnregisterStepBehaviour(this); PuzzleManager.Instance?.UnregisterStepBehaviour(this);
} }

View File

@@ -3,7 +3,25 @@ using System.Collections.Generic;
public class PuzzleManager : MonoBehaviour public class PuzzleManager : MonoBehaviour
{ {
public static PuzzleManager Instance { get; private set; } private static PuzzleManager _instance;
public static PuzzleManager Instance
{
get
{
if (_instance == null)
{
_instance = FindAnyObjectByType<PuzzleManager>();
if (_instance == null)
{
var go = new GameObject("PuzzleManager");
_instance = go.AddComponent<PuzzleManager>();
DontDestroyOnLoad(go);
}
}
return _instance;
}
}
private HashSet<PuzzleStepSO> completedSteps = new HashSet<PuzzleStepSO>(); private HashSet<PuzzleStepSO> completedSteps = new HashSet<PuzzleStepSO>();
private HashSet<PuzzleStepSO> unlockedSteps = new HashSet<PuzzleStepSO>(); private HashSet<PuzzleStepSO> unlockedSteps = new HashSet<PuzzleStepSO>();
@@ -15,12 +33,12 @@ public class PuzzleManager : MonoBehaviour
void Awake() void Awake()
{ {
if (Instance != null && Instance != this) if (_instance != null && _instance != this)
{ {
Destroy(gameObject); Destroy(gameObject);
return; return;
} }
Instance = this; _instance = this;
DontDestroyOnLoad(gameObject); DontDestroyOnLoad(gameObject);
} }