Smoothly attaching an object

Hello everyone, my goal here is to have my player object rotate around the first asteroid object it comes in contact with, I have a player object with a rigidbody2d and a circle collider 2d, and my asteroid which has a rigidbody2d, collider2d, and wheel joint 2d.

I have it somewhat working, as my player object does indeed attach and rotate around the other object, but the problem I’m having is that it is not a smooth transition at all. My player hits the object, and then slingshots to the anchor point. I’ve tried different ways to attach it smoothly to no avail.

    void OnCollisionEnter2D(Collision2D coll)
    {
        if (coll.gameObject.tag == "Asteroid")
        {
            mOnAstroid = true;
            mAsteroid = coll.gameObject;
            mAsteroidCenter = mAsteroid.transform;
            mAsteroidRadius = mAsteroid.GetComponent<CircleCollider2D>().radius;
            mAsteroidJoint = mAsteroid.GetComponent<WheelJoint2D>();

            mAsteroidId = mAsteroid.GetInstanceID();
           
         
        }

    }
    void FixedUpdate()
    {
        if (mOnAstroid == true && mAsteroidId != mLastAsteroidId)
        {
           
            mAsteroidJoint.anchor = (new Vector2(mAsteroidRadius, 0 ));
           
            mAsteroidJoint.connectedBody = mPlayerRigBody;

           
           

        }
    }

Thanks

After trying everything I can think of with the connected anchor, and anchor; I’m perplexed.

WheelJoint2D seems like an odd choice. Have you tried a Spring or Distance joint instead?

I experimented with the distance joint, but I couldn’t get the rotation around the object to work correctly. I figured the wheel joint would be the simplest way to simulate gravity of sorts since my “asteroids” are slowly spinning. The goal is for the player to spin around th sides of the astroid when it comes in contact with it - at the astroid rotation speed.

Any particular reason you need a joint / the physics system at all for that or was it just the best solution you could come up with? It seems like it could be solved pretty easily with pure math if all you’re trying to do is orbit.

I did have a setup without joints using transform that I couldn’t get working 100%, the player would either hit the asteroid and start rotating and continue to fall off the screen, or it would hit, start rotating, and fall to the bottom of it and never move. That’s why I started experimenting with the wheel joint.

     void OnCollisionEnter2D(Collision2D coll)
     {
         if (coll.gameObject.tag == "Asteroid")
         {
             mOnAstroid = true;
             mAstroid = coll.gameObject;
             mAstroidCenter = mAstroid.transform;
         }
     }
     void Update () {
         if (mOnAstroid == true)
         {
             //Rigidbody2D rig = GetComponent<Rigidbody2D>();
             //rig.gravityScale = 0;
             transform.RotateAround(mAsteroidCenter.position, Vector3.up, 80.0f * Time.deltaTime);
             Vector3 desiredPosition = (transform.position - mAsteroidCenter.position).normalized * 2.0f + mAsteroidCenter.position;
             transform.position = Vector3.MoveTowards(transform.position, desiredPosition, Time.deltaTime * 0.5f);
         
         }
   
     }
     void Update () {
         if (mOnAstroid == true)
         {
             Rigidbody2D rigbody = mplayer.GetComponent<Rigidbody2D>();
             Vector3 relativePos = (mAstroidCenter.position + new Vector3(0, 1.5f, 0)) - transform.position;
             Quaternion rotation = Quaternion.LookRotation(relativePos);
             Quaternion current = transform.localRotation;
             transform.localRotation = Quaternion.Slerp(current, rotation, Time.deltaTime);
             transform.Translate(0, 0, 3 * Time.deltaTime);
            // transform.RotateAround(mAstroidCenter.position, Vector3.up, mOrbitSpeed * Time.deltaTime);
           
         
         }
   
     }

I didn’t backup the method I had that caused it to stick, but both of the above methods failed to provide any sort of “stick” to the asteroid itself, they just continued to fall while tumbling uncontrollably; which as it’s 2D, doesn’t work.

I’m sure my method and or math is wrong, but I couldn’t figure out a decent solution

So I think this is what you’re looking for? (The colliders are bigger than the graphic just for clarity)

