Search code examples
androidunity-game-engineaccelerometer

Using Android accelerometer y axis falls through terrain - Unity3D


This works much better, thank you. However, it still does not work very well. While I don't go completely through the terrain, the FP controller seems to hover just below the terrain. Adding a +10 helps, but there is another strange issue: I have the camera set up as a child of the FP controller, at 0,0,0. When the game begins to run, the Y value in the transform of the controller window goes steadily down, in minus numbers, while the camera Y value goes steadily up, in the positive direction. The Y values are mirrored. Any ideas of what is going on?

void Update () {
    moveX = Input.acceleration.x * 1;
    moveY = Input.acceleration.y * 1;
    moveZ = (1+ (Input.acceleration.z)); 
    transform.Translate (0, 0, 0); //transform.translate Moves the transform in the direction and distance of translation

    temp = transform.position;     //temp = the position of the transform in world space. World Space: the absolute XYZ coordinates of all objects
    temp.y = terrainY;             //y component of Vector3 (float)
    transform.position = temp;     //put the position of the transform in world space back into temp
    terrainY = Terrain.activeTerrain.SampleHeight(temp); //Sample.height Samples the height at the given position defined in world space

    temp2 = transform.position.y; //this shows transform.position.y axis is the same as terrainY, but not the same value as shown in the inspector

        if (moveZ >= 0.055 && moveZ >= -0.1) { 
        zeroZFlag = 1;          
        if(moveZ >= 0.041){
            moveZ = moveZ*10;     //multiply by 10 to make it faster when going forward
                if (moveY >= 0) {        

                transform.Translate (moveX,terrainY + 10,moveZ); 
                //transform.translate needs to be three floats. So the middle one needs to be the y value of the top of the terrain
                    }
                    if (moveY < 0){
                transform.Translate (moveX,terrainY,-moveZ);
                    }
        }

I have added to my code as suggested but am still having trouble getting the first person controller to stay on the same y-value as the terrain. In the following iteration of code, the First person y value leaves the world entirely and goes up forever. My code uses `transform.Translate (moveX,terrainY,moveZ); to move the FP controller around, where moveX and moveY are acceleration values and terrainY theoretically should be the actual value of the Y-axis as shown in the transform box. I think that the first issue is that I am mixing acceleration values (X,Z) with a terrain transform for Y, so different meaning to the values. BTW X and Z axis move very well with the accelerometer with this code, but I will change everything if necessary!

I am not sure what kind of float value operation translate.transform does. The manual states that it returns in the space.world, but does it move by the number of units or position?

Here is my new code, and thank you in advance for help:

public float terrainY;

// y axis falls through terrain
// travels through walls even though collider is set

void LateUpdate (){
    //terrainY = Terrain.activeTerrain.SampleHeight (transform.position);
    }
void Update () {
    moveX = Input.acceleration.x * 1;
    moveY = Input.acceleration.y * 1;
    moveZ = (1+ (Input.acceleration.z)); 
    transform.Translate (0, 0, 0);
    terrainY = Terrain.activeTerrain.SampleHeight (transform.position);
    if (moveZ >= 0.055 && moveZ >= -0.1) { 
        zeroZFlag = 1;          
        if(moveZ >= 0.041){
            moveZ = moveZ*10; //multiply by 10 to make it faster when going forward
                    if (moveY >= 0) {
                transform.Translate (moveX,terrainY,moveZ); 
                //transform.translate needs to be three floats. so the middle one needs to be the y value of the top of the terrain
                    }
                    if (moveY < 0){
                transform.Translate (moveX,terrainY,-moveZ);
                    }

My code causes me to go through and under my terrrain in Unity 3D because the y axis is always zero. In this world, x-axis is left/right and z is depth. Y axis is up/down and shold follow the mountains, hills, valleys in the terrain. However, it just goes through, at 0 height. Does anyone know what variable/class should be in the y-axis spot instead of the "0" I have there? Thanks in advance!

public class Movement2 : MonoBehaviour {
public float moveX = Input.acceleration.x;
public float moveY = Input.acceleration.y;
public float moveZ = Input.acceleration.z;
public float Speed = 20.0f;
public int zeroZFlag;

void Update () {
    moveX = Input.acceleration.x * 1;
    moveY = Input.acceleration.y * 1;;
    //moveZ = Mathf.Abs(1+ (Input.acceleration.z) * 20); 
    moveZ = (1+ (Input.acceleration.z)); 
    transform.Translate (0, 0, 0);

    if (moveZ >= 0.055 && moveZ >= -0.1) { zeroZFlag = 1;                       
                    if (moveY >= 0) {
            transform.Translate (moveX,0,moveZ);
                    }
                    if (moveY < 0){
            transform.Translate (moveX,0,-moveZ);
                    }
     else {
     zeroZFlag = 0;  
     }
    }

Solution

  • Try using Terrain.SampleHeight(), it returns the height of the terrain with a given X and Z coordinate. Update its Y position to the height of the terrain every Update().

    Reference: http://docs.unity3d.com/ScriptReference/Terrain.SampleHeight.html.

    EDIT 1:
    The reason your FP controller always goes up forever is because you keep translating it with a Y value.

    transform.Translate(moveX, terrainY, moveZ)
    // this way you keep adding terrainY value to the Y position
    // thus it always goes up and will never end
    

    While you need your FP controller to be constantly the same Y position with the terrain. You should instead modify the position of Y directly.

    Vector3 temp = transform.position;
    temp.y = terrainY;
    transform.position = temp;
    

    EDIT 2:
    I try my best to help you see through your code:

    void Update () {
        moveX = Input.acceleration.x * 1;
        moveY = Input.acceleration.y * 1;
        moveZ = (1+ (Input.acceleration.z)); 
        transform.Translate (0, 0, 0); // why do you need this? this basically does nothing
    
        // you should get terrain height first to be used as temp.y below
        terrainY = Terrain.activeTerrain.SampleHeight(transform.position);
        temp = transform.position;
        temp.y = terrainY + 10; // you said +10 helped, so I put it here
        transform.position = temp;        
    
        if (moveZ >= 0.055 && moveZ >= -0.1) { 
            zeroZFlag = 1;          
            if(moveZ >= 0.041){
                moveZ = moveZ*10;
                if (moveY >= 0) {        
                 // here I think you shouldn't move the Y anywhere,
                 // because you've updated position of Y in every update frame   
                 // so you only need to move X and Z due to device tilt   
                    transform.Translate (moveX,0,moveZ); 
                }
                if (moveY < 0){
                    transform.Translate (moveX,0,-moveZ);
                }
            }