Files
PacManUdon/Assets/Scripts/PlayerInput.cs
2026-06-23 13:00:48 +02:00

274 lines
7.2 KiB
C#

namespace Marro.PacManUdon
{
using System;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon.Common;
enum InputMethod
{
KeyboardMouse,
Other,
}
public class PlayerInput : SyncedObject
{
public bool active;
private GameManager gameManager;
private VRCPlayerApi player;
private InputMethod inputMethod;
private Direction resultInput;
private Vector2 analogInput;
private bool dirty;
private HandType lastUsedHand;
private bool horizontalPriority;
public void Initialize(GameManager gameManager)
{
this.gameManager = gameManager;
player = Networking.LocalPlayer;
inputMethod = InputMethod.KeyboardMouse;
resultInput = Direction.Zero;
analogInput = Vector2.zero;
dirty = false;
horizontalPriority = false;
SubscribeToEvent(NetworkEventType.InputChange);
}
void Update()
{
if (active)
{
if (Input.GetKeyDown(KeyCode.R))
{
gameManager.ResetButtonPressed();
}
if (Input.GetKeyDown(KeyCode.G))
{
gameManager.networkManager.DoFullSync();
}
if (Input.GetKeyDown(KeyCode.C))
{
gameManager.JumpToTimeSequenceBoardClear();
}
}
else
{
if (Input.GetKeyDown(KeyCode.T))
{
gameManager.ResetButtonPressed();
}
}
}
public override void SyncedUpdate()
{
if (dirty) // Update now to ensure input feedback is performed timely
{
UpdateResultInput();
}
}
public void Activate()
{
Debug.Log($"{gameObject} got activated, {player} was immobilized");
active = true;
player.SetWalkSpeed(0);
player.SetRunSpeed(0);
player.SetStrafeSpeed(0);
gameManager.JoystickGrabbed();
}
public void Deactivate()
{
Debug.Log($"{gameObject} got deactivated, {player} was released");
player.SetWalkSpeed(2);
player.SetRunSpeed(4);
player.SetStrafeSpeed(2);
active = false;
gameManager.JoystickReleased();
}
public override void InputJump(bool pressed, UdonInputEventArgs args)
{
if (!active)
{
return;
}
if (pressed)
{
Deactivate();
}
}
public override void InputMoveHorizontal(float value, UdonInputEventArgs args)
{
if (!active)
{
return;
}
analogInput.x = value;
lastUsedHand = args.handType;
dirty = true;
}
public override void InputMoveVertical(float value, UdonInputEventArgs args)
{
if (!active)
{
return;
}
analogInput.y = value;
lastUsedHand = args.handType;
dirty = true;
}
public override void OnInputMethodChanged(VRCInputMethod inputMethod)
{
switch (inputMethod)
{
case VRCInputMethod.Keyboard:
case VRCInputMethod.Mouse:
this.inputMethod = InputMethod.KeyboardMouse;
return;
default:
this.inputMethod = InputMethod.Other;
return;
}
}
private void UpdateResultInput()
{
dirty = false;
var newResult = GetResultInput(analogInput);
if (newResult == resultInput)
{
return;
}
Debug.Log($"Switched to input direction {newResult} from analogInput {analogInput} with HorizontalPriority {horizontalPriority}");
resultInput = newResult;
networkManager.SendEventSoon(NetworkEventType.InputChange, true);
PlayHaptics();
}
private void PlayHaptics()
{
if (inputMethod == InputMethod.KeyboardMouse)
{
return;
}
VRC_Pickup.PickupHand hand;
switch (lastUsedHand)
{
case HandType.LEFT:
hand = VRC_Pickup.PickupHand.Left;
break;
case HandType.RIGHT:
hand = VRC_Pickup.PickupHand.Right;
break;
default:
return;
}
player.PlayHapticEventInHand(hand, 0.1f, 0.15f, 75);
}
private Direction GetResultInput(Vector2 analogInput)
{
if (analogInput.magnitude < 0.8)
{
return Direction.Zero;
}
var normalized = analogInput.normalized;
Debug.Log($"Checking analogInput {analogInput} with HorizontalPriority {horizontalPriority}, normalized {normalized}");
const float directionDivider = 0.72f;
if (normalized.x > directionDivider)
{
horizontalPriority = false;
return Direction.Right;
}
else if (normalized.x < -directionDivider)
{
horizontalPriority = false;
return Direction.Left;
}
else if (normalized.y > directionDivider)
{
horizontalPriority = true;
return Direction.Up;
}
else if (normalized.y < -directionDivider)
{
horizontalPriority = true;
return Direction.Down;
}
if (horizontalPriority)
{
if (normalized.x > 0)
{
return Direction.Right;
}
return Direction.Left;
}
if (normalized.y > 0)
{
return Direction.Up;
}
return Direction.Down;
}
public Direction GetDirection()
{
if (dirty) // Update now to reduce input delay
{
UpdateResultInput();
}
return resultInput;
}
public override void CollectSyncedData(byte[] data, ref int index, NetworkEventType eventType)
{
if (eventType != NetworkEventType.InputChange)
{
return;
}
ByteUtils.AppendAsByte(data, (int)resultInput, ref index);
}
public override bool WriteSyncedData(byte[] data, ref int index, NetworkEventType eventType)
{
if (eventType != NetworkEventType.InputChange)
{
return true;
}
resultInput = (Direction)ByteUtils.ReadByte(data, ref index);
return true;
}
}
}