/// SPΔWN[CAMPGAMES]™
/// SCRAPS (scripts-development) v2025
/// License: CCBYNC4.0
// DEPLOY
using SPAWN.Debug;
using UnityEngine;
namespace SpawnCampGames.Character
{
[RequireComponent(typeof(Rigidbody))]
public class SpringSuspensionWithPlatform : MonoBehaviour
{
[Header("Suspension Settings")]
public float rideHeight = 2f;
public float springStrength = 50f;
public float springDamping = 10f;
public LayerMask groundMask = 1 << 0;
[Header("Movement Settings")]
public float moveSpeed = 5f;
public float maxHorizontalSpeed = 10f;
public float turnSpeed = 100f;
public float horizontalDamp = 5f;
private Rigidbody rb;
// --- Platform support ---
private Vector3 platformVelocity; // velocity of current platform
private MovingPlatform currentPlatform; // reference to platform player is standing on
void Start()
{
rb = GetComponent<Rigidbody>();
rb.useGravity = false; // suspension handles gravity
}
void FixedUpdate()
{
ApplyRotation();
ApplyMovement();
ApplySuspension();
}
// --- Suspension (vertical movement) ---
private void ApplySuspension()
{
Vector3 vel = rb.velocity;
if (Physics.Raycast(transform.position, Vector3.down, out RaycastHit hit, rideHeight * 2f, groundMask))
{
float targetY = hit.point.y + rideHeight;
// Add platform vertical motion if standing on a platform
if (currentPlatform != null)
targetY += currentPlatform.GetVelocity().y * Time.fixedDeltaTime;
float displacement = transform.position.y - targetY;
float springAccel = (-springStrength * displacement) - (springDamping * vel.y);
vel.y += springAccel * Time.fixedDeltaTime;
}
else
{
vel.y += Physics.gravity.y * Time.fixedDeltaTime;
}
rb.velocity = vel;
}
// --- Movement (horizontal) ---
private void ApplyMovement()
{
float inputV = Input.GetAxis("Vertical");
Vector3 forward = transform.forward;
Vector3 vel = rb.velocity;
Vector3 desiredVel = forward * inputV * moveSpeed;
// Add horizontal platform velocity
Vector3 totalVel = desiredVel + new Vector3(platformVelocity.x, 0f, platformVelocity.z);
// Smooth horizontal movement
float lerp = horizontalDamp * Time.fixedDeltaTime;
vel.x = Mathf.Lerp(vel.x, totalVel.x, lerp);
vel.z = Mathf.Lerp(vel.z, totalVel.z, lerp);
// Clamp horizontal speed
Vector3 flatVel = new Vector3(vel.x, 0, vel.z);
if (flatVel.magnitude > maxHorizontalSpeed)
{
flatVel = flatVel.normalized * maxHorizontalSpeed;
vel.x = flatVel.x;
vel.z = flatVel.z;
}
rb.velocity = vel;
}
// --- Turning ---
private void ApplyRotation()
{
float turnInput = Input.GetAxis("Horizontal");
if (Mathf.Abs(turnInput) > 0.01f)
transform.Rotate(Vector3.up, turnInput * turnSpeed * Time.fixedDeltaTime);
}
// --- Detect platform collisions ---
void OnCollisionStay(Collision collision)
{
// Check if the player is standing on a platform
if (collision.gameObject.TryGetComponent(out currentPlatform))
{
platformVelocity = currentPlatform.GetVelocity(); // grab platform velocity
}
else
{
platformVelocity = Vector3.zero;
currentPlatform = null;
}
}
}
}