How can i get what angle my 2d planes nose is flying at?

im trying to get my gravity to effect my plane harder if the nose is flying straight up and hitting the collider, its bouncing off nicely at an angle but gets stuck when flying straight up, i want to increase the gravity if its hitting with the nose straight up so it will push the plane away more, would also be nice to lower the nose a bit when it stalls, but i cant work out how to do this. the rot and rotate variables im using for control dont seem to be correct.

here is da code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlaneController : MonoBehaviour
{
    Rigidbody2D rb;
    [Tooltip("World units per second.")]
    public float moveSpeed;
    [Tooltip("Degrees per second.")]
    public float rotateAmount;
    float rot;
    bool stalling = false;
   
    private Renderer[] renderers;
    private bool isWrappingX = false;

    SpriteRenderer spriteRenderer;

    void Start()
    {
        renderers = GetComponentsInChildren<Renderer>();
    }

    private void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
        spriteRenderer = GetComponent<SpriteRenderer>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            Vector3 mousePos = Input.mousePosition;
            mousePos.z = 1;    // gotta cast a little bit into the scene!

            mousePos = Camera.main.ScreenToWorldPoint(mousePos);

            if (mousePos.x < 0)
            {
                rot = rotateAmount;
            }
            else
            {
                rot = -rotateAmount;
            }

            transform.Rotate(0, 0, rot * Time.deltaTime);
        }
        else
        {
            SetFlipY();
        }

        if (stalling)
        {
            rb.gravityScale = 15;
            stalling = false;
           
            StartCoroutine(StallTime());
            if (transform.right.x > 0 && transform.right.x < 5) rb.gravityScale = 50;
           
           
                    
        }

    }

    private void FixedUpdate()
    {
        rb.velocity = transform.right * moveSpeed;
        ScreenWrap();
    }

    void SetFlipY()
    {
        // I'm not going to base it off of rot but rather off of the
        // sign of the x component of the transform.right vector.
        bool flipy = transform.right.x < 0;
        spriteRenderer.flipY = flipy;
    }

   void ScreenWrap()
    {
        bool isVisible = CheckRenderers();

        if (isVisible)
        {
            isWrappingX = false;
            return;
        }

        if (isWrappingX)
        {
            return;
        }

        Vector3 newPosition = transform.position;

        if (newPosition.x > 1 || newPosition.x < 0)
        {
            newPosition.x = -newPosition.x;
            isWrappingX = true;
        }

        transform.position = newPosition;
    }

    bool CheckRenderers()
    {
        foreach (Renderer renderer in renderers)
        {
            if (renderer.isVisible)
            {
                return true;
            }
        }

        return false;
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "HeightBorder")
        {
            stalling = true;
        }
    }

    IEnumerator StallTime()
    {
        //float randomTime = Random.Range(3f, 10f);
        yield return new WaitForSeconds(0.5f);
        rb.gravityScale = 0;
    }
}

You can get the rotation from the transform’s eulerangles:

float angle = transform.eulerAngles.z;

Play with it because it’s likely to be -180 to 180 I think, and I’m not sure which is where is what direction.

thanks again Kurt!!!

can i ask, did you look at documentation for that?..or is it something you just knew?

I know that the Transform contains information about the position, rotation, scaling and parenting… you kinda wanna know that part cold.

The details about the API used to get the rotation are forgettable, but in this case I happened to remember it because I use it frequently enough.

great the stall is working perfectly but i cant work out how to drop the nose. any tips? please

To rotate an object using RigidBody physics you add torque. Check out https://docs.unity3d.com/ScriptReference/Rigidbody2D.AddTorque.html

2 Likes

What Praetor said is spot on but because we chatted the other day, I think what you want is more this:

Based on which way your nose is facing (left/right), you need to effectively cause either left or right input, the one that brings your nose down.

This calls into mind your script above, and makes a case for breaking the code up a little bit.

I’m talking about line 34 to line 50 above.

Right now you gather the input, decide left or right and immediately act upon it.

Instead do this:

