commit b1d709bf8566ab0d7d4ae226411f0a0c331f94e2
parent d334726ef90e57b83d69b137c0d38b0c98caed67
Author: PlutoTank <qwolkensperg@gmail.com>
Date: Thu, 23 Apr 2020 20:37:34 -0400
can land on moving platforms
Diffstat:
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