slimecing

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit b1d709bf8566ab0d7d4ae226411f0a0c331f94e2
parent d334726ef90e57b83d69b137c0d38b0c98caed67
Author: PlutoTank <qwolkensperg@gmail.com>
Date:   Thu, 23 Apr 2020 20:37:34 -0400

can land on moving platforms

Diffstat:
MAssets/Prefabs/Slimes/Slime.prefab | 2++
MAssets/Scripts/Slimecing/Abilities/AbilityEffects/SimpleJumpAbilityEffect.cs | 2+-
MAssets/Scripts/Slimecing/Characters/CharacterMovementController.cs | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
MAssets/Scripts/Slimecing/Characters/SlimeMovementController.cs | 5+++--
MAssets/Scripts/Slimecing/Environment/MoverSimulationManager.cs | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
MAssets/Scripts/Slimecing/Environment/Moving/RigidbodyMover.cs | 2+-
MAssets/_Scenes/Testing/SLope.unity | 4++--
7 files changed, 207 insertions(+), 21 deletions(-)

diff --git a/Assets/Prefabs/Slimes/Slime.prefab b/Assets/Prefabs/Slimes/Slime.prefab @@ -1037,6 +1037,7 @@ MonoBehaviour: hitLayerMask: serializedVersion: 2 m_Bits: 8705 + preserveInteractableRigidbodyVelocity: 1 speedOfMovementSmoothing: 20 airControl: 0.8 groundControl: 1 @@ -1146,6 +1147,7 @@ MonoBehaviour: xAxis: 2.5 yAxis: 2.5 sticky: 0 + instantiateOnSpawn: 1 --- !u!114 &1450437300 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Slimecing/Abilities/AbilityEffects/SimpleJumpAbilityEffect.cs b/Assets/Scripts/Slimecing/Abilities/AbilityEffects/SimpleJumpAbilityEffect.cs @@ -35,7 +35,7 @@ namespace Slimecing.Abilities.AbilityEffects _jumpDir = -_controller.GravityDirection; _lastJumpMass = _controller.SimulatedFallingMass; _controller.SimulatedFallingMass = _simulatedJumpUpMass; - _controller.AddForceTo(-_jumpDir, _controller.PlayerRigidbody.velocity.y); + _controller.AddForceTo(-_jumpDir, _controller.playerRigidbody.velocity.y); BeginJump(); } diff --git a/Assets/Scripts/Slimecing/Characters/CharacterMovementController.cs b/Assets/Scripts/Slimecing/Characters/CharacterMovementController.cs @@ -1,6 +1,6 @@ -using System; +using Slimecing.Environment; +using Slimecing.Environment.Moving; using Slimecing.SimpleComponents.Movement; -using Slimecing.TestScripts; using UnityEngine; namespace Slimecing.Characters @@ -12,7 +12,7 @@ namespace Slimecing.Characters { [Header("Components")] [SerializeField] protected Rigidbody rb; - public Rigidbody PlayerRigidbody => rb; + public Rigidbody playerRigidbody => rb; [SerializeField] protected Rotatable rotatable; [SerializeField] private Collider playerCollider; @@ -52,7 +52,8 @@ namespace Slimecing.Characters [SerializeField] private LayerMask hitLayerMask; [Header("Other Settings")] - [SerializeField] const int MaxHitsBuffer = 3; + [SerializeField] private bool preserveInteractableRigidbodyVelocity; + const int MaxHitsBuffer = 3; protected Vector2 move; protected Vector3 calculatedGravity; @@ -61,7 +62,21 @@ namespace Slimecing.Characters public bool IsGrounded() => _isGrounded; private bool _canBeGrounded; + private Vector3 _bodyVelocity; + private Vector3 _attachedRigidbodyVelocity; + private Rigidbody _lastAttachedRigidbody; + private bool _isMovingFromAttachedRigidbody; + + private Vector3 _calculatedTargetVelocity; + public Vector3 calculatedTargetVelocity + { + get => _calculatedTargetVelocity; + set => _calculatedTargetVelocity = value; + } + + public Rigidbody attachedRigidbody { get; private set; } + public Vector3 internalTransformPosition { get; set; } private RaycastHit _internalGroundHit; private RaycastHit _internalSlopeHit; @@ -72,8 +87,20 @@ namespace Slimecing.Characters protected void Awake() { + internalTransformPosition = Vector3.zero; calculatedGravity = gravityDirection * gravityForce; } + + private void OnEnable() + { + MoverSimulationManager.CheckAlive(); + MoverSimulationManager.RegisterCharMover(this); + } + + private void OnDisable() + { + MoverSimulationManager.UnregisterCharMover(this); + } public abstract void GetMoveInputH(float h); public abstract void GetMoveInputV(float v); @@ -100,15 +127,15 @@ namespace Slimecing.Characters Debug.DrawLine(transform.position, transform.position + Forward() * 2, Color.yellow); } - protected virtual void FixedUpdate() + public virtual void TickCharacter(float deltaTime) { GroundCheck(groundProbingDistance, groundingSphereCastRadius); - - float deltaTime = Time.deltaTime; - + + InteractableRigidbodyCheck(deltaTime); + Rotate(deltaTime); Move(deltaTime); - + if (!_isGrounded && useGravity) rb.AddForce(simulatedFallingMass * calculatedGravity); if (rb.velocity.magnitude < minVelocityMagnitude) @@ -119,6 +146,91 @@ namespace Slimecing.Characters _isGrounded = false; } + private void InteractableRigidbodyCheck(float deltaTime) + { + if (!IsGrounded()) return; + _lastAttachedRigidbody = attachedRigidbody; + if (_lastGoodNormalHit.collider.attachedRigidbody) + { + Rigidbody validRigidbody = GetInteractableRigidbody(_lastGoodNormalHit.collider); + if (validRigidbody) + { + attachedRigidbody = validRigidbody; + } + } + else + { + attachedRigidbody = null; + } + + Vector3 tmpVelocityFromInteractableRigidbody = Vector3.zero; + if (attachedRigidbody) + { + tmpVelocityFromInteractableRigidbody = + GetVelocityFromRigidbodyMovement(attachedRigidbody, transform.position, deltaTime); + } + + if (preserveInteractableRigidbodyVelocity && _lastAttachedRigidbody != null && + attachedRigidbody != _lastAttachedRigidbody) + { + _bodyVelocity += _attachedRigidbodyVelocity; + _bodyVelocity -= tmpVelocityFromInteractableRigidbody; + } + + _attachedRigidbodyVelocity = Vector3.zero; + if (attachedRigidbody) + { + _attachedRigidbodyVelocity = tmpVelocityFromInteractableRigidbody; + Vector3 newForward = Vector3 + .ProjectOnPlane( + Quaternion.Euler(attachedRigidbody.angularVelocity * (Mathf.Rad2Deg * deltaTime)) * Forward(), + PlayerGroundedUpVector()).normalized; + rb.rotation = Quaternion.LookRotation(newForward, PlayerGroundedUpVector()); + } + + rb.position += _attachedRigidbodyVelocity * deltaTime; + internalTransformPosition = _attachedRigidbodyVelocity * deltaTime; + } + + private Vector3 PlayerGroundedUpVector() + { + return transform.rotation * Vector3.up; + } + + private Vector3 GetVelocityFromRigidbodyMovement(Rigidbody interactiveRb, Vector3 transformPosition, float deltaTime) + { + if (!(deltaTime > 0f)) return Vector3.zero; + Vector3 moverVelocity = interactiveRb.velocity; + + if (interactiveRb.angularVelocity == Vector3.zero) return moverVelocity; + + Vector3 centerOfRot = interactiveRb.position + interactiveRb.centerOfMass; + Vector3 centerOfRotOffset = transformPosition - centerOfRot; + Quaternion rotationFromMoverRigidbody = Quaternion.Euler(interactiveRb.angularVelocity * (Mathf.Rad2Deg * deltaTime)); + Vector3 finalPointPos = centerOfRot + (rotationFromMoverRigidbody * centerOfRotOffset); + moverVelocity += (finalPointPos - transformPosition) / deltaTime; + + return moverVelocity; + + } + + private Rigidbody GetInteractableRigidbody(Collider col) + { + if (!col.attachedRigidbody) return null; + + if (col.attachedRigidbody.gameObject.GetComponent<RigidbodyMover>()) + { + return col.attachedRigidbody; + } + + if (!col.attachedRigidbody.isKinematic) + { + return col.attachedRigidbody; + } + + return null; + } + protected abstract void Move(float deltaTime); protected abstract void Rotate(float deltaTime); diff --git a/Assets/Scripts/Slimecing/Characters/SlimeMovementController.cs b/Assets/Scripts/Slimecing/Characters/SlimeMovementController.cs @@ -27,8 +27,9 @@ namespace Slimecing.Characters velocityChange = Vector3.ClampMagnitude(velocityChange, grounded ? groundControl : airControl); velocityChange = transform.TransformDirection(velocityChange); - rb.AddForce(velocityChange, ForceMode.VelocityChange); - + rb.AddForce(velocityChange, ForceMode.VelocityChange); + internalTransformPosition += velocityChange * deltaTime; + } protected override void Rotate(float deltaTime) diff --git a/Assets/Scripts/Slimecing/Environment/MoverSimulationManager.cs b/Assets/Scripts/Slimecing/Environment/MoverSimulationManager.cs @@ -1,16 +1,48 @@ using System; using Boo.Lang; +using Slimecing.Characters; using Slimecing.Environment.Moving; using UnityEngine; namespace Slimecing.Environment { + public enum SimulationInterpolationMethod + { + None, + Unity + } + [DefaultExecutionOrder(-100)] public class MoverSimulationManager : MonoBehaviour { private static MoverSimulationManager _instance; + + private static readonly List<CharacterMovementController> s_CharacterMovers = new List<CharacterMovementController>(); + private static readonly List<RigidbodyMover> s_RigidbodyMovers = new List<RigidbodyMover>(); + + private static SimulationInterpolationMethod _internalInterpolationMethod = SimulationInterpolationMethod.None; + + public static SimulationInterpolationMethod interpolationMethod + { + get => _internalInterpolationMethod; + set + { + _internalInterpolationMethod = value; + + MoveBodiesInstantly(); + + RigidbodyInterpolation interpolation = (_internalInterpolationMethod == SimulationInterpolationMethod.Unity) ? RigidbodyInterpolation.Interpolate : RigidbodyInterpolation.None; + foreach (var charMover in s_CharacterMovers) + { + charMover.playerRigidbody.interpolation = interpolation; + } - private static List<RigidbodyMover> _rigidbodyMovers = new List<RigidbodyMover>(); + foreach (var mover in s_RigidbodyMovers) + { + mover.moverRigidbody.interpolation = interpolation; + } + } + } public static void CheckAlive() { @@ -31,15 +63,31 @@ namespace Slimecing.Environment { Destroy(gameObject); } + + public static void RegisterCharMover(CharacterMovementController charMover) + { + s_CharacterMovers.Add(charMover); + + RigidbodyInterpolation interpolate = _internalInterpolationMethod == SimulationInterpolationMethod.Unity ? RigidbodyInterpolation.Interpolate : RigidbodyInterpolation.None; + charMover.playerRigidbody.interpolation = interpolate; + } + + public static void UnregisterCharMover(CharacterMovementController charMover) + { + s_CharacterMovers.Remove(charMover); + } public static void RegisterMover(RigidbodyMover mover) { - _rigidbodyMovers.Add(mover); + s_RigidbodyMovers.Add(mover); + + RigidbodyInterpolation interpolate = _internalInterpolationMethod == SimulationInterpolationMethod.Unity ? RigidbodyInterpolation.Interpolate : RigidbodyInterpolation.None; + mover.moverRigidbody.interpolation = interpolate; } public static void UnregisterMover(RigidbodyMover mover) { - _rigidbodyMovers.Remove(mover); + s_RigidbodyMovers.Remove(mover); } private void FixedUpdate() @@ -52,7 +100,7 @@ namespace Slimecing.Environment private void PreSimulationTick() { - foreach (var mover in _rigidbodyMovers) + foreach (var mover in s_RigidbodyMovers) { var moverTransform = mover.transform; mover.beginningTickPosition = moverTransform.position; @@ -62,7 +110,7 @@ namespace Slimecing.Environment private void SimulateTick(float deltaTime) { - foreach (var mover in _rigidbodyMovers) + foreach (var mover in s_RigidbodyMovers) { mover.UpdateMoverVelocity(deltaTime); @@ -70,13 +118,18 @@ namespace Slimecing.Environment mover.moverRigidbody.position = mover.currentPosition; mover.moverRigidbody.rotation = mover.currentRotation; } + + foreach (var charMover in s_CharacterMovers) + { + charMover.TickCharacter(deltaTime); + } } private void PostSimulationTick() { Physics.SyncTransforms(); - foreach (var mover in _rigidbodyMovers) + foreach (var mover in s_RigidbodyMovers) { mover.moverRigidbody.position = mover.beginningTickPosition; mover.moverRigidbody.rotation = mover.beginningTickRotation; @@ -84,5 +137,23 @@ namespace Slimecing.Environment mover.moverRigidbody.MoveRotation(mover.currentRotation); } } + + private static void MoveBodiesInstantly() + { + foreach (var charMover in s_CharacterMovers) + { + charMover.transform.SetPositionAndRotation(charMover.internalTransformPosition, + charMover.transform.rotation); + charMover.playerRigidbody.position = charMover.internalTransformPosition; + charMover.playerRigidbody.rotation = charMover.transform.rotation; + } + + foreach (var mover in s_RigidbodyMovers) + { + mover.transform.SetPositionAndRotation(mover.currentPosition, mover.currentRotation); + mover.moverRigidbody.position = mover.currentPosition; + mover.moverRigidbody.rotation = mover.currentRotation; + } + } } } \ No newline at end of file diff --git a/Assets/Scripts/Slimecing/Environment/Moving/RigidbodyMover.cs b/Assets/Scripts/Slimecing/Environment/Moving/RigidbodyMover.cs @@ -59,7 +59,7 @@ namespace Slimecing.Environment.Moving objectRigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete; objectRigidbody.isKinematic = true; objectRigidbody.constraints = RigidbodyConstraints.None; - objectRigidbody.interpolation = RigidbodyInterpolation.Interpolate; + objectRigidbody.interpolation = MoverSimulationManager.interpolationMethod == SimulationInterpolationMethod.Unity ? RigidbodyInterpolation.Interpolate : RigidbodyInterpolation.None; } private void Awake() diff --git a/Assets/_Scenes/Testing/SLope.unity b/Assets/_Scenes/Testing/SLope.unity @@ -4001,7 +4001,7 @@ GameObject: - component: {fileID: 1589352743} - component: {fileID: 1589352742} m_Layer: 0 - m_Name: Cube (37) + m_Name: MovingPlatform m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -4088,7 +4088,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: d0bb19cad963bad4095d65f8bb48c07e, type: 2} + - {fileID: 2100000, guid: 798ec0822060d814cb5a3864cbe8c49f, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0