big problem with raycasts and collider.bounds

i am making a game partially inspired by geometry dash. as the character is a geometric shape, i need it to rotate at the same angle as the surface. i have some code relying on raycasthit2d.normal for that but there is one problem. collider.bounds is pretty useless for this as it gets affected by rotation. this causes some offsets which are super annoying. this means i get weird bugs like this(the white line is the raycast and extra height is 0.05):

9855432--1419231--upload_2024-5-26_11-6-26.png

my code is 100% done except for this annoying bug. my code:

private void Rotate()
    {
        RaycastHit2D raycastHit;

        Quaternion origRot = transform.rotation;

        float raycastHeight = boxCollider.bounds.extents.y + extraRotationRaycastHeight;

        // i added this line which sets the rotation to the previous rotation due to the fact that i use quaternion.rotatetowards for smooth rotation
        transform.rotation = rotation;

        if (isFacingRight)
        {
            raycastHit = Physics2D.Raycast(new Vector2(boxCollider.bounds.center.x + boxCollider.bounds.extents.x, boxCollider.bounds.center.y), -transform.up, raycastHeight, groundLayer);
            Debug.DrawRay(new Vector2(boxCollider.bounds.center.x + boxCollider.bounds.extents.x, boxCollider.bounds.center.y), -raycastHeight * transform.up);
        }
        else
        {
            raycastHit = Physics2D.Raycast(new Vector2(boxCollider.bounds.center.x - boxCollider.bounds.extents.x, boxCollider.bounds.center.y), -transform.up, raycastHeight, groundLayer);
            Debug.DrawRay(new Vector2(boxCollider.bounds.center.x - boxCollider.bounds.extents.x, boxCollider.bounds.center.y), -raycastHeight * transform.up);
        }

        transform.rotation = origRot;

        rotation = Quaternion.FromToRotation(Vector3.up, raycastHit.normal);

        rotation.x = 0;
        rotation.y = 0;
    }

the part of the code in fixedupdate that actually rotates the object:

transform.rotation = Quaternion.RotateTowards(transform.rotation, rotation, rotationSpeed * Time.fixedDeltaTime);

its in fixedupdate so that it happens on the same clock as my movement.

this code is most likely trash so if you can help fix it

thanks in advance for any help with this annoying problem

It’s more accurate to say that it doesn’t, as it’s an axis-aligned bounding box. Also a lot of that code doesn’t make sense at all, especially since you’re assigning directly to the w, x, y and z components of a quaternion which do not do that you think they do. You should only touch them if you have a math degree.

Is there any reason you can’t just raycast down a large distance?

2 Likes

what i mean by “it gets affected by rotation” is that if you rotate the player, the extents change depending on it. as for editing the w, x, y and z directly, i did that cuz in some situations the x and y rotation are affected and the player shrinks or expands. will change these to euler angles.

i can’t just raycast down as i get unexpected behavior sometimes and i can’t do it by a large distance as that just makes the shown bug worse.

since you said that a lot of my code does not make sense, can you give me a much better version of this code with explanation for how it works? i would appreciate that.

(also could you fix the bug and tell me how it was fixed ty)

Here was my little “follow the contour of a 2D ground” demo from a few years back:

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

im sorry but this is not what i asked for. the player should not just stick to the platform even if it is under it. i want something similar to the cube in geometry dash or sonic in the 2d sonic games. it would be nice if you could just get the bits of code i need for my project and explain them. although the demo does looks cool. are you using it for a game?

I offered you a fully-functional resource containing code that can align an object to a 2D collider, which sounds pretty close to what you asked:

Did you even read any of the linked package?

Did you study how the SetDesiredRotationFromNormal() method works and how it is used by the rest of the module? The name of that function is pretty close to self-documenting perfection, if I do say so myself.

If you are unable to understand that resource, I suggest you fix that first.

This is simply Step #2 of my guide on how to be a BasicDeveloper_100:

Tutorials and example code are great, but keep this in mind to maximize your success and minimize your frustration:

How to do tutorials properly, two (2) simple steps to success:

Step 1. Follow the tutorial and do every single step of the tutorial 100% precisely the way it is shown. Even the slightest deviation (even a single character!) generally ends in disaster. That’s how software engineering works. Every step must be taken, every single letter must be spelled, capitalized, punctuated and spaced (or not spaced) properly, literally NOTHING can be omitted or skipped.
Fortunately this is the easiest part to get right: Be a robot. Don’t make any mistakes.
BE PERFECT IN EVERYTHING YOU DO HERE!!

If you get any errors, learn how to read the error code and fix your error. Google is your friend here. Do NOT continue until you fix your error. Your error will probably be somewhere near the parenthesis numbers (line and character position) in the file. It is almost CERTAINLY your typo causing the error, so look again and fix it.

