Added new Rocket-Processing
This commit is contained in:
@@ -66,11 +66,16 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
NetworkVariableWritePermission.Server);
|
||||
|
||||
private readonly HashSet<Collider> ignoredPlayerColliders = new();
|
||||
private readonly HashSet<Collider> desiredIgnoredColliders = new();
|
||||
private readonly List<Collider> collidersToRestore = new();
|
||||
private readonly RaycastHit[] groundHits = new RaycastHit[16];
|
||||
private float nextCollisionRefreshTime;
|
||||
private Vector3 localGroundContactPoint;
|
||||
private Vector3 smoothedGroundNormal = Vector3.up;
|
||||
private Vector3 dragVelocity;
|
||||
private float dragWorldHeight;
|
||||
private bool hasDragReferenceHeight;
|
||||
private bool initialUseGravity;
|
||||
private CollisionDetectionMode initialCollisionDetectionMode;
|
||||
|
||||
public float Weight => weight;
|
||||
public int ActiveDraggerCount
|
||||
@@ -125,6 +130,12 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
{
|
||||
ResolvePhysicsReferences();
|
||||
ApplyWeight();
|
||||
|
||||
if (physicsBody != null)
|
||||
{
|
||||
initialUseGravity = physicsBody.useGravity;
|
||||
initialCollisionDetectionMode = physicsBody.collisionDetectionMode;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
@@ -157,7 +168,7 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
return;
|
||||
|
||||
nextCollisionRefreshTime = Time.time + collisionRefreshInterval;
|
||||
IgnoreCollisionsWithPlayers();
|
||||
RefreshDraggerCollisions();
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
@@ -168,10 +179,7 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
RemoveInvalidDraggers();
|
||||
if (!HasEnoughPullStrength ||
|
||||
!TryGetCombinedDragTarget(out Vector3 target, out Vector3 forward))
|
||||
{
|
||||
dragVelocity = Vector3.zero;
|
||||
return;
|
||||
}
|
||||
|
||||
float totalStrength = ActiveDraggerCount * pullStrengthPerPlayer;
|
||||
float loadRatio = Mathf.Clamp01(weight / totalStrength);
|
||||
@@ -181,7 +189,7 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
switch (movementMode)
|
||||
{
|
||||
case DraggableMovementMode.KeepWorldHeight:
|
||||
target.y = physicsBody.position.y;
|
||||
target.y = dragWorldHeight;
|
||||
FollowDragTarget(target, forward, movementSpeed, Vector3.up);
|
||||
break;
|
||||
|
||||
@@ -360,6 +368,21 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryReleaseExternalControlToPlayer(ulong clientId)
|
||||
{
|
||||
if (!IsServer || !IsSpawned || !IsExternallyControlled ||
|
||||
TryGetDraggedObject(clientId, this, out _) ||
|
||||
!TryGetPlayerObject(clientId, out _))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
isExternallyControlled.Value = false;
|
||||
AddDragger(clientId);
|
||||
ApplyDraggingState();
|
||||
return IsDragger(clientId);
|
||||
}
|
||||
|
||||
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
|
||||
private void RequestReleaseRpc(RpcParams rpcParams = default)
|
||||
{
|
||||
@@ -379,34 +402,52 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
{
|
||||
if (physicsBody != null)
|
||||
{
|
||||
bool shouldBeKinematic = HasAnyDragger || IsExternallyControlled || !IsServer;
|
||||
bool shouldBeKinematic = IsExternallyControlled || !IsServer;
|
||||
|
||||
if (physicsBody.isKinematic && !shouldBeKinematic)
|
||||
if (shouldBeKinematic)
|
||||
{
|
||||
physicsBody.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
|
||||
physicsBody.isKinematic = true;
|
||||
physicsBody.useGravity = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
physicsBody.isKinematic = false;
|
||||
physicsBody.useGravity = initialUseGravity;
|
||||
physicsBody.collisionDetectionMode = ResolveDynamicCollisionDetectionMode();
|
||||
}
|
||||
|
||||
if (!physicsBody.isKinematic)
|
||||
if (IsExternallyControlled)
|
||||
{
|
||||
physicsBody.linearVelocity = Vector3.zero;
|
||||
physicsBody.angularVelocity = Vector3.zero;
|
||||
}
|
||||
|
||||
physicsBody.isKinematic = shouldBeKinematic;
|
||||
}
|
||||
|
||||
if (HasAnyDragger || IsExternallyControlled)
|
||||
if (HasAnyDragger)
|
||||
{
|
||||
dragVelocity = Vector3.zero;
|
||||
if (!hasDragReferenceHeight && physicsBody != null)
|
||||
{
|
||||
dragWorldHeight = physicsBody.position.y;
|
||||
hasDragReferenceHeight = true;
|
||||
}
|
||||
|
||||
CacheGroundContactPoint();
|
||||
smoothedGroundNormal = physicsBody != null ? physicsBody.transform.up : Vector3.up;
|
||||
IgnoreCollisionsWithPlayers();
|
||||
RefreshDraggerCollisions();
|
||||
}
|
||||
else
|
||||
{
|
||||
dragVelocity = Vector3.zero;
|
||||
hasDragReferenceHeight = false;
|
||||
RestorePlayerCollisions();
|
||||
}
|
||||
}
|
||||
|
||||
private CollisionDetectionMode ResolveDynamicCollisionDetectionMode() =>
|
||||
initialCollisionDetectionMode == CollisionDetectionMode.Discrete
|
||||
? CollisionDetectionMode.ContinuousDynamic
|
||||
: initialCollisionDetectionMode;
|
||||
|
||||
private void ResolvePhysicsReferences()
|
||||
{
|
||||
if (physicsBody == null)
|
||||
@@ -430,16 +471,11 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
float movementSpeed,
|
||||
Vector3 surfaceNormal)
|
||||
{
|
||||
Vector3 nextPosition = Vector3.SmoothDamp(
|
||||
physicsBody.position,
|
||||
DrivePhysicsBody(
|
||||
target,
|
||||
ref dragVelocity,
|
||||
positionSmoothTime,
|
||||
CalculateDragRotation(forward, surfaceNormal),
|
||||
movementSpeed,
|
||||
Time.fixedDeltaTime);
|
||||
|
||||
physicsBody.MovePosition(nextPosition);
|
||||
physicsBody.MoveRotation(CalculateDragRotation(forward, surfaceNormal));
|
||||
movementSpeed);
|
||||
}
|
||||
|
||||
private void MoveAlongGround(
|
||||
@@ -449,18 +485,10 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
{
|
||||
Vector3 currentPosition = physicsBody.position;
|
||||
Vector3 planarTarget = new(dragTarget.x, currentPosition.y, dragTarget.z);
|
||||
Vector3 planarVelocity = new(dragVelocity.x, 0f, dragVelocity.z);
|
||||
Vector3 nextPlanarPosition = Vector3.SmoothDamp(
|
||||
currentPosition,
|
||||
planarTarget,
|
||||
ref planarVelocity,
|
||||
positionSmoothTime,
|
||||
movementSpeed,
|
||||
Time.fixedDeltaTime);
|
||||
nextPlanarPosition.y = currentPosition.y;
|
||||
dragVelocity = new Vector3(planarVelocity.x, dragVelocity.y, planarVelocity.z);
|
||||
|
||||
Vector3 probePosition = nextPlanarPosition;
|
||||
Vector3 planarStep = Vector3.ClampMagnitude(
|
||||
planarTarget - currentPosition,
|
||||
movementSpeed * Time.fixedDeltaTime);
|
||||
Vector3 probePosition = currentPosition + planarStep;
|
||||
|
||||
if (!TryGetGroundSurface(probePosition, out Vector3 groundPoint, out Vector3 groundNormal))
|
||||
return;
|
||||
@@ -469,14 +497,55 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
Vector3 scaledContactPoint = Vector3.Scale(localGroundContactPoint, physicsBody.transform.lossyScale);
|
||||
float contactOffsetY = (targetRotation * scaledContactPoint).y;
|
||||
float targetHeight = groundPoint.y - contactOffsetY + groundClearance;
|
||||
float nextHeight = Mathf.MoveTowards(
|
||||
currentPosition.y,
|
||||
targetHeight,
|
||||
maximumGroundVerticalSpeed * Time.fixedDeltaTime);
|
||||
DrivePhysicsBody(
|
||||
new Vector3(dragTarget.x, targetHeight, dragTarget.z),
|
||||
targetRotation,
|
||||
movementSpeed,
|
||||
maximumGroundVerticalSpeed);
|
||||
}
|
||||
|
||||
physicsBody.MovePosition(new Vector3(nextPlanarPosition.x, nextHeight, nextPlanarPosition.z));
|
||||
private void DrivePhysicsBody(
|
||||
Vector3 targetPosition,
|
||||
Quaternion targetRotation,
|
||||
float maximumPlanarSpeed,
|
||||
float maximumVerticalSpeed)
|
||||
{
|
||||
Vector3 positionDelta = targetPosition - physicsBody.position;
|
||||
float responseTime = Mathf.Max(positionSmoothTime, 0.01f);
|
||||
Vector3 desiredVelocity = positionDelta / responseTime;
|
||||
Vector3 desiredPlanarVelocity = Vector3.ClampMagnitude(
|
||||
new Vector3(desiredVelocity.x, 0f, desiredVelocity.z),
|
||||
maximumPlanarSpeed);
|
||||
desiredVelocity = new Vector3(
|
||||
desiredPlanarVelocity.x,
|
||||
Mathf.Clamp(desiredVelocity.y, -maximumVerticalSpeed, maximumVerticalSpeed),
|
||||
desiredPlanarVelocity.z);
|
||||
|
||||
physicsBody.MoveRotation(targetRotation);
|
||||
float maximumAcceleration = Mathf.Max(
|
||||
maximumPlanarSpeed,
|
||||
maximumVerticalSpeed) / responseTime;
|
||||
Vector3 velocityChange = Vector3.ClampMagnitude(
|
||||
desiredVelocity - physicsBody.linearVelocity,
|
||||
maximumAcceleration * Time.fixedDeltaTime);
|
||||
physicsBody.AddForce(velocityChange, ForceMode.VelocityChange);
|
||||
|
||||
Quaternion rotationDelta = targetRotation * Quaternion.Inverse(physicsBody.rotation);
|
||||
rotationDelta.ToAngleAxis(out float angle, out Vector3 axis);
|
||||
if (axis.sqrMagnitude < 0.0001f || float.IsNaN(axis.x))
|
||||
return;
|
||||
|
||||
if (angle > 180f)
|
||||
angle -= 360f;
|
||||
|
||||
Vector3 desiredAngularVelocity = axis.normalized *
|
||||
(angle * Mathf.Deg2Rad * rotationFollowSpeed);
|
||||
desiredAngularVelocity = Vector3.ClampMagnitude(
|
||||
desiredAngularVelocity,
|
||||
rotationFollowSpeed);
|
||||
Vector3 angularVelocityChange = Vector3.ClampMagnitude(
|
||||
desiredAngularVelocity - physicsBody.angularVelocity,
|
||||
rotationFollowSpeed * 4f * Time.fixedDeltaTime);
|
||||
physicsBody.AddTorque(angularVelocityChange, ForceMode.VelocityChange);
|
||||
}
|
||||
|
||||
private bool TryGetGroundSurface(
|
||||
@@ -538,8 +607,7 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
Quaternion desiredRotation = Quaternion.LookRotation(
|
||||
surfaceForward.normalized,
|
||||
smoothedGroundNormal) * Quaternion.Euler(rotationOffset);
|
||||
float rotationBlend = 1f - Mathf.Exp(-rotationFollowSpeed * Time.fixedDeltaTime);
|
||||
return Quaternion.Slerp(physicsBody.rotation, desiredRotation, rotationBlend);
|
||||
return desiredRotation;
|
||||
}
|
||||
|
||||
private void CacheGroundContactPoint()
|
||||
@@ -596,19 +664,50 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
return false;
|
||||
}
|
||||
|
||||
private void IgnoreCollisionsWithPlayers()
|
||||
private void RefreshDraggerCollisions()
|
||||
{
|
||||
foreach (CharacterController playerCollider in FindObjectsByType<CharacterController>(
|
||||
FindObjectsInactive.Exclude,
|
||||
FindObjectsSortMode.None))
|
||||
{
|
||||
foreach (Collider objectCollider in objectColliders)
|
||||
{
|
||||
if (objectCollider != null && playerCollider != null)
|
||||
Physics.IgnoreCollision(objectCollider, playerCollider, true);
|
||||
}
|
||||
desiredIgnoredColliders.Clear();
|
||||
AddDraggerColliders(firstDraggerClientId.Value);
|
||||
AddDraggerColliders(secondDraggerClientId.Value);
|
||||
|
||||
ignoredPlayerColliders.Add(playerCollider);
|
||||
collidersToRestore.Clear();
|
||||
foreach (Collider ignoredCollider in ignoredPlayerColliders)
|
||||
{
|
||||
if (ignoredCollider == null || !desiredIgnoredColliders.Contains(ignoredCollider))
|
||||
collidersToRestore.Add(ignoredCollider);
|
||||
}
|
||||
|
||||
foreach (Collider colliderToRestore in collidersToRestore)
|
||||
{
|
||||
SetCollisionIgnored(colliderToRestore, false);
|
||||
ignoredPlayerColliders.Remove(colliderToRestore);
|
||||
}
|
||||
|
||||
foreach (Collider desiredCollider in desiredIgnoredColliders)
|
||||
{
|
||||
if (desiredCollider != null && ignoredPlayerColliders.Add(desiredCollider))
|
||||
SetCollisionIgnored(desiredCollider, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddDraggerColliders(ulong clientId)
|
||||
{
|
||||
if (clientId == NoDragger || !TryGetPlayerObject(clientId, out NetworkObject playerObject))
|
||||
return;
|
||||
|
||||
foreach (Collider playerCollider in playerObject.GetComponentsInChildren<Collider>(true))
|
||||
desiredIgnoredColliders.Add(playerCollider);
|
||||
}
|
||||
|
||||
private void SetCollisionIgnored(Collider playerCollider, bool ignored)
|
||||
{
|
||||
if (playerCollider == null)
|
||||
return;
|
||||
|
||||
foreach (Collider objectCollider in objectColliders)
|
||||
{
|
||||
if (objectCollider != null)
|
||||
Physics.IgnoreCollision(objectCollider, playerCollider, ignored);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,13 +718,11 @@ public sealed class NetworkDraggableInteractable : NetworkInteractable, IWorksta
|
||||
if (playerCollider == null)
|
||||
continue;
|
||||
|
||||
foreach (Collider objectCollider in objectColliders)
|
||||
{
|
||||
if (objectCollider != null)
|
||||
Physics.IgnoreCollision(objectCollider, playerCollider, false);
|
||||
}
|
||||
SetCollisionIgnored(playerCollider, false);
|
||||
}
|
||||
|
||||
ignoredPlayerColliders.Clear();
|
||||
desiredIgnoredColliders.Clear();
|
||||
collidersToRestore.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user