Alternative methods of making character move with 3d moving platform?
I'm asking, because my usual solution (dynamic parenting to platforms) causes me lot of issues (scale and object not always staying on a platform) and solutions that require things like physics materials are out of a question as well, because when I tried them, player was moving like through molasses when on a moving platform.
Are there any other ways of making player move with a 3d moving platform? Player is a rigidbody and so is the platform.
Answer by LazyElephant · Dec 27, 2015 at 08:38 AM
A simple solution would be to set the player velocity to match the moving platform velocity when the player lands.
void OnCollisionEnter(Collision collision){
if( collision.gameObject.tag == "Platform" ){
gameObject.GetComponent<Rigidbody>().velocity = collision.gameObject.GetComponent<Rigidbody>().velocity;
}
Edit: To get this working in my test, I had a cube acting as the platform and a capsule as the player, both with rigidbodies attached. The only settings I changed on the rigidbodies were to set the platform rigidbody to kinematic and to constrain the x and z rotation of the capsule so it wouldn't roll over.
On the capsule, I added these two scripts:
using UnityEngine;
using System.Collections;
public class MovePlayer : MonoBehaviour {
Rigidbody rbody;
void Start () {
rbody = gameObject.GetComponent<Rigidbody>();
}
void FixedUpdate () {
float xAxis = Input.GetAxis("Horizontal");
rbody.AddForce(Vector3.right * 20 * xAxis);
}
}
and
using UnityEngine;
using System.Collections;
public class PlayerCollision : MonoBehaviour
{
void OnCollisionEnter(Collision collision)
{
print("CollisionEnter");
gameObject.GetComponent<Rigidbody>().velocity = collision.gameObject.GetComponent<Rigidbody>().velocity;
}
}
On the platform, I used this one script:
using UnityEngine;
using System.Collections;
public class MovePlatform : MonoBehaviour {
Rigidbody rbody;
public Vector3 targetPos = new Vector3(5, 0, 0);
float elapsedTime = 0f;
// Use this for initialization
void Awake() {
rbody = gameObject.GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate () {
elapsedTime += Time.deltaTime;
rbody.MovePosition(targetPos * elapsedTime );
}
}
To simulate dropping onto the platform, I started the capsule a short distance above the platform. The result was a capsule that didn't slide at all when it landed on the platform and was still able to move with my input.
Thought about it, but it would have that unfortunate con that it would make impossible for player to move around the platform, since it would be have to be applied in OnCollisionStay as player is a rigidbody. Also put it as an answer.
If you're moving the platform with the physics system, using it once in OnCollisionEnter should work. When I tested the solution, I had a kinematic rigidbody on the platform and moved it with rigidbody.$$anonymous$$ovePosition. I used a capsule with a non-kinematic rigidbody attached to represent the player. When the capsule landed on the platform, it didn't slide at all. I didn't test moving it after, but since the velocity was only set in the OnCollisionEnter function, it shouldn't effect your ability to move.
I edited my answer to give the code I used. Unless there is something specific to your implementation that prevents it, this solution should work.