3
\$\begingroup\$

I'm working in a project with Unity 2d where player walks on a small planet. I try to use some code from youtube tutorial to apply gravity to my planet.This code consists of two parts, Attractable and Attractor. Attractables are used on objects that are drawn and Attractors placed on planets. I use simple platformer move script to move my player. But I found that if my player moves in one direction and suddenly changes the other direction, my player can "fly". I think this happened because my players moved at the wrong angle. I use my Attractor script to constantly applying force towards the center of the planet every update, but my player still fly and doesn't get pulled down unless if i run to another dirrection, then my player will get pulled again. I'm confused because my player is supposed to be pulled every update, but it seems like it's not being pulled.

My problem look like this

in Attractor script, it just find all object inside Circle area with Physics2D.OverlapCircleAll and then call Attract function from object with Attractable script. The Attractor code look like this:

    void Update()
    {
        SetAttractedObjects();
    }

    void FixedUpdate()
    {
        AttractObjects();
    }

    void SetAttractedObjects()
    {
        AttractedObjects = Physics2D.OverlapCircleAll(planetTransform.position, effectionRadius, AttractionLayer).ToList();// can be optimized
    }

    void AttractObjects()
    {
        for (int i = 0; i < AttractedObjects.Count; i++)
        {
            AttractedObjects[i].GetComponent<Attractable>().Attract(this);
        }
    }

And inside the Attractable script, it has Attract function, that apply some force to object rigidbody. This is the function called from the previous Attractor script.

public void Attract(Attractor artgra)
    {
        Vector2 attractionDir = (Vector2)artgra.planetTransform.position - m_rigdibody.position;
        m_rigdibody.AddForce(attractionDir.normalized * -artgra.gravity * 100 * Time.fixedDeltaTime);
        if (currentAttractor == null) 
        {
            currentAttractor = artgra;
        }

    }

This script also has, a RotateToCenter function which ensures the player is always facing the planet. This function is called from the Update function.

void RotateToCenter() 
    {
        Vector2 distanceVector = (Vector2)currentAttractor.planetTransform.position - (Vector2)m_transform.position;

        float angle = Mathf.Atan2(distanceVector.y, distanceVector.x) * Mathf.Rad2Deg;
        m_transform.rotation = Quaternion.AngleAxis(angle + 90,Vector3.forward);
    }

And i use this movement code that add some velocity to my rigidbody to move my player;

void Update( )
{
     Move();
}

void Move(){
     scale=transform.localScale;
     if (Input.GetKey(KeyCode.A))
     {
          isMoving=true;
          rb.velocity = transform.right * -moveSpeed;
          scale.x=-1;
     }
     else if (Input.GetKey(KeyCode.D))
     {
          isMoving=true;
          rb.velocity = transform.right * moveSpeed;
          scale.x=1;
          
     }
     else
     {
        rb.velocity = new Vector2(0f, 0f);
        isMoving=false;
     }
     transform.localScale=scale;
     animator.SetBool("isRunning",isMoving);
}

I think the problem is in the Attract function because my player doesn't seem to be pulled to the center of the planet, but when I try to debug it, it seems that this function is still being called every update, even when my player is hovering in the air. Anyone know how to solve this?

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Your platformer control script is assigning a value to Rigidbody2D.velocity directly, overruling any forces applied by the attraction scripts and preventing them from accumulating frame over frame until you fall at terminal velocity. If you want to combine movements from multiple scripts, you should apply forces or accelerations, rather than replacing the body's entire velocity — that just throws out physics state that your other script worked hard to apply! \$\endgroup\$
    – DMGregory
    Aug 25 at 11:51
  • \$\begingroup\$ seems to work, but when my player runs too fast, my player starts "flying" as before, should I put a speed limit? \$\endgroup\$
    – Kon
    Aug 25 at 14:03
  • \$\begingroup\$ If you found a solution that works for you, post it as an Answer below. If you need help solving a new problem, edit your question to ask about that. We don't do Q&A in the comments. \$\endgroup\$
    – DMGregory
    Aug 26 at 12:11
  • \$\begingroup\$ oh, sorry about it \$\endgroup\$
    – Kon
    Aug 26 at 12:45
  • \$\begingroup\$ Make the planet bigger i would reccomend! \$\endgroup\$
    – LiamBeran
    Aug 29 at 14:35
0
\$\begingroup\$

So thanks for the suggestions in the comments, I have solved this problem. Based on the solution in the comments, I changed the way my character moves using addForce. The code look like this:

void Move(){
     scale=transform.localScale;
     
     if (Input.GetKey(KeyCode.A))
     {
          isMoving=true;
          Vector2 movement = transform.right.normalized * -moveSpeed;
          rb.AddForce(movement);
          scale.x=-1;
     }
     else if (Input.GetKey(KeyCode.D))
     {
          isMoving=true;
          Vector2 movement = transform.right.normalized * moveSpeed;
          rb.AddForce(movement);
          scale.x=1;
     }
     else
     {
          rb.velocity = new Vector2(0f, 0f);
          isMoving=false;
     }

And then i call this function from FixedUpdate function. It works well at low moveSpeed, but if my moveSpeed is too big, my players can be "thrown" from the planet. But it's fine for me.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ The reason you get thrown off at higher speeds, is that you are moving faster than orbital velocity, either increase the gravty, or make the planet bigger so you need a higher speed to get thrown off \$\endgroup\$
    – Ferrybig
    Aug 26 at 13:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.