Step 2. Go back and work through every part of the tutorial again, and this time explain it to your doggie. See how I am doing that in my avatar picture? If you have no dog, explain it to your house plant. If you are unable to explain any part of it, STOP. DO NOT PROCEED. Now go learn how that part works. Read the documentation on the functions involved. Go back to the tutorial and try to figure out WHY they did that. This is the part that takes a LOT of time when you are new. It might take days or weeks to work through a single 5-minute tutorial. Stick with it. You will learn.
Step 2 is the part everybody seems to miss. Without Step 2 you are simply a code-typing monkey and outside of the specific tutorial you did, you will be completely lost. If you want to learn, you MUST do Step 2.

Of course, all this presupposes no errors in the tutorial. For certain tutorial makers (like Unity, Brackeys, Imphenzia, Sebastian Lague) this is usually the case. For some other less-well-known content creators, this is less true. Read the comments on the video: did anyone have issues like you did? If there’s an error, you will NEVER be the first guy to find it.

Beyond that, Step 3, 4, 5 and 6 become easy because you already understand!

The purpose of this forum is to assist people who are ready to learn by doing, and who are unafraid to get their hands dirty learning how to code, particularly in the context of Unity3D.

This assumes you have at least written and studied some code and have run into some kind of issue.

If you haven’t even started yet, go check out some Youtube videos for whatever game design you have in mind. There are already many examples of the individual parts and concepts involved, as there is nothing truly new under the sun.

If you just want someone to do it for you, you need go to one of these places:

https://forum.unity.com/forums/commercial-job-offering.49/

https://forum.unity.com/forums/non-commercial-collaboration.17/

https://livehelp.unity.com/?keywords=&page=1&searchTypes=lessons

Remember this is YOUR game, not ours. We have our own games we’re working on.

1 Like

im sorry. i just watched the video and thought is was for something else. i apologize. i also disagree in copying code with no understanding of it, but i will read more of your code. just tell me how to use your package as i have never worked with unity packages before.

ok so in you script, i like how you use floats for rotation instead of using quaternion.fromtorotation and risking x and y values that warp the player.

however, my problem is not solved. i got around the boxcollider issue by using transform.right and transform.up and also setting the extents in the inspector. but, now if i set my raycast height to something less than 0.25, it just wont rotate at all and will jitter instead. and if i set it to something greater than that or equal to that, the same bug happens. plus, i need the raycast to be decently long so that if it is above a slope, it will still snap to it. i think what i need is a way to snap the player position to the platform.

i browsed through your code and found that you did a raycast and you set the position to raycast.point, but if i try something similar, my character just moves all around the place. i have already read a post about snapping the player position, but i need some extra guidance. also tell me if i missed anything. one big weakness of mine is pulling myself together to read hundreds of lines of code and understanding it. so any help on this is appreciated

my code now(probably still trash(also extentX an extentY are set in inspector now)):

private float DesiredRotationFromNormal(Vector3 normal)
    {
        return Mathf.Atan2(-normal.x, normal.y) * Mathf.Rad2Deg;
    }


    private void Rotate()
    {
        RaycastHit2D raycastHit;

        Quaternion origRot = transform.rotation;

        transform.rotation = Quaternion.identity;

        transform.rotation = rotation;

        if (isFacingRight)
        {
            raycastHit = Physics2D.Raycast(transform.position + transform.right * extentX, -transform.up, extentY + extraRotationRaycastHeight, groundLayer);
            Debug.DrawRay(transform.position + transform.right * extentX, -transform.up * (extentY + extraRotationRaycastHeight));
        }
        else
        {
            raycastHit = Physics2D.Raycast(transform.position - transform.right * extentX, -transform.up, extentY + extraRotationRaycastHeight, groundLayer);
            Debug.DrawRay(transform.position - transform.right * extentX, -transform.up * (extentY + extraRotationRaycastHeight));
        }

        transform.rotation = origRot;

        rotation.eulerAngles = new Vector3(0, 0, DesiredRotationFromNormal(raycastHit.normal));
    }

also i see that you have set the actual object to the rotation but used movetowardsangle for the visuals. i tried something similar by having a rotation the player rotates towards and while doing the raycast i set the rotation to that variable

ok for now i am just going to not ovecomplicate things and do a simple raycast in the direction of the player. this causes some issues but is pretty good for now. this is the simple and elegant code i was avoiding because i wanted everything to be perfect:

private float DesiredRotationFromNormal(Vector3 normal)
    {
        return Mathf.Atan2(-normal.x, normal.y) * Mathf.Rad2Deg;
    }


    private void Rotate()
    {
        Quaternion origRot = transform.rotation;

        transform.rotation = rotation;

        RaycastHit2D raycastHit = Physics2D.Raycast(transform.position, Vector2.down, boxCollider.bounds.extents.y + extraRotationRaycastHeight, groundLayer);

        transform.rotation = origRot;

        rotation.eulerAngles = new Vector3(0, 0, DesiredRotationFromNormal(raycastHit.normal));
    }

only a few bugs but works pretty well for now. i will fix those bugs later. thanks to everyone who tried to help.

1 Like