- Home /
Can't get 1st person controller to stay on a platform.
This seems to be a recurring question here but I have tried all that I can find on this subject and it still won't work for me.
I have created a first person controller game where the player needs to step onto a platform that rises up and down. The script that I used for the motion of the platform is:
var RisingPlatformA : GameObject;
var RisingPlatformB : GameObject;
var speed : float = 0.1;
function FixedUpdate ()
{
var weight = Mathf.Cos(Time.time * speed * 2 * Mathf.PI) * 0.5 + 0.5;
transform.position = RisingPlatformA.transform.position * weight + RisingPlatformB.transform.position * (1-weight);
}
That works fine in a Mac/PC world game. My character will travel up and down just great but I'm trying to get this to work on the iOS system. When I try it there, the platform moves beautifully but the player just falls through the platform. I searched this site and found something that seems to be exactly what I'm looking for at:
**http://answers.unity3d.com/questions/8207/charactercontroller-falls-through-or-slips-off-mov.html**
but when I follow along with that as well as the 2D tutorial from Unity, I can't get it to work. I really don't know what I am doing wrong. Granted, I am not completely versed in javascript but I have been learning it.
The answer that @Rune Skovbo Johansen posted has areas that need to be filled in and I'm not sure what is needed.
I gave the platform a rigidbody, turned off Use Gravity and turned on Is Kinematic but I still can't travel up on the platform or jump off of it.
I think I included all the info that I have at this point. If I'm missing anything, I will be happy to add it.
Any help on this would be greatly appreciated as this is all I am left with to complete my project.
Thanks so much in advance!!! Tom
Answer by aldonaletto · Jan 05, 2012 at 03:24 AM
Have you tried the Elevators tutorial? It's a youtube movie that explains how to use a trigger to child the character to the elevator, much like mentioned in your first comment.
You could try it; if this still fails, you can change the trigger script to this one:
private var yOffset: float; // offset from trigger y private var player: Transform; //
function OnTriggerEnter(col: Collider){ if (col.CompareTag("Player")){ // entered the trigger: player = col.transform; // link the character to the platform yOffset = player.position.y - transform.position.y; // get the relative y } }
function OnTriggerExit(col: Collider){ if (col.CompareTag("Player")){ player = null; // null the link when exiting the trigger } }
function LateUpdate(){ if (player){ // player position follow platform y player.position.y = transform.position.y + yOffset; } } This script forces the character to keep the y relative position it had when entered the trigger, what should make it go up and down with the platform. When exiting the trigger, the link is broken and the character can jump or fall - things that it can't do while in the trigger volume.
EDITED: Well, since nothing else worked, let's use the dirty trick. To begin with, find in the FirstPersonControl.js the following part:
... movement += velocity; movement += Physics.gravity; movement *= Time.deltaTime;
// Actually move the character
character.Move( movement );
...
Just modify the first line adding the small movement value:
movement += velocity + Vector3(0, 0, 0.0001);
This code will make the player move continuously 0.1mm per second; if this solves the problem, you can try to reduce even more the value, or use the platform trigger to enable the small movement only when the player entered it.
I would suggest you to put an additional "floor" inside the platform - a stretched cube without any rigidbody, and child to the platform but positioned a little below the platform level: it would become a "safety collider" to stop character fall.
Another possibility: I saw a question one of these days that had the same problem (not sure if in a mobile device), and the OP found an interesting solution: he put a trigger inside the platform (a little below the platform surface), and its OnTriggerEnter event just moved the character back to the platform surface - I suppose the code (not shown) should be something like this (player script):
var offset: float = 1.1; // adjust character position here
function OnTriggerEnter(other: Collider){ if (other.tag == "Platform"){ // tag the trigger as "Platform"! // move character back to where it should be: transform.position.y = other.transform.position.y + offset; } }
There's a lot of code in Character$$anonymous$$otor.js for handling moving platforms, I'm surprised it doesn't work on iOS. $$anonymous$$ight be worth sticking some Debug.Log calls into all the moving platform functions and see which ones are being called - maybe there's a loophole in the logic?
Also, I've been assu$$anonymous$$g this is framerate-related, as that's the most obvious difference between desktop and iOS. Is the framerate actually any lower on your iOS build though? If so, try disabling as much of the scene as you can (or set the far clip plane very close)...if you can get it to run faster, and the moving platform suddenly works again then it IS a framerate issue.
In that case, maybe you can "fix" it by optimising your scene to run faster - simplify shaders, reduce geometry, shorten the draw distance, disable GameObjects outside a certain range of the player, etc...
@Zephyr, I tried the elevators in my PC and had the same problem: the character stayed over the platform when going down, but fell through when it moved up. I used the trigger over the platform to child the character, and it worked like a charm! I childed a cube to the platform, adjusted it's dimensions like in the tutorial and made it invisible and set isTrigger, then attached the script below to the trigger:
function OnTriggerEnter(other: Collider){ if (other.tag == "Player"){ other.transform.parent = transform.parent; } }
function OnTriggerExit(other: Collider){ if (other.tag == "Player"){ other.transform.parent = null; } }
@aldonaletto, I really appreciate your help! I have done the same thing and it does work well for the PC and the $$anonymous$$ac. In fact, on the $$anonymous$$ac, the standard assets first person controller doesn't even need any extra scripting to have the character stay on my platform. It seems to be a major problem in the iOS. I have tried your suggestion above and the character still falls through even when I make it the child of the cube and/or platform. I even tried to use the scripting form the standard assets in the mobile iOS first person but it took away the joystick scripts and expects the input to be from a keyboard. So, that didn't work either. I really think that if I can figure out how to force the first person to move ever so slightly even when the player is not moving it, that should solve my problem but I don't know how to script that or where to put the 0.001 force movement for X in the scripting.
If you know that, PLEASE tell me. I am about ready to change the whole level but I think what I have is really cool and I'd like to keep it.
Agian, thank you so much for you effort. I'm still trying.
$$anonymous$$
Well, since nothing else worked, let's use the dirty trick. To begin with, find in the FirstPersonControl.js the following part:
... movement += velocity; movement += Physics.gravity; movement *= Time.deltaTime;
// Actually move the character
character.$$anonymous$$ove( movement );
...
Just modify the first line adding the small movement value:
movement += velocity + Vector3(0, 0, 0.0001);
This code will make the player move continuously 0.1mm per second; if this solves the problem, you can try to reduce even more the value, or use some periodic function like sine:
var delta = $$anonymous$$athf.Sin(3*Time.time);
movement += velocity + Vector3(0, 0, 0.001 * delta);
This code will swing the player 1mm forth and back each second.
Answer by Winterblood · Jan 02, 2012 at 03:05 AM
Most likely this is because your framerate is lower on mobile, so where the desktop sees you embedding slightly in the platform and unembeds you, the mobile platform sees you embedded right through the platform and can't figure out how to seperate them. It's called "tunnelling" because in extreme cases a ball might be on one side of a wall one frame, and on the far side the frame after. In that case it has "tunnelled" right through without even touching the wall.
Try setting the player's collision to continuous rather than discrete. That makes the collision geometry sweep through the space from one frame to the next, so it would detect the aforementioned wall. It's more maths, but worthwhile on critical objects like the player's capsule.
If that doesn't help, you may need to do the same thing on the platform - but that will require a rewrite so that the platform is driven to position by physics forces rather than repositioned every frame by script. You might get away with just setting the platform Rigidbody's velocity manually based on the difference from the last frame, to give it a hint about which way the player should unembed.
Still sounds like the same problem - when the platform moves down away from the player, the player can fall onto it. But when the platform rises towards the player as gravity is pulling the player down, they move towards each other simultaneously and embed too far.
@Codayus's suggestion sounds like it should work, let's debug it. Try adding a Debug.Log( "On platform!") message to make sure the trigger box is activating when it should be. $$anonymous$$aybe the trigger is too small, or offset slightly in the Z axis?
Sounds like the player capsule is unembedding fine from the platform as long as it is doing the moving, but not when it stays still and the platform moves through it.
Dirty hack idea - give the trigger box an OnTriggerStay function which pokes the player capsule with a microscopic +Y nudge to keep it moving just enough for the physics to do the unembedding...
I'm on my iPhone now and can't check the FirstPersonController script. Suspect it's fine as long as the capsule is moving. Try adding the microscopic upward movement hack to the FirstPersonController script every frame, just to see if it actually helps...
It's just what I mentioned above - find the code in the FirstPerson$$anonymous$$ovement script that moves the player, and make sure that it always moves them +0.001f in the Y axis even if they're not trying to move. This will stop the physics from letting the player settle.
If you can't get that working I can help with the code in a couple of days, but I've got to finish my FIAF entry before the deadline!
@Winterblood, Here is the section of the script that appears (to me) to be the movement section. It is from the First Person Controls of the Standard Assets ($$anonymous$$obile) group:
function Update(){
var movement = thisTransform.TransformDirection( Vector3( moveTouchPad.position.x, 0, moveTouchPad.position.y ) );
// We only want horizontal movement
movement.y = 0;
movement.Normalize();
// Apply movement from move joystick
var absJoyPos = Vector2( $$anonymous$$athf.Abs( moveTouchPad.position.x ), $$anonymous$$athf.Abs( moveTouchPad.position.y ) );
if ( absJoyPos.y > absJoyPos.x )
{
if ( moveTouchPad.position.y > 0 )
movement *= forwardSpeed * absJoyPos.y;
else
movement *= backwardSpeed * absJoyPos.y;
}
else
movement *= sidestepSpeed * absJoyPos.x;
I replaced each '0' with '0.001' but it didn't work. I even went so far as to put a '1' in each spot. Your suggestion sounds like it's the answer that I'm looking for I just don't know how to incorporate it in with the script. Thanks ahead for any help!
$$anonymous$$
Answer by milali · Jan 13, 2012 at 12:15 AM
yerp try attaching your actor to the elevator via collisions and then detach when he moves off it. When attached whatever translation the elevator does you apply that to the player before he does his collision checks himself.
so do the players movement in lateupdate.
Hey I tried doing that but even after attached as a child to a moving platform my first person character still doesn't move with the platform
Your answer
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
How to only get touch on specific object? 0 Answers
Boolean check not referenced correctly from other script 2 Answers
First Person Controller controlling via another script 0 Answers
First Person Controller (or all scripts?) Not Working Anymore 3 Answers