This commit is contained in:
2026-08-13 08:39:14 +03:00
parent 6b1a6b83a4
commit 22df749a0e
10 changed files with 568 additions and 4 deletions
@@ -29,6 +29,11 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server);
private readonly NetworkVariable<bool> isExternallyControlled = new(
false,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server);
private readonly HashSet<Collider> ignoredPlayerColliders = new();
private float nextCollisionRefreshTime;
private Vector3 followVelocity;
@@ -39,17 +44,21 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
protected abstract string DropPrompt { get; }
public bool IsHeld => holderClientId.Value != NoHolder;
public bool IsExternallyControlled => isExternallyControlled.Value;
public bool IsHeldByLocalPlayer =>
NetworkManager != null && holderClientId.Value == NetworkManager.LocalClientId;
public string HeldObjectName => InteractionLabel;
public override string InteractionPrompt => !IsHeld
public override string InteractionPrompt => IsExternallyControlled
? "In machine"
: !IsHeld
? InteractionLabel
: IsHeldByLocalPlayer
? DropPrompt
: "In use";
public override bool IsInteractionAvailable => base.IsInteractionAvailable &&
!IsExternallyControlled &&
(!IsHeld || IsHeldByLocalPlayer);
private void Awake()
@@ -65,12 +74,14 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
{
SpawnedHeldObjects.Add(this);
holderClientId.OnValueChanged += HandleHolderChanged;
ApplyHoldingState(IsHeld);
isExternallyControlled.OnValueChanged += HandleExternalControlChanged;
ApplyHoldingState(IsHeld || IsExternallyControlled);
}
public override void OnNetworkDespawn()
{
holderClientId.OnValueChanged -= HandleHolderChanged;
isExternallyControlled.OnValueChanged -= HandleExternalControlChanged;
SpawnedHeldObjects.Remove(this);
ApplyHoldingState(false);
}
@@ -105,6 +116,30 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
RequestThrowServerRpc();
}
public bool TryAcquireExternalControl()
{
if (!IsServer || !IsSpawned || IsExternallyControlled)
return false;
isExternallyControlled.Value = true;
if (IsHeld)
holderClientId.Value = NoHolder;
ApplyHoldingState(true);
return true;
}
public bool TryReleaseExternalControl()
{
if (!IsServer || !IsSpawned || !IsExternallyControlled)
return false;
isExternallyControlled.Value = false;
ApplyHoldingState(IsHeld);
return true;
}
public static bool TryGetHeldObject(
ulong clientId,
out NetworkHeldInteractable heldObject)
@@ -124,6 +159,9 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
protected override bool CanInteractOnServer(ulong senderClientId)
{
if (IsExternallyControlled)
return false;
if (holderClientId.Value == senderClientId)
return true;
@@ -166,6 +204,9 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
private void StartHolding(ulong clientId)
{
if (IsExternallyControlled)
return;
holderClientId.Value = clientId;
ApplyHoldingState(true);
}
@@ -173,7 +214,7 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
private void StopHolding()
{
holderClientId.Value = NoHolder;
ApplyHoldingState(false);
ApplyHoldingState(IsExternallyControlled);
}
private Transform ResolveHoldingAnchor(NetworkObject holder)
@@ -226,7 +267,10 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
}
private void HandleHolderChanged(ulong _, ulong currentHolder) =>
ApplyHoldingState(currentHolder != NoHolder);
ApplyHoldingState(currentHolder != NoHolder || IsExternallyControlled);
private void HandleExternalControlChanged(bool _, bool isControlled) =>
ApplyHoldingState(IsHeld || isControlled);
private void ApplyHoldingState(bool isHeld)
{