Added RocketAssemblyStation and ReadyRocket

This commit is contained in:
2026-08-18 16:12:00 +03:00
parent 7a0ee6b519
commit 63d2836dc9
85 changed files with 15087 additions and 3562 deletions
@@ -16,13 +16,12 @@ public abstract class NetworkHeldInteractable : NetworkInteractable, IWorkstatio
[Header("Holding Follow")]
[SerializeField, Min(0.1f)] private float maximumFollowSpeed = 12f;
[SerializeField, Min(0.1f)] private float followResponsiveness = 10f;
[SerializeField, Min(0.1f)] private float maximumFollowAcceleration = 80f;
[SerializeField, Min(0.5f)] private float maximumHoldDistance = 4.5f;
[SerializeField, Min(0.1f)] private float rotationFollowSpeed = 14f;
[Header("Local Presentation")]
[Tooltip("Removes the server round-trip delay for the player currently carrying the item.")]
[SerializeField] private bool correctLocalHolderPresentation = true;
[SerializeField, Min(0.1f)] private float maximumLocalCorrectionDistance = 2f;
[SerializeField, Min(0.1f)] private float rotationResponsiveness = 10f;
[SerializeField, Min(0.1f)] private float maximumAngularAcceleration = 80f;
[Header("Throw")]
[SerializeField, Min(0f)] private float throwForce = 6f;
@@ -41,10 +40,10 @@ public abstract class NetworkHeldInteractable : NetworkInteractable, IWorkstatio
private readonly HashSet<Collider> ignoredPlayerColliders = new();
private readonly HashSet<Collider> desiredIgnoredColliders = new();
private readonly List<Collider> collidersToRestore = new();
private readonly RaycastHit[] localCorrectionHits = new RaycastHit[24];
private float nextCollisionRefreshTime;
private bool initialUseGravity;
private CollisionDetectionMode initialCollisionDetectionMode;
private NetworkTransform networkTransform;
protected abstract Vector3 HoldingOffset { get; }
protected abstract string DropPrompt { get; }
@@ -80,6 +79,8 @@ public abstract class NetworkHeldInteractable : NetworkInteractable, IWorkstatio
initialUseGravity = physicsBody.useGravity;
initialCollisionDetectionMode = physicsBody.collisionDetectionMode;
}
networkTransform = GetComponent<NetworkTransform>();
}
public override void OnNetworkSpawn()
@@ -87,6 +88,12 @@ public abstract class NetworkHeldInteractable : NetworkInteractable, IWorkstatio
SpawnedHeldObjects.Add(this);
holderClientId.OnValueChanged += HandleHolderChanged;
isExternallyControlled.OnValueChanged += HandleExternalControlChanged;
if (networkTransform != null)
{
networkTransform.Interpolate = true;
networkTransform.UseUnreliableDeltas = true;
}
ApplyHoldingState();
}
@@ -129,28 +136,6 @@ public abstract class NetworkHeldInteractable : NetworkInteractable, IWorkstatio
}
private void LateUpdate()
{
if (!correctLocalHolderPresentation || IsServer || !IsSpawned ||
!IsHeldByLocalPlayer || IsExternallyControlled || physicsBody == null ||
!TryGetPlayerObject(holderClientId.Value, out NetworkObject holder))
{
return;
}
Transform anchor = ResolveHoldingAnchor(holder);
Vector3 targetPosition = anchor.TransformPoint(HoldingOffset);
Vector3 targetDelta = targetPosition - physicsBody.position;
if (targetDelta.sqrMagnitude >
maximumLocalCorrectionDistance * maximumLocalCorrectionDistance ||
HasBlockingColliderForLocalCorrection(targetDelta))
{
return;
}
transform.SetPositionAndRotation(targetPosition, anchor.rotation);
}
public void RequestThrow()
{
if (IsSpawned && IsHeldByLocalPlayer)
@@ -292,10 +277,14 @@ public abstract class NetworkHeldInteractable : NetworkInteractable, IWorkstatio
return false;
}
Vector3 targetVelocity = targetDelta / Mathf.Max(Time.fixedDeltaTime, 0.001f);
physicsBody.linearVelocity = Vector3.ClampMagnitude(
targetVelocity,
float fixedDeltaTime = Mathf.Max(Time.fixedDeltaTime, 0.001f);
Vector3 targetVelocity = Vector3.ClampMagnitude(
targetDelta * followResponsiveness,
maximumFollowSpeed);
physicsBody.linearVelocity = Vector3.MoveTowards(
physicsBody.linearVelocity,
targetVelocity,
maximumFollowAcceleration * fixedDeltaTime);
DriveRotation(anchor.rotation);
return true;
@@ -306,57 +295,25 @@ public abstract class NetworkHeldInteractable : NetworkInteractable, IWorkstatio
Quaternion rotationDelta = targetRotation * Quaternion.Inverse(physicsBody.rotation);
rotationDelta.ToAngleAxis(out float angle, out Vector3 axis);
if (axis.sqrMagnitude < 0.0001f || float.IsNaN(axis.x))
{
physicsBody.angularVelocity = Vector3.MoveTowards(
physicsBody.angularVelocity,
Vector3.zero,
maximumAngularAcceleration * Mathf.Max(Time.fixedDeltaTime, 0.001f));
return;
}
if (angle > 180f)
angle -= 360f;
Vector3 targetAngularVelocity = axis.normalized *
(angle * Mathf.Deg2Rad / Mathf.Max(Time.fixedDeltaTime, 0.001f));
physicsBody.angularVelocity = Vector3.ClampMagnitude(
targetAngularVelocity,
float fixedDeltaTime = Mathf.Max(Time.fixedDeltaTime, 0.001f);
Vector3 targetAngularVelocity = Vector3.ClampMagnitude(
axis.normalized * angle * Mathf.Deg2Rad * rotationResponsiveness,
rotationFollowSpeed);
}
private bool HasBlockingColliderForLocalCorrection(Vector3 targetDelta)
{
float distance = targetDelta.magnitude;
if (distance <= 0.0001f)
return false;
int hitCount = Physics.RaycastNonAlloc(
physicsBody.position,
targetDelta / distance,
localCorrectionHits,
distance,
~0,
QueryTriggerInteraction.Ignore);
for (int hitIndex = 0; hitIndex < hitCount; hitIndex++)
{
Collider hitCollider = localCorrectionHits[hitIndex].collider;
if (hitCollider == null ||
ignoredPlayerColliders.Contains(hitCollider) ||
IsObjectCollider(hitCollider))
{
continue;
}
return true;
}
return false;
}
private bool IsObjectCollider(Collider candidate)
{
foreach (Collider objectCollider in objectColliders)
{
if (objectCollider == candidate)
return true;
}
return false;
physicsBody.angularVelocity = Vector3.MoveTowards(
physicsBody.angularVelocity,
targetAngularVelocity,
maximumAngularAcceleration * fixedDeltaTime);
}
private void HandleHolderChanged(ulong _, ulong __) => ApplyHoldingState();
@@ -369,6 +326,9 @@ public abstract class NetworkHeldInteractable : NetworkInteractable, IWorkstatio
{
bool isPhysicallyHeld = IsHeld && !IsExternallyControlled;
bool shouldBeKinematic = IsExternallyControlled || !IsServer;
physicsBody.interpolation = IsServer
? RigidbodyInterpolation.Interpolate
: RigidbodyInterpolation.None;
if (shouldBeKinematic)
{