gather the input
decide if there is either no input, left input, or right input and set a variable accordingly
----- placeholder empty spot for future code ----
now look at that variable and act upon the input.

NOW… once you have tested the above changes and 100% confident your game works properly, its time to decide if you are stalling.

IF you are stalling, and your nose is facing left, then you override the input with LEFT, which is nose down
If you are stalling and your nose is facing right, then you override the input with RIGHT, which is nose down

And while the stall detection can go somewhere else, the actual check of the stalling variable would occur where I wrote “placeholder” above.

By making decisions and setting variables, you define a very clear flow of data through the game loop, and this enables you to move parts around and do interesting things like couple the stalling effect to the normal control inputs the way I just proposed.

1 Like

Thanks Kurt!!!

Thanks PraetorBlue

Can somebody please help me break down and understand this code?

if (Input.GetMouseButton(0))
        {
            Vector3 mousePos = Input.mousePosition;
            mousePos.z = 1;    // gotta cast a little bit into the scene!

            mousePos = Camera.main.ScreenToWorldPoint(mousePos);

            if (mousePos.x < 0)
            {
                rot = rotateAmount;
            }
            else
            {
                rot = -rotateAmount;
            }

            transform.Rotate(0, 0, rot * Time.deltaTime);
        }

if (Input.GetMouseButton(0)) - ok if the left mouse button is clicked, 1 is right, 2 is the middle button.

Vector3 mousePos = Input.mousePosition; - creating a variable called mousePos which references a Vector3 (why a vector3? I only need x and y, why isnt a Vector2 used? anyway, Vector3 mousePos = where the mouse is on the screen.

mousePos.z = 1; - moves the mousePos.z position (view depth on a 2d game?) but why is this needed for mouse movement? why does the depth matter? i mean its something you dont really see in the game.

mousePos = Camera.main.ScreenToWorldPoint(mousePos); i googled Camera.main.ScreenToWorldPoint and in the doc it said "Transforms a point from screen space into world space, where world space is defined as the coordinate system at the very top of your game’s hierarchy.

World space coordinates can still be calculated even when provided as an off-screen coordinate, for example for instantiating an off-screen object near a specific corner of the screen." - im sorry i just dont understand this? am i just thick and will never be a programmer? what is the best way to learn all this stuff without bugging people? Is there a course online, i dont mind paying if i have to.

but anyway i think that the line is just capturing where the mouse is on the screen?

then:

if (mousePos.x < 0)
{
rot = rotateAmount;
}
else
{
rot = -rotateAmount;
}

this if just checks if the position is less than 0, left of the middle of the screen? add rotate
else minus rotate.

finally

transform.Rotate(0, 0, rot * Time.deltaTime);

this actually rotates the object,
0 0?
0 on x
0 on y
rot on z?

rot = rotateAmount which is the number of degrees per second stipulated.

  • deltaTime - i know you need deltatime when moving stuff, but why escapes me.

sorry for the long post and from the heart…thanks guys

I assumed you wrote it that way.

As I noted on our very first exchange, it will fail as soon as your camera is not located at world x == 0.

A far simpler approach is this:

        if (Input.GetMouseButton(0))
        {
            Vector3 mousePos = Input.mousePosition;

            if (mousePos.x < Screen.width / 2)
            {
                rot = rotateAmount;
            }
            else
            {
                rot = -rotateAmount;
            }

            transform.Rotate(0, 0, rot * Time.deltaTime);
        }

That approach cares nothing about camera, just asks “is the mouse position touching the left half or the right half of the screen?” which is all you care about.

My comments to this effect can be found in our first exchange here, in paragraph 6:

https://discussions.unity.com/t/811649/2

“I assumed you wrote it that way.” so you could use a vector2?

That’s irrelevant. You only care what the mouse X is, right? I mean that’s how you wrote it the first time.

You could just take only the mousex:

float mouseX = Input.mousePosition.x;

if (mouseX < Screen.width / 2)
{
  // left side
}
else
{
  // right side
}

Alternatively, most games implement some kind of button controls, but touchscreen buttons can also be annoying, so this left/right half of the screen approach is still pretty legit.