This post might look simple to you but the problem has burnt my hairs. Actually I am working on a game which is similar to Temple Run on iOS. Now if you have played that game then it would be easier for you to understand it in a better way.
My character would keep on running endlessly until it falls from the platform like in Temple Run. I do not have any problem in implementing all other features which Temple Run has except limiting the position of the character in left and right while at the same time maintaining the same forward speed.
I do not want my character to go beyond the side limits of the platform. To do this I first put some colliders in the sides so that it won’t fall from the platform but then the character controller starts giving jitter. Then I tried to do this by scripting and since then I have been trying hard to achieve this.
Please if anybody could help me in coming out of this situation would be greatly appreciated.
I don’t know how/if you can stop the jitter, but that seems like the optimal solution to me (as well).
Failing a solution to that, I would consider to stop trying to move the character when he reaches those end-points (but keeping any animations running, so as to give the illusion of trying to move still).
If you post your most promising attempt at a solution, you might get more specific suggestions.
That’s what I did by limiting the position in x axis as
var upperLimit: float=2;
var lowerLimit: float=2;
if(player.position.x>upperLimit)
player.position.x=upperLimit;
if(player.position.x<lowerLimit)
player.position.x=lowerLimit;
But unfortunately it won’t work as my character would keep on changing it’s direction based on the path on which it is running. So I can’t rely on just one axis.
So after this what I did was quite tricky.
On each left or right movement I used to check which axis is right to the player and then setting the limits on the behalf of it’s position.
function SetLimits()
{
//This would check if the right axis is "X". So we have to limit x position of player.
if(Mathf.Approximately(player.right.x,1) || Mathf.Approximately(player.right.x,-1))
{
//We are running in forward direction
if(player.right.x>0)
{
upperLimit=player.position.x+2;
lowerLimit=player.position.x-2;
}
//We are running in backward direction
else if(player.right.x<0)
{
upperLimit=player.position.x-2;
lowerLimit=player.position.x+2;
}
}
//This would check if the right axis is "Z". So we have to limit z position of player.
if(Mathf.Approximately(player.right.z,1) || Mathf.Approximately(player.right.z,-1))
{
//We are running in left direction which is equivalent to Vector3.left
if(player.right.z>0)
{
upperLimit=player.position.z+2;
lowerLimit=player.position.z-2;
}
//We are running in right direction which is equivalent to Vector3.right
else if(player.right.z<0)
{
upperLimit=player.position.z-2;
lowerLimit=player.position.z+2;
}
}
}
Now this code has 2 problems.
It is quite messy and might not give you expected results.
You just can’t set left, right limits on the behalf of player’s position as the chances are more likely that you would fall from the platform.
Consider the situation when you turn left just on the edge of the platform. Now either right/left limit would be too far from the edge of the new platform so you would definitely fall from one of the sides.
Even if I try to set the limit based on the ground, I am just unable to get how would I do it. I can get the reference of the collider in OnControllerColliderHit() but after that what, where should I go from there?
Could you please put some more light on this? How I can actually achieve that.
I would have a separate game object(invisible) follow the player’s transform forward position but not it’s left/right position. I will then have that game object do ray casts and have it detect the colliders on the edge of the player’s left and right limits. I will use the raycast to get me back a distance, with that value, I dunno, make up an algorithm that restricts player movement.
But that game object that projects the ray cast has to be in the middle of the screen at all times.
What does the code that moves your character look like?
In stead of simply limiting the x movement by setting it directly like that, how about disabling movement completely if the character is heading too far off the side? In stead of setting the x-value in your SetLimits() function, I would consider switching some bool back and forth, and then checking against it in your movement script.
I already have an invisible object but that is front of the player but I am using it for Camera functionality.
I have thought of the same scenario in which there would always be an object in the middle of the platform to get the reference in setting left and right limits but I too don’t know how to achieve this.
I am using Unity’s inbuilt script viz. character motor and then accessing it in my own script to move, turn, jump, steer, etc.
Hmm… it’s a good !dea, I would give it a try, thanks
First, let me be clear what you’re trying to achieve. The character hits some object on the platform, and should then stop there and not move further. Is that correct, or too simply put?
You could put code like this in the script that controls movement (applies changes to velocity/position):
var upperLimit: float=2;
var lowerLimit: float=2;
var canMoveRight: bool=true;
var canMoveLeft: bool=true;
if(player.position.x>upperLimit)
canMoveRight = false;
else
canMoveRight = true;
if(player.position.x<lowerLimit)
canMoveLeft = false;
else
canMoveLeft = true;
Of course, your limits are now more like the scene boundaries, like the edge of the screen, and you’d need one set of bool for each area. You may want to re-think this completely, depending on what exactly you’re trying to do.
In any case, you can check these values before applying movement.
if ( [Trying to move right] canMoveRight)
//do movement to the right
else
//ignore movement order
if ( [Trying to move left] canMoveLeft)
//do movement to the left
else
//ignore movement order
Actually this is not the case. Let me explain to you,
My character is moving in forward direction and you are steering your character left or right with the help of accelerometer and swipe to turn left or right and jump or slide. When I say swipe to turn left or right, it means a 90 degrees or 270 degrees rotation on either side.
Now when you steer with accelerometer you would fall from the ground if you haven’t set any limits for left and right.
and Soldier321 I know how to use raycast and I have implemented in my previous games as well but what I meant is to put some light on the scenario you had mentioned in your previous post.
I don’t understand what you mean by ‘fall from the ground’. Can you explain that?
Is the view like from the side, as in a normal platformer game, or is it top-down?
I think you’re overengineering the problem. We know that the character will always be constrained to the exact same region no matter what, and that the Z and Y axis is always the same; the only thing that changes is his X axis, which is constrained to a certain region. You don’t need colliders, you don’t need raycasts or an invisible object, you just need to limit his movement along X as he moves left or right.
But it would work when my character would not take a turn of 90 degrees to the left or 270 degrees to the right. I don’t know why but the same axis is not working for me, it changes the axis and I have to deal with 2 axes i.e., x and z.
actually it is very lengthy and I haven’t commented yet. But for the movement I am using FPS Controller script and CharacterMotor script provided by Unity.
You could just limit his movement on his local x axis, so you only let him move so far to the right and left on his local x axis. Something like this. I used moveSide as an int, because I don’t like having a ton of booleans to constantly change. Also this code is untested.
var moveSide : int;
var sideMoveAmount : float;
function Update(){
if(transform.localPosition.x > sideMoveAmount){
moveSide = 1;
}
else if(transform.localPosition.x < -sideMoveAmount){
moveSide = 0;
}
}
Thanks Astrauk for replying but the method is not working for me.
Diablo on your suggestion I looked into CharacterMotor and I was wondering does “InverseTransformDirection” method has something to do with my axis problem?
ok then. So we have two fixed values for x, for when the character falls off to the left and right? Below some value is ok, and it’s also ok above some other value?
Then I would push my suggestion. Find the x values at which he falls to the right [maxRight], and the x value where he falls to the left [minRight].
Determine if the character is about to plummet to his death:
You put this in your ‘character’ script.
var upperLimit: float=[maxRight];
var lowerLimit: float=[minRight];
var canMoveRight: bool=true;
var canMoveLeft: bool=true;
if(player.position.x>upperLimit)
canMoveRight = false;
else
canMoveRight = true;
if(player.position.x<lowerLimit)
canMoveLeft = false;
else
canMoveLeft = true;
So, if you test your game and find that the character falls off when his transform.position.x is greater than, say, 800, and fell of to the left when it’s less than 0, you would go:
var upperLimit: float=800;
var lowerLimit: float=0;
The final task is to make use of the bool. Put this in the script that handles the movement:
//Get a hold of the character script
//This could be your CharacterMotor or -Controller scripts.
//Assumes the script 'CharacterMotor' is on the same GameObject as this script
// CharactoerMotor is the name of the script where you place the above code
CharacterMotor motorSc = (CharactorMotor) GetComponent<CharacterMotor>();
if ( [Trying to move right] motorSc.canMoveRight)
//do movement to the right
else
//ignore movement order
if ( [Trying to move left] motorSc.canMoveLeft)
//do movement to the left
else
//ignore movement order