- Home /
Need help scripting ladders for a 3d Top-Down level
Hey everyone I really need help scripting ladders for a level that is strictly top-bottom that I am working with a few teammates for a class project. I have both the code and an attachment for a demo of my ladders and this level uses a first-person controller, yet it is more of a third-person level. I'll show you my demo level and my script, but since the demo level exceeds the file size limit, I have it uploaded on an external host.
Here is my level. http://www.filefactory.com/file/2ncr6pzdz5qr/LadderScriptDemo.zip
And here is my script as well:
#pragma strict
var ChController : Transform;
var inside : boolean = false;
var heightFactor : float = 3.2;
var chMotor: CharacterMotor;
private var FPSInput : FPSInputController;
function Start()
{
FPSInput = GetComponent(FPSInputController);
chMotor = GetComponent(CharacterMotor);
}
function OnTriggerEnter (Col : Collider)
{
if((Col.gameObject.tag == "northLadder")||(Col.gameObject.tag == "southLadder")||
(Col.gameObject.tag == "eastLadder")||(Col.gameObject.tag == "westLadder"))
{
FPSInput.enabled = false;
inside = !inside;
ChangeGravity(0.0);
ChangeAirAccel(0.0);
}
}
function OnTriggerExit (Col : Collider)
{
if((Col.gameObject.tag == "northLadder")||(Col.gameObject.tag == "southLadder")||
(Col.gameObject.tag == "eastLadder")||(Col.gameObject.tag == "westLadder"))
{
FPSInput.enabled = true;
inside = !inside;
ChangeGravity(20.0);
ChangeAirAccel(15.0);
}
}
function Update(Col : Collider)
{
if(Col.gameObject.tag == "northLadder")
{
if((inside == true && Input.GetKey("w")) || (inside == true && Input.GetKey("up")))
{
ChController.transform.position += Vector3.up / heightFactor;
}
if((inside == true && Input.GetKey("s")) || (inside == true && Input.GetKey("down")))
{
ChController.transform.position += Vector3.down / heightFactor;
}
}
if(Col.gameObject.tag == "southLadder")
{
if((inside == true && Input.GetKey("w")) || (inside == true && Input.GetKey("up")))
{
ChController.transform.position += Vector3.down / heightFactor;
}
if((inside == true && Input.GetKey("s")) || (inside == true && Input.GetKey("down")))
{
ChController.transform.position += Vector3.up / heightFactor;
}
}
if(Col.gameObject.tag == "westLadder")
{
if((inside == true && Input.GetKey("a")) || (inside == true && Input.GetKey("left")))
{
ChController.transform.position += Vector3.up / heightFactor;
}
if((inside == true && Input.GetKey("d")) || (inside == true && Input.GetKey("right")))
{
ChController.transform.position += Vector3.down / heightFactor;
}
}
if(Col.gameObject.tag == "eastLadder")
{
if((inside == true && Input.GetKey("a")) || (inside == true && Input.GetKey("left")))
{
ChController.transform.position += Vector3.down / heightFactor;
}
if((inside == true && Input.GetKey("d")) || (inside == true && Input.GetKey("right")))
{
ChController.transform.position += Vector3.up / heightFactor;
}
}
}
function ChangeGravity(g: float){
chMotor.movement.gravity = g;
chMotor.movement.maxFallSpeed = g;
}
function ChangeAirAccel(a: float){
chMotor.movement.maxAirAcceleration = a;
}
So the problem that I am trying to solve is that I want to make it so that these ladders can be climbed no matter what direction they are facing and so you should be able to use either key to go up and down them since this is a top/down map. You also have to jump into the colliders while you are adjacent to the ladders in order to use them. The ladders are also tagged with the four cardinal directions as the script very much depends on tags. However, when I run the level, the code to control the movement up the ladders does not seem to work for some reason. When I jump into the ladders' colliders, all the controller does is drift up the ladders and then gets stuck when it reaches the top. I can't control it going up or down. Can anyone please look at my stuff and tell me what is going on and what I need to fix? Or maybe show me an even better way to make this mechanic work for a top/down level?
Answer by StrykerS. · Mar 13, 2014 at 01:13 PM
I think your controller is getting stuck between onCollisionEnter and onCollisionExit. When you jump into the ladder it triggers and allows you to climb but when you reach the top there's probably a couple frames that you exit the ladder collider but then you reactivate your physics and the controller falls back onto the ladder. I can't be sure this is whats happening but I've had this sort of thing happen with a few projects.
The way I would fix this if that is what's going on, is by adding a timer to stop the player from checking to see if it's hit the ladder for a bit so the player has time to move away from the ladder before it checks again.
Something like this maybe.
void Update()
{
if(timer > 0)
{
timer -= Time.deltaTime;
}
}
void onCollisionEnter()
{
//Check for your ladder collider
if(timer <= 0)
{
//Turn off your physics and start climbing
}
}
void onCollisionExit()
{
//Run your code to activate the normal controller
//then at the end set your timer to some number
//it doesn't have to be 1 second you can set it lower
//but I would use at least 1 second to make sure it works
timer = 1.0f;
}
Just a personal note, I'm not sure how other feel about this but I'm a bit hesitant to download and open zip files so I haven't actually seen how your game runs. A better option might be to setup a dropbox account and build a webplayer version so you can share it that way.
Answer by Terminus_Est · Mar 14, 2014 at 01:03 AM
Ok here is my updated code but it does not even compile. And plus I am doing it in JavaScript, not C# so I'm not sure how your example would translate well to JS.
#pragma strict
var ChController : Transform;
var inside : boolean = false;
var heightFactor : float = 3.2;
var chMotor: CharacterMotor;
private var FPSInput : FPSInputController;
function Start()
{
FPSInput = GetComponent(FPSInputController);
chMotor = GetComponent(CharacterMotor);
}
function OnTriggerEnter (Col : Collider)
{
if((Col.gameObject.tag == "northLadder")||(Col.gameObject.tag == "southLadder")||
(Col.gameObject.tag == "eastLadder")||(Col.gameObject.tag == "westLadder"))
{
if(timer < 0)
{
FPSInput.enabled = false;
inside = !inside;
ChangeGravity(0.0);
ChangeAirAccel(0.0);
}
}
}
function OnTriggerExit (Col : Collider)
{
if((Col.gameObject.tag == "northLadder")||(Col.gameObject.tag == "southLadder")||
(Col.gameObject.tag == "eastLadder")||(Col.gameObject.tag == "westLadder"))
{
FPSInput.enabled = true;
inside = !inside;
ChangeGravity(20.0);
ChangeAirAccel(15.0);
timer = 1.0f;
}
}
function Update(Col : Collider)
{
if(timer > 0)
{
timer -= Time.deltaTime;
}
if(Col.gameObject.tag == "northLadder")
{
if((inside == true && Input.GetKey("w")) || (inside == true && Input.GetKey("up")))
{
ChController.transform.position += Vector3.up / heightFactor;
}
if((inside == true && Input.GetKey("s")) || (inside == true && Input.GetKey("down")))
{
ChController.transform.position += Vector3.down / heightFactor;
}
}
if(Col.gameObject.tag == "southLadder")
{
if((inside == true && Input.GetKey("w")) || (inside == true && Input.GetKey("up")))
{
ChController.transform.position += Vector3.down / heightFactor;
}
if((inside == true && Input.GetKey("s")) || (inside == true && Input.GetKey("down")))
{
ChController.transform.position += Vector3.up / heightFactor;
}
}
if(Col.gameObject.tag == "westLadder")
{
if((inside == true && Input.GetKey("a")) || (inside == true && Input.GetKey("left")))
{
ChController.transform.position += Vector3.up / heightFactor;
}
if((inside == true && Input.GetKey("d")) || (inside == true && Input.GetKey("right")))
{
ChController.transform.position += Vector3.down / heightFactor;
}
}
if(Col.gameObject.tag == "eastLadder")
{
if((inside == true && Input.GetKey("a")) || (inside == true && Input.GetKey("left")))
{
ChController.transform.position += Vector3.down / heightFactor;
}
if((inside == true && Input.GetKey("d")) || (inside == true && Input.GetKey("right")))
{
ChController.transform.position += Vector3.up / heightFactor;
}
}
}
function ChangeGravity(g: float){
chMotor.movement.gravity = g;
chMotor.movement.maxFallSpeed = g;
}
function ChangeAirAccel(a: float){
chMotor.movement.maxAirAcceleration = a;
}
And by the way I have a dropbox account but I do not know how to make a webplayer version and share it. Is there anyone else who may want to look at my file?
Pretty close just remove the f at the end of timer = 1.0f; and it should run fine. The f tells the c# compiler that the number is a float not a double this is not necessary in JS.
Hmm not sure if I fully understand your script since you are doing stuff to change the gravity but also using transform position which will move your character at the same rate right?
I never used character controller or character motor though so I may not be a good person to evaluate your script. For me after briefly trying out character controller I felt I would have more control just setting up everything from scratch, nice way to learn too but maybe I'm missing out on some cool features.
For me if I was doing this it would just be a matter of creating a big enough collider for the ladder and having a bool for when your within that collider. Then based on your distance from the player and ladder you either lock onto the ladder and do the animation when moving OR you are in the state of exiting entering the ladder like jumping on off or whatever you do specifically.
And then the up and down buttons would just directly transform your player up and down, when you reach a certain position relative to the ladder at top or bottom you are able to press another key to jump off.
You should probably post a screenshot of the player on ladder. I'm not sure if I understand why you have the 4 different direction tags.
Not sure if that will help at all but that's my 2 cents opinion on this without knowing all your details of the project it could be worthless.
Your answer
Follow this Question
Related Questions
force before ragdoll 1 Answer
Call a Void on Collision 2 Answers
Activate Script not Working 6 Answers
Tilemap edge-outline collider 1 Answer
Collider detection problems! 1 Answer