Last active
December 10, 2024 05:21
-
-
Save kawashirov/3a66ebc78dc2671a0e68c340590de056 to your computer and use it in GitHub Desktop.
SyncVelocityLimiter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEngine; | |
using UnityEngine.SceneManagement; | |
using VRC.SDKBase; | |
using UdonSharp; | |
using VRC.SDK3.Components; | |
#if UNITY_EDITOR && !COMPILER_UDONSHARP | |
using UnityEditor; | |
using UdonSharpEditor; | |
#endif | |
[UdonBehaviourSyncMode(BehaviourSyncMode.None)] | |
public class SyncVelocityLimiter : UdonSharpBehaviour | |
{ | |
// The maximum linear velocity of the rigidbody measured in meters per second. | |
// https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Rigidbody-maxLinearVelocity.html | |
public float MaxLinearVelocity = 100; | |
// The maximum angular velocity of the rigidbody measured in radians per second. (Default 7) range { 0, infinity }. | |
// https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Rigidbody-maxAngularVelocity.html | |
public float MaxAngularVelocity = 7; | |
// Maximum velocity of a rigidbody when moving out of penetrating state. | |
// https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Rigidbody-maxDepenetrationVelocity.html | |
public float MaxDepenetrationVelocity = 10; | |
// https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Rigidbody-drag.html | |
public float MinDrag = 0.01f; | |
// https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Rigidbody-angularDrag.html | |
public float MinAngularDrag = 0.05f; | |
public Rigidbody[] Rigidbodies; | |
public void Start() | |
{ | |
_ApplyLimits(); | |
SendCustomEventDelayedFrames(nameof(_ApplyLimits), 1); | |
SendCustomEventDelayedSeconds(nameof(_ApplyLimits), 1); | |
} | |
public void _ApplyLimits() | |
{ | |
if (!Utilities.IsValid(Rigidbodies)) | |
return; | |
foreach (var rb in Rigidbodies) | |
{ | |
if (!Utilities.IsValid(rb)) | |
continue; | |
rb.maxLinearVelocity = MaxLinearVelocity; // Mathf.Min(rb.maxLinearVelocity, MaxLinearVelocity); | |
rb.maxAngularVelocity = MaxAngularVelocity; // Mathf.Min(rb.maxAngularVelocity, MaxAngularVelocity); | |
rb.maxDepenetrationVelocity = MaxAngularVelocity; // Mathf.Min(rb.maxDepenetrationVelocity, MaxAngularVelocity); | |
rb.drag = Mathf.Max(rb.drag, MinDrag); | |
rb.angularDrag = Mathf.Max(rb.angularDrag, MinAngularDrag); | |
} | |
} | |
#if UNITY_EDITOR && !COMPILER_UDONSHARP | |
[CustomEditor(typeof(SyncVelocityLimiter), true)] | |
public class Editor : UnityEditor.Editor | |
{ | |
public override void OnInspectorGUI() | |
{ | |
if (UdonSharpGUI.DrawDefaultUdonSharpBehaviourHeader(target)) | |
return; | |
DrawDefaultInspector(); | |
var refreshable = target as SyncVelocityLimiter; | |
if (GUILayout.Button("Refresh Rigidbodies")) | |
{ | |
refreshable.Refresh(); | |
} | |
} | |
} | |
private static bool IsRuntimeHideFlags(Object obj) => | |
(obj.hideFlags & (HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild)) == HideFlags.None; | |
public static bool IsRuntime(Object obj) | |
{ | |
// Имеет ли объект шанс попасть в рантайм после сборки? Если точно известно, что нет, то возвращается false | |
if (obj == null || !IsRuntimeHideFlags(obj)) | |
return false; | |
if (obj is GameObject gobj) | |
{ | |
if (gobj.CompareTag("EditorOnly")) | |
return false; | |
var parent = gobj.transform.parent; | |
if (parent != null && !IsRuntime(parent)) // Рекурсивно | |
return false; // Имеет не-рантайм родителя | |
} | |
else if (obj is Component c) | |
{ | |
// Примечание: hideFlags свои у компонента и у гейм объекта. | |
if (!IsRuntime(c.gameObject)) // Рекурсивно | |
return false; // Имеет не-рантайм родителя | |
} | |
return true; | |
} | |
public void Refresh() | |
{ | |
Rigidbodies = SceneManager.GetActiveScene() | |
.GetRootGameObjects() | |
.SelectMany(gobj => gobj.GetComponentsInChildren<Rigidbody>(true)) | |
.Where(IsRuntime) | |
.Where(rb => rb.GetComponent<VRCObjectSync>() != null) | |
.ToArray(); | |
EditorUtility.SetDirty(this); | |
} | |
#endif // UNITY_EDITOR && !COMPILER_UDONSHARP | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment