feat: add reusable virtual hud input
This commit is contained in:
@@ -5,6 +5,7 @@ using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UI;
|
||||
using XGame.VirtualInput;
|
||||
using XWorld.Framework.Protocol;
|
||||
using UObject = UnityEngine.Object;
|
||||
|
||||
@@ -29,7 +30,7 @@ namespace XGame
|
||||
public bool IsPlaceholder; // Obj 当前是胶囊占位(真实角色预设还在异步加载),加载完成后会原地升级
|
||||
}
|
||||
|
||||
private const string JoystickPrefabPath = "Assets/Game/Art/UI/Prefab/UI_LobbyJoystick.prefab";
|
||||
private const string JoystickPrefabPath = "Assets/Game/Art/UI/Prefab/UI_VirtualJoystick.prefab";
|
||||
private const string CharacterConfigResourcePath = "Config/CharacterConfig";
|
||||
private const string SelectedCharacterKey = "CharacterSwitch.SelectedCharacterId";
|
||||
private const float MoveSpeed = 1f;
|
||||
@@ -39,7 +40,6 @@ namespace XGame
|
||||
private const float DirectionChangeMinInterval = 0.1f;
|
||||
private const float DirectionChangeDot = 0.98f;
|
||||
private const float JoystickRadius = 74f;
|
||||
private const float JoystickKnobRadius = 28f;
|
||||
private const float JoystickPadding = 100.0f;
|
||||
private const float JoystickDeadZone = 0.18f;
|
||||
private const float JoystickAcquireRadiusMultiplier = 1.6f;
|
||||
@@ -83,6 +83,7 @@ namespace XGame
|
||||
private float lastPinchDistance;
|
||||
private RectTransform joystickRoot;
|
||||
private RectTransform joystickWidget; // 视觉容器:新预设里的 "Joystick" 子节点(自带定位);找不到则回退为 joystickRoot
|
||||
private VirtualJoystick virtualJoystick;
|
||||
private RectTransform joystickKnob;
|
||||
private bool joystickMouseCaptured;
|
||||
private int joystickTouchFingerId = -1;
|
||||
@@ -151,6 +152,7 @@ namespace XGame
|
||||
{
|
||||
joystickRoot.gameObject.SetActive(false);
|
||||
}
|
||||
OnVirtualJoystickEnded();
|
||||
}
|
||||
|
||||
public void RefreshSelectedFigure()
|
||||
@@ -218,6 +220,11 @@ namespace XGame
|
||||
UpdateCamera();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
ReleaseJoystickUI(true);
|
||||
}
|
||||
|
||||
private void ApplyState(LobbyStateMsg state)
|
||||
{
|
||||
ReconcileSelfPlayerId(state);
|
||||
@@ -382,7 +389,6 @@ namespace XGame
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateJoystick();
|
||||
Vector3 dir = GetMoveDirection();
|
||||
bool moving = dir.sqrMagnitude > 0.001f;
|
||||
if (moving)
|
||||
@@ -418,17 +424,36 @@ namespace XGame
|
||||
Camera cam = Camera.main;
|
||||
Vector3 forward = cam != null ? cam.transform.forward : Vector3.forward;
|
||||
Vector3 right = cam != null ? cam.transform.right : Vector3.right;
|
||||
forward.y = 0f;
|
||||
right.y = 0f;
|
||||
forward = forward.sqrMagnitude > 0.001f ? forward.normalized : Vector3.forward;
|
||||
right = right.sqrMagnitude > 0.001f ? right.normalized : Vector3.right;
|
||||
return MapMoveInputForTest(
|
||||
joystickActive ? joystick : Vector2.zero,
|
||||
forward,
|
||||
right,
|
||||
Input.GetKey(KeyCode.W),
|
||||
Input.GetKey(KeyCode.S),
|
||||
Input.GetKey(KeyCode.A),
|
||||
Input.GetKey(KeyCode.D));
|
||||
}
|
||||
|
||||
public static Vector3 MapMoveInputForTest(
|
||||
Vector2 joystickInput,
|
||||
Vector3 cameraForward,
|
||||
Vector3 cameraRight,
|
||||
bool keyW,
|
||||
bool keyS,
|
||||
bool keyA,
|
||||
bool keyD)
|
||||
{
|
||||
cameraForward.y = 0f;
|
||||
cameraRight.y = 0f;
|
||||
Vector3 forward = cameraForward.sqrMagnitude > 0.001f ? cameraForward.normalized : Vector3.forward;
|
||||
Vector3 right = cameraRight.sqrMagnitude > 0.001f ? cameraRight.normalized : Vector3.right;
|
||||
|
||||
Vector3 dir = Vector3.zero;
|
||||
if (Input.GetKey(KeyCode.W)) dir += forward;
|
||||
if (Input.GetKey(KeyCode.S)) dir -= forward;
|
||||
if (Input.GetKey(KeyCode.A)) dir -= right;
|
||||
if (Input.GetKey(KeyCode.D)) dir += right;
|
||||
if (joystickActive) dir += right * joystick.x + forward * joystick.y;
|
||||
if (keyW) dir += forward;
|
||||
if (keyS) dir -= forward;
|
||||
if (keyA) dir -= right;
|
||||
if (keyD) dir += right;
|
||||
if (joystickInput.sqrMagnitude > 0.001f) dir += right * joystickInput.x + forward * joystickInput.y;
|
||||
return dir;
|
||||
}
|
||||
|
||||
@@ -917,7 +942,7 @@ namespace XGame
|
||||
rootObj = Instantiate(prefabObj);
|
||||
UIManager.AttachTo(UILayer.HUD, rootObj);
|
||||
|
||||
rootObj.name = "UI_LobbyJoystick";
|
||||
rootObj.name = "UI_VirtualJoystick";
|
||||
joystickRoot = rootObj.GetComponent<RectTransform>();
|
||||
if (joystickRoot == null)
|
||||
{
|
||||
@@ -926,6 +951,16 @@ namespace XGame
|
||||
joystickRoot.localScale = Vector3.one; // 兜底:设备包 prefab 根缩放异常时仍可见
|
||||
|
||||
// 视觉容器:新预设里是 "Joystick" 子节点(预设自带定位);找不到则用根并由 ApplyJoystickLayout 代码定位
|
||||
virtualJoystick = rootObj.GetComponent<VirtualJoystick>();
|
||||
if (virtualJoystick == null)
|
||||
{
|
||||
virtualJoystick = rootObj.AddComponent<VirtualJoystick>();
|
||||
}
|
||||
virtualJoystick.Changed -= OnVirtualJoystickChanged;
|
||||
virtualJoystick.Changed += OnVirtualJoystickChanged;
|
||||
virtualJoystick.Ended -= OnVirtualJoystickEnded;
|
||||
virtualJoystick.Ended += OnVirtualJoystickEnded;
|
||||
|
||||
Transform widget = joystickRoot.FindTransform("Joystick");
|
||||
joystickWidget = (widget as RectTransform) ?? joystickRoot;
|
||||
if (joystickWidget == joystickRoot)
|
||||
@@ -939,9 +974,7 @@ namespace XGame
|
||||
if (joystickKnob == null)
|
||||
{
|
||||
Debug.LogError("[LobbyWorldController] joystick prefab missing Knob node: " + JoystickPrefabPath);
|
||||
Destroy(rootObj);
|
||||
joystickRoot = null;
|
||||
joystickWidget = null;
|
||||
ReleaseJoystickUI(true);
|
||||
yield break;
|
||||
}
|
||||
|
||||
@@ -949,6 +982,59 @@ namespace XGame
|
||||
UpdateJoystickVisual();
|
||||
}
|
||||
|
||||
private void ReleaseJoystickUI(bool destroyObject)
|
||||
{
|
||||
if (virtualJoystick != null)
|
||||
{
|
||||
virtualJoystick.Changed -= OnVirtualJoystickChanged;
|
||||
virtualJoystick.Ended -= OnVirtualJoystickEnded;
|
||||
}
|
||||
|
||||
GameObject rootObj = joystickRoot != null ? joystickRoot.gameObject : null;
|
||||
virtualJoystick = null;
|
||||
joystickRoot = null;
|
||||
joystickWidget = null;
|
||||
joystickKnob = null;
|
||||
joystickMouseCaptured = false;
|
||||
joystickTouchFingerId = -1;
|
||||
joystickLoading = false;
|
||||
OnVirtualJoystickEnded();
|
||||
|
||||
if (destroyObject && rootObj != null)
|
||||
{
|
||||
DestroyUnityObject(rootObj);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DestroyUnityObject(UObject obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
Destroy(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyImmediate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnVirtualJoystickChanged(Vector2 value, bool active)
|
||||
{
|
||||
joystick = active ? value : Vector2.zero;
|
||||
joystickActive = active;
|
||||
}
|
||||
|
||||
private void OnVirtualJoystickEnded()
|
||||
{
|
||||
joystick = Vector2.zero;
|
||||
joystickActive = false;
|
||||
}
|
||||
|
||||
private Transform GetHudParent()
|
||||
{
|
||||
RectTransform hud = UIManager.GetLayer(UILayer.HUD);
|
||||
@@ -1229,9 +1315,7 @@ namespace XGame
|
||||
|
||||
private bool IsInJoystickArea(Vector2 screenPosition)
|
||||
{
|
||||
Vector2 center = GetJoystickScreenCenter();
|
||||
float radius = GetJoystickScreenRadius();
|
||||
return Vector2.Distance(screenPosition, center) <= radius * JoystickAcquireRadiusMultiplier;
|
||||
return virtualJoystick != null && virtualJoystick.IsScreenPositionInAcquireArea(screenPosition);
|
||||
}
|
||||
|
||||
private bool EnsureCharacterConfig()
|
||||
|
||||
Reference in New Issue
Block a user