Added new Rocket-Processing

This commit is contained in:
2026-08-14 16:54:09 +03:00
parent 3c490bdae8
commit b5eadea728
36 changed files with 17653 additions and 1984 deletions
@@ -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();
}
}