feat(Connect): 完成连线基本玩法,

This commit is contained in:
2025-10-19 19:38:52 +08:00
parent e14e8925de
commit f3d73ab65a
34 changed files with 2528 additions and 988 deletions

View File

@@ -0,0 +1,121 @@
using System.Linq;
using Core;
using UnityEngine;
using Script.Gameplay.Connect;
using Script.Gameplay.Input;
using System;
namespace Gameplay.Player
{
public class PlayerConnectController : MonoBehaviour
{
public bool IsEnableConnecting = true; // 是否启用连接功能
[SerializeField] private FirstPersonRaycaster raycaster; // 第一人称射线检测器
private IConnectable currentTarget; // 当前注视的可连接对象
private IConnectable previousGazedTarget; // 上一次注视的 IConnectable用于触发进入/离开)
private InputManager inputManager;
private IConnectable outTarget;
private IConnectable inputTarget;
public event Action<IConnectable> OnSetOutputTarget;
public event Action<IConnectable> OnSetInputTarget;
void Start()
{
inputManager = InputManager.Instance;
inputManager.Input.Player.SetOutput.performed += ctx => SetOutTarget(currentTarget);
inputManager.Input.Player.SetInput.performed += ctx => SetInputTarget(currentTarget);
inputManager.Input.Player.Connect.performed += ctx => CreateConnection();
if (raycaster == null)
raycaster = GetComponent<FirstPersonRaycaster>() ?? GetComponentInChildren<FirstPersonRaycaster>();
if (raycaster == null)
raycaster = FindObjectOfType<FirstPersonRaycaster>();
if (raycaster == null)
Debug.LogWarning("FirstPersonRaycaster not found! Please assign or add it to the player.");
ControllerLocator.Instance.Register(this);
}
void Update()
{
DetectConnectable();
}
void DetectConnectable()
{
if (raycaster == null) return;
GameObject lookAtObj = raycaster.CurrentLookAtObject;
IConnectable hitConnectable = lookAtObj != null ? lookAtObj.GetComponent<IConnectable>() : null;
// 注视对象变化时触发进入/离开(使用接口方法)
if (hitConnectable != previousGazedTarget)
{
if (previousGazedTarget != null)
{
previousGazedTarget.OnGazeExit();
}
if (hitConnectable != null)
{
hitConnectable.OnGazeEnter();
}
previousGazedTarget = hitConnectable;
}
currentTarget = hitConnectable;
}
public IConnectable GetCurrentTarget()
{
return currentTarget;
}
public void SetOutTarget(IConnectable target)
{
if (target == null) return;
if(!IsEnableConnecting) return;
if (!target.IsConnectedOutput)
{
outTarget = target;
OnSetOutputTarget?.Invoke(outTarget);
}
}
public void SetInputTarget(IConnectable target)
{
if (target == null) return;
if(!IsEnableConnecting) return;
if (!target.IsConnectedInput)
{
inputTarget = currentTarget;
OnSetInputTarget?.Invoke(inputTarget);
}
}
private void CreateConnection()
{
if(!IsEnableConnecting) return;
if (outTarget != null && inputTarget != null && outTarget != inputTarget)
{
ConnectionLine connectionLine = ConnectionLineManager.Instance.GenerateConnectionLine(outTarget, inputTarget);
// 重置信号目标
outTarget = null;
inputTarget = null;
}
else
{
Debug.Log("Cannot create connection: invalid targets.");
}
}
void OnDrawGizmos()
{
// 射线可视化交由 FirstPersonRaycaster 处理
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5981311fef324f939be05186f7936173
timeCreated: 1760838186

View File

@@ -0,0 +1,9 @@
using UnityEngine;
namespace Gameplay.Player
{
public class PlayerConnectionLineController : MonoBehaviour
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e152f6521db343f3aac46c7c448491bc
timeCreated: 1760841639

View File

@@ -16,29 +16,26 @@ namespace Gameplay.Player
public class PlayerWatchModeController : MonoBehaviour
{
[SerializeField] private Camera cam;
public event Action OnEnterInsideWatchMode;
public event Action OnExitInsideWatchMode;
public event Action<WatchMode> OnEnterWatchMode;
public event Action<WatchMode> OnExitWatchMode;
private InputManager inputManager;
private TimePauseManager timePauseManager;
private WatchMode currentMode = WatchMode.Normal;
private PlayerInteractorController playerInteractorController;
private PlayerConnectController _playerConnectController;
private WatchMode previousMode = WatchMode.Normal;
private WatchMode currentMode = WatchMode.Normal;
public WatchMode CurrentWatchMode
{
get => currentMode;
set
{
if (value != WatchMode.Inside)
{
OnExitInsideWatchMode?.Invoke();
}
if (value == WatchMode.Inside)
{
OnEnterInsideWatchMode?.Invoke();
}
previousMode = currentMode;
currentMode = value;
// 触发退出事件
OnExitWatchMode?.Invoke(previousMode);
OnEnterWatchMode?.Invoke(currentMode);
SwitchWatchMode(currentMode);
}
}
@@ -48,6 +45,7 @@ namespace Gameplay.Player
inputManager = InputManager.Instance;
timePauseManager = TimePauseManager.Instance;
playerInteractorController = GetComponent<PlayerInteractorController>();
_playerConnectController = GetComponent<PlayerConnectController>();
var input = inputManager.Input;
input.Player.SwitchWatchMode.performed += ctx =>
@@ -80,6 +78,11 @@ namespace Gameplay.Player
playerInteractorController.SetPlayerInteractionEnabled(true);
}
if (_playerConnectController != null)
{
_playerConnectController.IsEnableConnecting = false;
}
break;
case WatchMode.Inside:
SetSeeLines(false);
@@ -95,6 +98,11 @@ namespace Gameplay.Player
{
playerInteractorController.SetPlayerInteractionEnabled(false);
}
if (_playerConnectController != null)
{
_playerConnectController.IsEnableConnecting = false;
}
break;
case WatchMode.Outside:
@@ -111,6 +119,11 @@ namespace Gameplay.Player
{
playerInteractorController.SetPlayerInteractionEnabled(true);
}
if (_playerConnectController != null)
{
_playerConnectController.IsEnableConnecting = true;
}
break;
default: