| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- using UdonSharp;
- using UnityEngine;
- using VRC.SDK3.Components;
- using VRC.SDKBase;
- [UdonBehaviourSyncMode(BehaviourSyncMode.NoVariableSync)]
- [DisallowMultipleComponent]
- [AddComponentMenu("Artyom Scripting System/Jump Pad Controller")]
- public class JumpPad : UdonSharpBehaviour
- {
- public bool debug;
- public Animator launchAnim;
- public string animName = "isLaunch";
- public Transform jumpTarget;
- public Transform self;
- public float arcTime = 1.2f;
- public float walkLimit = 0.2f;
- public float runLimit = 0.4f;
- public float strafeLimit = 0.2f;
- private Vector3 appliedVelocity;
- private float defaultWalk;
- private float defaultStrafe;
- private float defaultRun;
- private VRCPlayerApi player;
- private bool ready;
- private int localLaunches; // Launches of the local player still in the air
- private int animLaunches; // Launches of anyone still holding the launch animation on
- void Start()
- {
- // The inspector's Animator wins; only fall back to one on this object
- if (launchAnim == null) launchAnim = GetComponent<Animator>();
- if (self == null) self = transform;
- if (jumpTarget == null)
- {
- Debug.LogError("[AUMSS] Jump Pad Controller: Jump Target isn't assigned, so the pad won't launch anything.");
- return;
- }
- ready = true;
- if (debug) Debug.Log("Jump Pad Controller: Velocity Calculated to:" + CalculateInitialVelocity(self.position, jumpTarget.position, Physics.gravity.y, arcTime).ToString());
- }
- public static Vector3 CalculateInitialVelocity(Vector3 origin, Vector3 target, float gravity, float time)
- {
- // Compute the differences in position
- Vector3 displacement = target - origin;
- // Calculate the initial velocity components
- Vector3 initialVelocity = new Vector3(
- displacement.x / time, // Horizontal X velocity
- (displacement.y - 0.5f * gravity * time * time) / time, // Vertical Y velocity
- displacement.z / time // Horizontal Z velocity
- );
- return initialVelocity;
- }
- private float LaunchDuration()
- {
- return Mathf.Max(arcTime - 0.2f, 0f);
- }
- public override void OnPlayerTriggerEnter(VRCPlayerApi collidedPlayer)
- {
- if (!ready) return;
- StartLaunchAnim();
- SendCustomEventDelayedSeconds(nameof(EndLaunchAnim), LaunchDuration());
- // Remote players get launched by their own client, and speed/velocity calls on them throw and halt this script
- if (!collidedPlayer.isLocal) return;
- player = collidedPlayer;
- // Only save the speeds when not already mid-launch: mid-launch they're the limits, and would be kept forever
- if (localLaunches == 0)
- {
- defaultRun = player.GetRunSpeed();
- defaultStrafe = player.GetStrafeSpeed();
- defaultWalk = player.GetWalkSpeed();
- }
- localLaunches++;
- // Players fall with the world's gravity scaled by their own gravity strength
- appliedVelocity = CalculateInitialVelocity(self.position, jumpTarget.position, Physics.gravity.y * player.GetGravityStrength(), arcTime);
- LimitMobility();
- player.SetVelocity(appliedVelocity);
- if (debug) Debug.Log("Jump Pad Controller: Player Velocity Set to:" + appliedVelocity.ToString());
- SendCustomEventDelayedSeconds(nameof(Mobilize), LaunchDuration());
- }
- private void OnTriggerEnter(Collider other)
- {
- if (!ready || other == null) return;
- VRC_Pickup pickup = other.GetComponent<VRC_Pickup>();
- Rigidbody body = other.GetComponent<Rigidbody>();
- if (pickup == null || body == null) return;
- // A synced pickup is launched by its owner; anyone else setting its velocity just fights the sync
- if (other.GetComponent<VRCObjectSync>() != null && !Networking.IsOwner(other.gameObject)) return;
- appliedVelocity = CalculateInitialVelocity(self.position, jumpTarget.position, Physics.gravity.y, arcTime);
- pickup.Drop();
- body.velocity = appliedVelocity;
- }
- public void LimitMobility()
- {
- if (!Utilities.IsValid(player)) return;
- player.SetWalkSpeed(walkLimit);
- player.SetRunSpeed(runLimit);
- player.SetStrafeSpeed(strafeLimit);
- if (debug) Debug.Log("Jump Pad Controller: Limited Player Mobility for " + arcTime.ToString() + " seconds");
- }
- public void Mobilize()
- {
- if (localLaunches > 0) localLaunches--;
- if (localLaunches > 0 || !Utilities.IsValid(player)) return; // Still in the air from a later launch
- player.SetWalkSpeed(defaultWalk);
- player.SetRunSpeed(defaultRun);
- player.SetStrafeSpeed(defaultStrafe);
- if (debug) Debug.Log("Jump Pad Controller: De-Limited Player Mobility after" + arcTime.ToString() + " seconds");
- }
- private void StartLaunchAnim()
- {
- animLaunches++;
- if (launchAnim == null || string.IsNullOrEmpty(animName)) return;
- launchAnim.SetBool(animName, true);
- if (debug) Debug.Log("Jump Pad Controller: Animator State attempted to be set to True");
- }
- public void EndLaunchAnim()
- {
- if (animLaunches > 0) animLaunches--;
- if (animLaunches > 0) return; // Someone else launched since; their launch ends it
- if (launchAnim == null || string.IsNullOrEmpty(animName)) return;
- launchAnim.SetBool(animName, false);
- if (debug) Debug.Log("Jump Pad Controller: Animator State attempted to be set to False");
- }
- }
|