- Home /
Velocity powered rigidbody on a moving platform without parenting.
Hello, I've searched beforehand, and nothing applies to my specific situation, and I need to have moving platforms work, however, I'm using a rigidbody because I need it to be pushed around, and because of issues with scaling and being parented but just frozen in midair, I can't use parenting to do this.
I'm moving the player by directly controlling velocity, the platform is ticked as kinematic (it has a rigidbody too), gravity on it is disabled, the way the platform moves is like this:
public class Platform : MonoBehaviour
{
public float speed = -1f;
public Vector3 pointB;
IEnumerator Start()
{
var pointA = transform.position;
while (true)
{
yield return StartCoroutine(MoveObject(transform, pointA, pointB, speed));
yield return StartCoroutine(MoveObject(transform, pointB, pointA, speed));
}
}
IEnumerator MoveObject(Transform thisTransform, Vector3 startPos, Vector3 endPos, float time)
{
var i = 0.0f;
var rate = 1.0f/time;
while (i < 1.0f)
{
i += Time.deltaTime * rate;
thisTransform.position = Vector3.Lerp(startPos, endPos, i);
yield return null;
}
}
}
What can I do to get the player to stick to the platform when needed?, and only when he's standing on the top of it, a scenario with the player being stuck to the side of the moving platform wouldn't be very good.
Answer by HarshadK · Apr 28, 2014 at 02:34 PM
I know it is not the best way but you can use Fixed Joint for this purpose.
As you want to have your player character to just stand on the platform you can use Fixed Joint for this.
All you have to do is check when the player collides with the platform and create a joint between the platform and player.
Also you can just destroy the joint when not needed i.e. you want to make player move away from the platform.
Alright, I've sorta got it working, only thing is that I can't seem to set the break force or break torque via script, how do I do this?, I'm only given the option to change the hingeJoint break force.
There are two ways: 1) you have to apply force greater than your break force on your object. To use this you have to use lower amount of break force. 2) or you can Destroy the fixed joint component from your object. And each time create and add the fixed joint component programatically as required.
Sorry if I didn't make it clear, that isn't my problem, I can't figure out how to assign the break force, which means I can't lower it, I need to know how to use the scripts to decide what the break force is.
Does this make sense?, by default the break force is infinity, I can't find any way to use scripting to adjust this to a lower number, I found an option to adjust the break force for hinge joints, but not fixed joints.
I did this with math, no parenting or joint. It does not use a rigidbody so I guess it is not what you want.
Answer by Mr.Hal · Apr 29, 2014 at 11:01 AM
Make the object on the platform share the velocity of the platform its on. So on the callback OnCollisionStay(). Get the rigidbody and assign the velocity on it to be the same as the platform. However for this to work you need to find out, make or use Vector3.SmoothDamp to find out the velocity of the platform. Because looking at your script... You are manually moving it via the lerp function so there is no true way to know the velocity of the platform. You could take the normalized direction of where the platform is going and multiply it by the speed. You could also find out if the player is on the platform by using a trigger instead or find out the direction the player is relative to the platform.
var Direction = (transform.position - player.transform.position).normalized;
const float SafeZone = 0.5;//Adjust me a little!
//Player is on the platform
if(Direction.y > SafeZone)
{
}
Answer by marcanthonysanti · Oct 18, 2020 at 06:06 PM
I know this is super late, but even 6 years later there was little in way of example on how to do this when the character is using a dynamic Rigidbody 2d (or 3d) and the platforms are kinematic.
So I took the additive velocity approach and that seemed best.
Here is my moving platform component code
using Player;
using UnityEngine;
namespace Environment {
public class MovingPlatform : MonoBehaviour {
public ParticleSystem dirt;
public float speed = .5f;
public Vector2 startPosition;
public Vector2 endPosition;
[HideInInspector] public Vector3 velocity;
private Rigidbody2D _self;
private SwordMenMovement _player;
private Vector2 _distance;
private Vector2 _oldPosition;
private bool _playerIsOnTop;
private void Start() {
_self = GetComponent<Rigidbody2D>();
_oldPosition = _self.position;
}
private void FixedUpdate() {
var time = Mathf.PingPong(Time.time * speed, 1);
_distance = Vector2.Lerp(startPosition, endPosition, time);
_self.MovePosition(_distance);
// calculate velocity on kinematic object, I found a version of this on the internet and adopted it to the fixed update method.
var newPosition = _self.position;
var media = (newPosition - _oldPosition);
velocity = media / Time.fixedDeltaTime;
_oldPosition = newPosition;
if (_playerIsOnTop && _player) {
// custom function on my player component
_player.AddVelocity(velocity);
}
}
private void OnCollisionEnter2D(Collision2D other) {
if (!other.collider.CompareTag("Player")) return;
// only when player is on top of the platform
if (!(Vector3.Dot(other.contacts[0].normal, Vector3.down) > 0.5)) return;
// optional particle effect
dirt.Play();
// some caching
if (_player == null) {
// get whatever component used to able to access your player
_player = other.transform.GetComponent<SwordMenMovement>();
}
_playerIsOnTop = true;
}
private void OnCollisionExit2D(Collision2D other) {
if (!other.collider.CompareTag("Player")) return;
_playerIsOnTop = false;
}
}
}
Within my player component for movement
public void AddVelocity(Vector2 v) {
_velocity += v.x;
}
where the _velocity
is applied in a fixed update with modified code from the Brackeys character controller;
var targetVelocity = new Vector2(_velocity, _rb.velocity.y);
_rb.velocity = Vector3.SmoothDamp(_rb.velocity, targetVelocity, ref _mVelocity, .0001f);
where the friction in the material is set to 1, though it's not needed anymore so i'm going to remove it.
I should probably refactor and rename AddVelocity to AddHorizontalVelocity