I just used Transform.RotateAround for the orbits once they attach and set the rotation rate to the same as the asteroid’s. You could also simply parent the ship to the asteroid (ship.SetParent(Asteroid)) and remove all of your movement and rotation code in that state. That’s even easier but I don’t know how your scene is setup so I didn’t want to make that assumption.

Here’s the two scripts:

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

public class AsteroidController : MonoBehaviour
{
   public float rotationSpeed = -90.0f;

   protected void Update()
   {
     transform.Rotate(0.0f, 0.0f, rotationSpeed * Time.deltaTime);
   }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShipController : MonoBehaviour
{
   public Vector3 direction;
   public float speed;

   protected bool orbiting = false;
   protected Transform asteroid = null;
   protected AsteroidController asteroidController = null;

   protected void OnCollisionEnter2D(Collision2D collision)
   {
     if(collision.gameObject.name == "Asteroid")
     {
       orbiting = true;
       asteroid = collision.gameObject.transform;
       asteroidController = asteroid.GetComponent<AsteroidController>();

       CircleCollider2D collider = GetComponent<CircleCollider2D>();
       collider.enabled = false;
     }
   }

   protected void Update()
   {
     if (orbiting == true)
     {
       transform.RotateAround(asteroid.position, Vector3.forward, asteroidController.rotationSpeed * Time.deltaTime);
     }
     else
     {
       transform.Translate(direction * speed * Time.deltaTime, Space.World);
     }
   }
}

Hope that helps!

That’s exactly what I was failing to accomplish!

Unfortunately, even after removing anything that could interfere with it, it doesn’t seem to want to work for me.

This is using the transform above

This is setting the players parent to the object

Thank you for your help thus far, it’s been awhile since I’ve used unity and I feel like a moron.

Can you post your scripts in their entirety?

Brand new project with nothing else added but those two scripts, just to make sure nothing else was interfering with it.

Attached to Player Object

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

public class AstroidBehavior : MonoBehaviour {


    public Vector3 mDirection;
    public float mSpeed;


    protected bool mOrbiting = false;
    protected Transform mAsteroid = null;
    protected AstroidController mAsteroidController = null;



    protected void OnCollisionEnter2D(Collision2D collision)
    {
        if(collision.gameObject.tag == "Asteroid")
        {
            mOrbiting = true;
            mAsteroid = collision.gameObject.transform;
            mAsteroidController = mAsteroid.GetComponent<AstroidController>();

            CircleCollider2D collider = GetComponent<CircleCollider2D>();
            collider.enabled = false;

        }
    }

   
    // Update is called once per frame
    void Update () {

        if(mOrbiting == true)
        {
            transform.RotateAround(mAsteroid.position, Vector3.forward, mAsteroidController.mRotationSpeed * Time.deltaTime);
            transform.SetParent(mAsteroid);
        }
        else
        {
            transform.Translate(mDirection * mSpeed * Time.deltaTime, Space.World);
        }
   
    }




}

Attached to asteroid object

using UnityEngine;
using System.Collections;

public class AstroidController : MonoBehaviour {

    public float mRotationSpeed = -90.0f;
    // Use this for initialization
    void Start () {
   
    }
   
    // Update is called once per frame
    void Update () {

        transform.Rotate(0.0f, 0.0f, mRotationSpeed * Time.deltaTime);
    }
}

I think if you just delete this line:

  transform.SetParent(mAsteroid);

You should be good to go. You should either parent it or rotate around it, not both. If you want to set the parent, do it in the collision, not every update.

EDIT: Since you’re going to be using rigidbody physics, I’d recommend parenting it. That way you’re not messing with the transforms directly once you figure out your movement code. To do that, just remove the transform.RotateAround() line and move the transform.SetParent(mAsteroid) into the collision check.

eeerrm, I was messing around with it and forgot to comment out the SetParent when I copy and pasted it on here. That wasn’t originally in the script, the images above show what happens when either of those are commented out, with the SetParent image having it set inside OnCollisionEnter2D

Took a while but I’ve got it: You have gravity enabled. That’s why in both gif’s they’re constantly falling down. Disable the gravity by setting gravity scale to 0 for that specific ship ridigbody, or disable gravity universally in the project settings. If you want gravity, set the gravity scale via script on collision where you disable the collider in the collision check.

Oh man, that worked amazingly…thank you very much!