- Home /
Object moves to -infinite... help!
Hi There:
I'm doing a platformer game, and i've planned a pick up that lets you fly, so when you pick it up, you can move up and down when you get input from the vertical axis...
this is my first game, that i'm coding, so i'm really bad at this, and i can't get this function to work properly.
The set up is the following:
The character has a bool that checks to check if it can fly, that is turned to true when you pick up the crate, that works... the problem is as soon as i pick up the crate, the player is translated to -infinite in the y position and the game crashes...
This is my example code:
public bool kiteOn = false; // checks to see if it can fly
public float kiteTime = 4.0f; // amount of time it can fly
public float kiteSpeed = 1.0f; // movement speed while flying
void Update()
...
if (kiteOn) // on update it checks it, and calls the function
{ninjaKite ();}
}
public void ninjaKite() // the function to make it "fly"
{
float timer = 0.0f;
while ( timer < kiteTime)
{
timer += Time.deltaTime;
inAir = true;
if (this.transform.position.y < 1.0f | this.transform.position.y > -1.0f)
{
float tmpY = this.transform.position.y + kiteSpeed * Input.GetAxis("Vertical");
this.transform.Translate (0.0f, tmpY, 0.0f);
}
}
kiteOn = false;
}
Answer by ThePersister · Sep 17, 2014 at 07:39 AM
Haha, easy one, we'll solve this in a fraction of time :3 You used to define a:
float timer = 0;
In the ninjaKite() method, which in turn was called very often, to up the timer, which is logical, however, making a new timer every update will keep it at roundabout 0.
So, now here's some new code. Note that we've only fixed the timer / crash issue, you might still want to edit the kiteSpeed value.
Also, I'm not sure what inAir does, but that's up to you ;)
public bool kiteOn = false; // checks to see if it can fly
public float kiteSpeed = 1.0f; // movement speed while flying
public float kiteTimer_Max = 4.0f; // amount of time it can fly
private float kiteTimer_Cur; // Define the timer_Cur up here
void Update() {
//...
if (kiteOn) // on update it checks it, and calls the function
{
ninjaKite ();
}
}
public void ninjaKite() // the function to make it "fly"
{
// Increment timer
kiteTimer_Cur += Time.deltaTime;
inAir = true; // ?
// Fly upwards when -1 < y < 1
if (this.transform.position.y < 1.0f | this.transform.position.y > -1.0f)
{
// Added time.deltaTime to smooth out the translation just a bit (in case you have lower fps => same result, because of Time.deltaTime)
// You might need a higher speed value though, but that's a number change.
// Calculate a new Y and fly
float tmpY = this.transform.position.y + kiteSpeed * Input.GetAxis("Vertical") * Time.deltaTime;
this.transform.Translate(0.0f, tmpY, 0.0f);
}
if (kiteTimer_Cur >= kiteTimer_Max)
{
// Turn off the flying and reset the timer
kiteTimer_Cur = 0;
kiteOn = false;
}
}
I hope that helps, if you need anything else or have other questions, please ask another one or comment down below if it's related.
Otherwise, please accept this answer and have a nice day! :)
Thanks for your time, and the code example, i'm still pretty new, so everything helps!
On to commenting the solution:
inAir is to check if the character is in the air so it cant jump, so no jumping while flying.
the game doesn't crash anymore, and that's GOOD! but the char is moved downwards out of the screen and dies, restarting the scene.
as i commented on Bored$$anonymous$$ormon's answer, i tried using $$anonymous$$athf.Clamp, and if i put it somewhere in the middle of the screen it just stays there shaking, and does not take input.
As it is now, the crash issue is fixed, but it's still not flying, because it's not taking input and goes automatically to the lowest value possible.
The idea is that it should not be able to go up or down beyond the screen boundaries while it is flying.
Thanks again, and i hope you can help me out a little bit more on this one :)
Heey there, sorry for my massive absence, I was busy doing my internship research ;O
You probably figured out your problem by now and I want to thank you for accepting my answer, but here's the fix to your reply :3
Let me fix up the code a bit, less .transform (GetComponents in reality) and Fixed the whole translate idea (adding up the transform to the current transform will basically apply a POW (transform.localposition.y ^ frames, which essentially will be infinity in no time) so ins$$anonymous$$d of that, we just use kiteSpeed and the input with transform.position += in a nice and easy fashion :)
public bool kiteOn = false; // checks to see if it can fly
public float kiteSpeed = 1.0f; // movement speed while flying
public float kiteTimer_$$anonymous$$ax = 4.0f; // amount of time it can fly
private float kiteTimer_Cur; // Define the timer_Cur up here
Transform m_Transform;
void Start() {
m_Transform = transform;
}
void Update() {
//...
if (kiteOn) // on update it checks it, and calls the function
{
ninja$$anonymous$$ite ();
}
}
public void ninja$$anonymous$$ite() // the function to make it "fly"
{
// Increment timer
kiteTimer_Cur += Time.deltaTime;
inAir = true; // ?
// Fly upwards when -1 < y < 1
if (m_Transform.position.y < 1.0f | m_Transform.position.y > -1.0f)
{
// Added time.deltaTime to smooth out the translation just a bit (in case you have lower fps => same result, because of Time.deltaTime)
// You might need a higher speed value though, but that's a number change.
// Calculate a new Y and fly
m_Transform.position += new Vector3(0.0f, Input.GetAxis("Vertical") * kiteSpeed * Time.deltaTime, 0.0f);
}
if (kiteTimer_Cur >= kiteTimer_$$anonymous$$ax)
{
// Turn off the flying and reset the timer
kiteTimer_Cur = 0;
kiteOn = false;
}
}
That should be it then, gl with your future program$$anonymous$$g!! :D
Thanks Again!!! i've moved towad another project... in fact i started that after the 2d infinite scroller live class on the Unity page, but i wasn't really into it... at the moment i'm trying a diferent thing but i'll be sure going back to it in the future...
Answer by Kiwasi · Sep 17, 2014 at 07:36 AM
Got it. Your while loop is executing entirely in a single frame.
Couple of solutions
Make NinjaKite a coroutine
Move the timer functionality out into update
Change the structure so that the timer check is done in an if
You've got a bunch of other problems to consider as you fix this too
NinjaKite is called every frame. You reset your timer at the start of NinjaKite
Consider using Mathf.Clamp on tmpY. Its more readable
Using common coding conventions around indentation and capitalisation will help you a lot in the long run
Thx for this answer, $$anonymous$$e contains a bit more details and code, so the user at his / her level could easily understand it, but I appreciate the fact you're spreading coding conventions, always a great sight to see ;)
Thanks for the answer! tried it out, out and it fixed the issue of going to -infinite, but it still goes out of screen, and the player gets killed now, not crashing at least... :)
Using the clamp i noted that the char is moved automatically to the lowest point in the clamp, i tried putting it in the middle of the screen and it stayed there shaking as if something was pulling it down.
So i still cant seem to make it fly on screen or take any real input, because it's moved even if i don't touch anything.
PS: on the indentation, it got messed up after copypasting and i was lazy to fix it... sorry... :S PPS: Thanks for your advice!
Did you want to post new code with the fixed while loop? Which solution did you pick?
Indenting is of special importance here, because we don't have the built in compiler tools to help tell us which set of braces we are in.
Here is how I would code using a coroutine. $$anonymous$$ey points to note are
If the player is already flying then getting a new kite will reset the timer to 0. I used the string form of StartCoroutine to allow this. There are other ways to configure it
Nija$$anonymous$$ite is a coroutine, its return type is now IEnumerator
There is a yield return null inside your while loop. This means the method will stop here and wait until next frame to resume execution
I've set the transform position directly ins$$anonymous$$d of using Translate. Its easier to apply the clamp this way
Enjoy
public bool kiteOn = false;
public float kiteTime = 4.0f;
public float kiteSpeed = 1.0f;
void Update(){
if (kiteOn) {
StopCoroutine("Ninja$$anonymous$$ite");
StartCoroutine("Ninja$$anonymous$$ite");
kiteOn = false;
}
}
private IEnumerator Ninja$$anonymous$$ite() {
float timer = 0.0f;
while (timer < kiteTime) {
timer += Time.deltaTime;
float newY = $$anonymous$$athf.Clamp(transform.position.y + kiteSpeed * Input.GetAxis("Vertical")* Time.deltaTime,-1,1);
transform.position = new Vector3 (transform.position.x, newY, transform.position.z);
yield return null
}
}
Your answer
Follow this Question
Related Questions
How make 2d player only able to fly / jump for 3 seconds if not on the ground? 1 Answer
One-way Platforms (2D) 1 Answer
Which language should we use ? 1 Answer
Unity lighten 3d objects in 2d game 0 Answers
Death Zone Difficulties 1 Answer