- Home /
Why does my character can't touch the terrain?
Now I am writing a control code, and my code doesn't use the Velocity that some tutorials used. It use character.transform.position and change it to move character. It works well, but when I begin applying gravity, the character fall through the terrain, even I used the controller.isGrounded, it fall off the terrain. I have checked it already, like this:
if (!controller.isGrounded)
{print("In air"); character.transform.position.y -= 3;}
else print ("On ground"); // and some stuff to disable the gravity
And, when I play, the character fall off, and the console screen only show "In air" message, that mean the Unity's isGrounded doesn't work correctly.
My terrain has a terrain collider, my character has rigibody, CharacterController and my own script. There are no trigger is ticked, I checked it. And I disable Unity's default Gravity in Rigibody, I use my own gravity code (like above). That is my status now.
Could you please help me? Thank you for reading.
Answer by raybarrera · Oct 20, 2013 at 10:00 AM
I believe your controller is just falling to fast to even register the collision.
You are subtracting 3 units per frame, so from one frame to the next, your character could have gone entirely through the terrain, and it would never detect a collision.
Try smoothing your transform
character.transform.position.y -= 3 * Time.deltaTime;
like so, and you should be fine.
Thank you for replying my question, but somehow my script doesn't work, my character is still falled. Look like I have to change the way I write the code, maybe rewrite all of it? Anyway, thank you very much. I hope you will keep helping me and every one.
You'll probably have to post the whole script for us to help you more effectively.
You were right, my character "fall" too fast, or you can say that is not "falling", that is "teleporting". I changed the code, like this:
character.transform.position.y -= 3 * Time.deltaTime/const;
First, I choose the const to be 10, and it work! So I reduced it, and the smallest value make the code's right is 7.
Hi @golemsmk, good to hear you have a solution sorted. I do have one question purely for interest sake: Why are you dividing by a const ins$$anonymous$$d of changing the number 3?
To clarify my question, here's my understanding. 3 = your gravity value. Thus higher gravity values = stronger gravity = faster falling.
Time.deltaTime = the time since the last frame. Used to allow you to make calculations based upon real time and not at Frames Per Second.
const = it appears you are using the const to change the rate time passes. Thus a value of 10 = 10 times slower than real time.
So in your example you are saying: apply a gravity of 3, over normal time divided by 7. In other words: apply gravity 7 times slower than normal speed.
Is this your intention?
In first time, my code is:
character.transform.position.y -= 3*gravity/const;
Because I need my gravity value can be control when I need, stronger, or weaker, or disable it, so I have a gravity variable. About const, it is just a variable, and I dont want to find a variable in the hunders of code line. So I set it in the top of the script and I can change it more easier. Nothing more.
I just use the code over there when the character position higher than the floor just equal or less than 1, in otherwise, the character "teleport", so it does not make me worry about a slower speed. Anyway, thank you for carrying about my problem.
Answer by duclaw · Oct 19, 2013 at 10:26 PM
try if(!controller.isGrounded) {print("in air"); character.transform.position -=3;} else {print("on ground")}
This is invalid because it breaks typing constraints. Also format your code, please.
In general, it's the right idea, though - you need to negate the "isGrounded" condition by using the ! operator.
Oh, I am sorry. $$anonymous$$y bad, I type (!isGrounded) in my code, but when I copy I have deleted something to have a clear example code for you, so look like I deleted the "!" in front of the "isGround", that's my mistake. Sorry, but as I said before, there is alway just the "In air" message are showed ( I set the position of character higher than the terrain), and when I play, he falls off without "On Ground" message.
@hoeloe if you do know how to code then you won't say such
@duclaw: I know exactly how to code. Your code is not formatted at all, making it difficult to read, and you wrote this line: character.transform.position -=3
which performs integer subtraction of a Vector3, breaking typing constraints.
As for solving your problem, I think we need to see what code you're using to "disable gravity" - it's completely relevant and you've omitted it. Also double check - are there constraints applied to your Rigidbody?
About my gravity code, it's very simple, I just change the jump speed's value into its negative when I need gravity. This is my code (this time I don't delete anything, just Ctrl+C and Ctrl+V):
function Gravity()
{
if (!jumpingUp)
{
if (controller.isGrounded)
{
curJumpSpeed = 0 ;
}
else curJumpSpeed=-jumpSpeed;
}
} jumpingUp is a boolean var that true when player is incresing its position y, and if not, it will be false. This code mean, if player in not jumping up, there are 2 situations, there will be no gravity if he is on the ground, anh if he isn't on the ground, that mean he is falling down and enable the gravity.
$$anonymous$$aybe he falls too fast that the isGrounded can't activate?
Answer by Ellandar · Oct 20, 2013 at 10:02 AM
First, start with following EVERY step in this post: http://answers.unity3d.com/questions/147687/Checklist-Object-or-Character-is-falling-through-the-floor.html It's my holy grail reference if I run into the problem of things falling through the ground.
If the problem is still there then it's probably your method of grounding your character. I'm going to assume that your Rigidbody is just there for collision detection. If not, and there's physics involved then transform.position updates are never going to work nicely with a character controller added.
Can I suggest you handle gravity and ground detection along these lines? Don't use .IsGrounded, use your own script that does something like this (untested code! may work):
C# code - assumes root of your characters GameObject is at the base (not in the middle);
int Gravity = 3;
if(!CustomIsGrounded && HigherThanGravity)
{
print("In air"); character.transform.position.y -= Gravity;
}
if(CustomIsGrounded)
{
//onground code
}
if(!CustomIsGrounded && !HigherThanGravityUnit)
{
float groundHeight = Terrain.activeTerrain.terrainData.GetHeight(character.transform.position.x, character.transform.position.z);
print("In air"); character.transform.position.y = groundHeight;
}
private bool CustomIsGrounded()
{
// Use your rigidbody to detect for a collision with the ground, or check that your character position.y = groundHeight. There's lots of examples in answers for these.
}
// If the character is less than 1 unit of "Gravity" off the ground, then return false;
private bool HigherThanGravityUnit()
{
float groundHeight = Terrain.activeTerrain.terrainData.GetHeight(character.transform.position.x, character.transform.position.z);
if((character.transform.position.y - groundHeight) < Gravity)) return false;
return true;
}
Or if you are happy to make slightly bigger changes, change gravity to apply over time (multiply by Time.deltaTime), and this will smoothly drop your character to the ground instead of stepping it down in large increments. It will also alleviate the need for the "HigherThanGravityUnity" code.
Just read that @raybarrera added code that matched my final statement. I'd recommend using that and marking his as the correct answer. $$anonymous$$y method was just trying to stick to your existing gravity implementation, which come to think of it wasn't a good approach for me to take. :)
Still follow the collision stuff if your character is still falling through the ground after applying raybarrera's approach.
I checked all the list in that link before ask (I found it by google). I tried all, and, no effect at all. Even your code here is not working. So with a lot of error like this, I think I have to rewrite all my code, just 2 day and I have 2 big error, that's a bad news, right? And, thank you for helping me.
Wait. Your code has errors? Or do you just mean it's not working as you expect? There is an important distinction between the two. An error is a specific concept that means there was something wrong with your code preventing it from compiling correctly, or causing it to execute illegally. Not working as you expect, on the other hand, means it is compiling and running without problems, but the behaviour is different to what you intended.
Answer by golemsmk · Oct 21, 2013 at 09:17 AM
Thank you everyone. Now I know why. You were right, my character "fall" too fast, or you can say that is not "falling", that is "teleporting". I changed the code, like this:
character.transform.position.y -= 3 * Time.deltaTime/const;
First, I choose the const to be 10, and it work! So I reduced it, and the smallest value make the code's right is 7.
You helped me a lot, thank you very much. I hope I can see you later.
Sorry, I forgot. I will comment in raybarrere's answer and mark it correct.