I’ve made a script to move my rigidbody capsuleCollider character when it’s on a moving platform. Basically it’s suppose to apply a Vector3 velocity to the rigidbody in the direction that the contact point has moved since the last frame. Instead it is causing movement in apparently random directions. I need help.
var addAmount : Vector3;
var PrevContactPoint : Vector3;
var StoredContactPoint : GameObject;
function Update()
{
//If not moving, determine the velocity to our rigidbody character by comparing the last contactPoint's position
//to its current position
if((Input.GetAxis("Vertical") == 0)(Input.GetAxis("Horizontal") == 0))
{
addAmount = StoredContactPoint.transform.position - PrevContactPoint;
}
else
{
addAmount = Vector3.zero;
}
//Another script catches the addAmount variable and applies it
//If moving, destroy the old StoredContactPoint and replace it with the current contactPoint
if((Input.GetAxis("Vertical") != 0)||(Input.GetAxis("Horizontal") != 0))
{
if(StoredContactPoint != null)
{
Destroy(StoredContactPoint);
}
StoredContactPoint = new GameObject("StoredContactPoint");
//The script "ControlScript" has the contactPoint info via OnCollisionStay
StoredContactPoint.transform.position = ControlScript.contactPoint;
StoredContactPoint.transform.parent = transform;
PrevContactPoint = StoredContactPoint.transform.position;
}
}
im not sure, but there are some things to mention here:
-You are doing this in Update() whilst the rigidbody(that is moved by physics.Force stuff, i imply) is moved in FixedUpdate (where you also get your .contactPoint)
-The rigidbody.velocity Vector only moves the rigidbody in FixedUpdate() by modifying its position, so you add a value every frame to a velocity that is applied in a completely other timeScale
Therefore addAmount sometimes will get added 0 times, other times it will get added 4 times (depending on the fixedTime/deltaTime ratio) before the velocity is applied to your character the next time
-what you can do:
-calculate the velocity in Update using deltaTime to compensate the variable frame lengths
-or just calculate and apply velocity in FixedUpdate()
or
-move the platform as a rigidbody by setting its velocity manually
-then check if character has contact, if yes add the platforms current velocity to the characters velocity
I changed the function to FixedUpdate as you recommended and it helped with a camera script in which a second camera followed a parented camera with a delay on the y axis. The second camera’s movement was shaky at first but when the position changes were made in fixedupdate it was smooth. I’m still unable to transfer motion from a platform to the character though. I failed to mention that I had already successfully done this with non-angular velocity change. If the character stands on a spinning platform I have to somehow translate the platform’s angular velocity to linear velocity.
you can use the distance of the contact point of your character to the center of the platform’s rotation. then calculate the radian that the rotation platform would drag the character next step. if you calculate a straight vector the character will get pushed off the plattform with time.
You should therefore simply rotate your Character around the center of rotation. If it happen to be that the rotating plattform is moving too, it should be no problem combining both transformations (rotational, velocity)
i guess this velocity is using radians, but i am not sure
I ended up sort of “cheating” lol. I made an inverted cylinder with the top and bottom removed that just fits around the character. Whenever standing on the rotating platform I use this cylinder to force move the character by having it parented by the platform and being set to the position of the character whenever he’s standing still. When moving, the collider for the inverted cylinder is disabled. The only problem, which is not a deal breaker in my opinion, is that when moving there is only about half of the velocity of the rotating platform applied through friction, so if one was to analyse it close enough they could tell it is not completely accurate.
I’ve seen lots of posts on different threads about this, and have been fighting with it for a while myself. I wanted to have my 3rd person character get on elevators or other moving platforms, but even if I parented to the platform, the player would often bounce up and down, or jerk around, even when moving quite slowly. For example, a descending hot air balloon , moving at less than 5 km/h was causing my character to float off the floor of the gondola! I’ve seen lots of suggestions. Everyone has their own favorite techniques, but many of the posted answers were pretty vague, or just didn’t seem to work. I’m going to try something different, and post a complete general purpose script, that should work in many situations. As such, it may have options you don’t need, but even if it doesn’t work for your specific needs, there might be something in it that you can use to build your own.
It’s pretty straightforward. It parents a player with a rigid body to another (moving) object. Rather than making the rigid body kinematic, I’ve provided options to restrict movement and/or rotation on any axis. There’s also an option to temporarily disable RB gravity while parented. This allows you to select how much or how little your player will be able to move within the confines of the moving platform, while not falling off or being left behind. Parenting happens when the player enters a trigger, and I’ve chosen to use the “Jump” button to break the parent link when it’s time to exit. Most of these options are selectable in the inspector window, but I’ve commented the code as much as possible so you won’t need to guess what I’m doing, or why. As a disclaimer, I’m not really a programmer, and those of you who are will probably see lots of stuff I could have done more efficiently, but it’s simple, it works, and it’s the first thing I’ve found that does. Just copy the whole thing into a new javascript, plonk it onto a trigger collider on your moving platform, select the options you want in the inspector, and hit play. I hope it helps at least some of you who are having problems with this.
// This script parents the player to another object when the player enters a trigger.
// It optionally restricts player movement and rotation on a per axis basis, and turns
// rigidbody gravity off while parented. The "Jump" button is used to unparent the player
// when it's time to leave, even when position restraints prevent other movements
// (and also serves to remove the player physically from the object:).
#pragma strict
var parentObject : GameObject; // select gameobject player will be parented to.
var delayStart : float = 0; // delays parenting to allow player to make full contact with surface.
private var myPlayer : GameObject; // will autodetect "Player" tag. To populate manually, remove "private".
private var rb : Rigidbody;
private var inTrigger : boolean = false;
private var onboard : boolean = false;
// target vectors to match position to
var targetPositionX : boolean = false;
var targetPositionY : boolean = false;
var targetPositionZ : boolean = false;
// target vectors to match rotation to
var targetRotationX : boolean = false;
var targetRotationY : boolean = false;
var targetRotationZ : boolean = false;
var disableGrav : boolean = true; // turns rigidbody gravity off when parented if true.
function Start () {
FindPlayer ();
}
function FindPlayer () { // finds player and rigidbody if present
yield WaitForSeconds (1);
myPlayer = GameObject.FindWithTag("Player"); // your player must be tagged as "Player".
yield;
if (!myPlayer) {
print ("Triggered Player Parenting script can't find player! Must be tagged as 'Player'");
}
else if (disableGrav !myPlayer.rigidbody) {
print ("Triggered Player Parenting script can't find rigidbody!");
}
else {
rb = myPlayer.rigidbody;
}
}
function OnTriggerEnter(newTrigger : Collider) {
if (newTrigger.tag == "Player") {
inTrigger = true;
}
}
function OnTriggerExit(newTrigger : Collider) {
if (newTrigger.tag == "Player") {
inTrigger = false;
}
}
function Update () {
if (inTrigger !onboard !Input.GetButton ("Jump")) { // triggers "GetIn" if conditions are met.
GetIn ();
}
if (onboard Input.GetButton ("Jump")){ // triggers "GetOut" if conditions are met.
GetOut();
}
}
function GetIn() {
yield WaitForSeconds (delayStart);
myPlayer.transform.parent = parentObject.transform; // parents player to object
if (rb disableGrav) {
rb.useGravity = false; // optionally turns off rigidbody gravity
}
onboard = true;
}
function GetOut() {
myPlayer.transform.parent = null; // unparents player from object
if (rb disableGrav) {
rb.useGravity = true; // turns rigidbody gravity back on
}
onboard = false;
}
function FixedUpdate () { // uses FixedUpdate to better match player controller position calculations
if (onboard) { // locks selected axis of player to parent object
if (targetPositionX) {
myPlayer.transform.position.x = parentObject.transform.position.x;
}
if (targetPositionY) {
myPlayer.transform.position.y = parentObject.transform.position.y;
}
if (targetPositionZ) {
myPlayer.transform.position.z = parentObject.transform.position.z;
}
if (targetRotationX) {
myPlayer.transform.rotation.x = parentObject.transform.rotation.x;
}
if (targetRotationY) {
myPlayer.transform.rotation.y = parentObject.transform.rotation.y;
}
if (targetRotationZ) {
myPlayer.transform.rotation.z = parentObject.transform.rotation.z;
}
}
else { // matches nothing
return;
}
}