Assistance on Rotate Quaternion & Eluer

Discuss modding questions and implementation details.
l3lessed
Posts: 1399
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Assistance on Rotate Quaternion & Eluer

Post by l3lessed »

Hey, I need some assistance on getting a vector3 to rotate along the y axis. I want it to create a downward arc going from top of the screen to the bottom.

I was able to do this easily when modifying the other axis to create a left to right and right to left arc. But the moment I try to move it along the top down axis to create a downward arc, I start getting really funky results as the player rotates their camera more and more. My dumb math head can't figure this out, and I can't find a solution on google. Any assist would help.

Here is the code:

This sets up the attack cast to be rotated over the time of the attack to create a swing arc. It creates a vector3 forward value using the player camera and then passes that to a function that rotates it based on the vector3 rotate values put in.

Code: Select all

                        Vector3 attackcast = AmbidexterityManager.mainCamera.transform.forward;
                        if (weaponState == WeaponStates.StrikeRight)
                            attackcast = ArcCastCalculator(new Vector3(0, -90, 0), new Vector3(0, 90, 0), percentagetime * arcSpeed, attackcast);
                        else if (weaponState == WeaponStates.StrikeDownRight)
                            attackcast = ArcCastCalculator(new Vector3(35, -35, 0), new Vector3(-30, 35, 0), percentagetime * arcSpeed, attackcast);
                        else if (weaponState == WeaponStates.StrikeLeft)
                            attackcast = ArcCastCalculator(new Vector3(0, 90, 0), new Vector3(0, -90, 0), percentagetime * arcSpeed, attackcast);
                        else if (weaponState == WeaponStates.StrikeDownLeft)
                            attackcast = ArcCastCalculator(new Vector3(35, 35, 0), new Vector3(0, -30, -35), percentagetime * arcSpeed, attackcast);
                        //THIS IS THE SWING WITH THE ERROR TO BE SPECIFIC: ALL OTHER SWINGS THAT USE ONLY THE Y VALUE WORK FINE\\
                        else if (weaponState == WeaponStates.StrikeDown)
                            attackcast = ArcCastCalculator(new Vector3(45, 0, 0), new Vector3(-45, 0, 0), percentagetime * arcSpeed, attackcast);
                        else if (weaponState == WeaponStates.StrikeUp)
This actually rotates the vector3 raycast by converting the starting and ending vector3 values into quaternion eulers, rotating them using a quaternion Lerp function to move the vector3 between the beginning and end rotation value, and then multiplying that by the cast direction.

Code: Select all

        //uses vector3 axis rotations to figure out starting and ending point of arc, then uses lerp to calculate where the ray is in the arc, and then returns the calculations.
        public Vector3 ArcCastCalculator(Vector3 startPosition, Vector3 endPosition, float percentageTime, Vector3 castDirection)
        {
            if (flip)
            {
                startPosition = startPosition * -1;
                endPosition = endPosition * -1;
            }

            //sets up starting and ending quaternion angles for the vector3 offset/raycast.
            Quaternion startq = Quaternion.Euler(startPosition);
            Quaternion endq = Quaternion.Euler(endPosition);
            //computes rotation for each raycast using a lerp. The time percentage is modified above using the animation time.
            Quaternion slerpq = Quaternion.Lerp(startq, endq, percentageTime);
            Vector3 attackcast = slerpq * castDirection;
            return attackcast;
        }
I know it is getting screwed up when it is being converted math wise into the Quaternion and Euler numbers, but I do not know how to resolve this issue by either ensuring only the one axis changes or setting it up so the math comes out correct.
Last edited by l3lessed on Thu Jul 15, 2021 7:59 pm, edited 1 time in total.
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

User avatar
DunnyOfPenwick
Posts: 275
Joined: Wed Apr 14, 2021 1:58 am
Location: Southeast US

Re: Assistance on Rotate Quaternion & Eluer

Post by DunnyOfPenwick »

I had to fiddle with Quaternions in my mods, so I went back and checked my code.

It is basically the same except I was multiplying 2 quaternions together and then multiplying by a vector.

Try the following:
Change attackcast vector in the first code chunk to a Quaternion attackcast = mainCamera.transform.rotation;
and pass that to ArcCastCalculator instead.
...then in that function use Vector3 attackcast = (slerpq * castDirection) * Vector3.forward;

...and see if it makes any difference.

I'm not sure how the '*' operator is really handled underneath the covers by Quaternion class.

l3lessed
Posts: 1399
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Assistance on Rotate Quaternion & Eluer

Post by l3lessed »

Thanks, I'll try that; I think not storing the camera rotation could be the key, as the google searches seemed to reference this at times. I couldn't understand how it was working though, as I've never used Eulers are quaternions before this.

I had another thought if that doesn't work. I could try shooting out the arc using a Vector3.lerp and then use a Euler.LooktoDirection to face the vector camera forward.
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

User avatar
DunnyOfPenwick
Posts: 275
Joined: Wed Apr 14, 2021 1:58 am
Location: Southeast US

Re: Assistance on Rotate Quaternion & Eluer

Post by DunnyOfPenwick »

I didn't have any experience with quaternions before either, prior to writing mods that use them.

I think one of the key concepts is that quaternions don't so much represent angles, they really represent a rotation operation. It's a kind of subtle difference. So you combine all your rotation operations together, then you apply the result to a Vector3.forward.

l3lessed
Posts: 1399
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Assistance on Rotate Quaternion & Eluer

Post by l3lessed »

Not working. I'm still having the same issue. It seems like it might be tied to the z rotation moving with the x rotation. As I spin the character, it shows in the debug log that the transform.forward z value is changing along with the x.

What I need to do is lock all rotation axis, accept for the Z.

https://forum.unity.com/threads/how-qua ... ks.985800/
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

l3lessed
Posts: 1399
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Assistance on Rotate Quaternion & Eluer

Post by l3lessed »

Yep, my intuition was right. The issue has to do with how both the z and x axis are used to compute a transform.rotate forward direction.

As a result, when you are halfway between forward(0,0,1) and backward(0,0,-1) coordinates, you get right(1,0,0) and left (-1,0,0) added to get the forward direction (-1,0,1); the (-1,0,1) coordinate would be a 180 degree rotation from starting forward position. When the x coordinate is added and then muplited through god knows what math via quaternions and Euler's, it completely throws off the y axis for the arc. Think of trying to draw a line around a ball as it rotates not only around its x axis, but also another axis, say the y, and you quickly will see how the rotation in world space start getting distorted quickly.

So, the fix is as thought. First, create the arc using the players position and straight vector3 offsets and the vector3.lerp function. This will create a clean arc based on actual world space coordinates, separate from player rotation values and eulers and crap, then rotate it camera forward by using the quaternion.lookdirection function; this worked, but introduced one last bug. Apparently, the camera look forward is actually offset by +20 degrees along the y axis rotation, so I had to take away 20 degrees of rotation. Once I did that, we have a proper arc cast, without distortion, coming from the players center forward.

Think of it this way, you have your ball and instead of drawing your line/arc on it while it rotates in the world, you stop the ball from rotating. You draw the line/arc you want on it with it standing still, then you rotate the whole ball afterwards so the line is where you wanted it in the first place. This way, the line doesn't distort during rotation and instead the whole line moves with the balls rotation because its been drawn on before rotation.

I'll change all my other arc casts to use this method, since it is the proper one for ensuring you don't get the dreaded rotation distortion from multiplying rotational values.

Here is the fix.

Code: Select all

//calculate the y-axis/downward arc in world space using the players current x and z position. Uses lerp and animation time to move arc between y cordinates.
attackcast = Vector3.Lerp(new Vector3(GameManager.Instance.PlayerObject.transform.position.x, 45f, GameManager.Instance.PlayerObject.transform.position.z), new Vector3(GameManager.Instance.PlayerObject.transform.position.x, -45f, GameManager.Instance.PlayerObject.transform.position.z), percentagetime);
                            
//rotate the object towards the players look/forward direction; However, this is off by 20 degrees to the right, so rotate it 20 degrees left to center the arc with player view; have to use the y coordinates because of the engine uses that for players x rotate instead.                      
objectRotation = Quaternion.LookRotation(GameManager.Instance.PlayerObject.transform.forward) * Quaternion.Euler(0, -20f, 0);
                            
//multiply the arc cast by the object rotation/look forward angle.
attackcast = (objectRotation * attackcast)
Last edited by l3lessed on Thu Jul 15, 2021 8:01 pm, edited 2 times in total.
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

User avatar
DunnyOfPenwick
Posts: 275
Joined: Wed Apr 14, 2021 1:58 am
Location: Southeast US

Re: Assistance on Rotate Quaternion & Eluer

Post by DunnyOfPenwick »

I didn't even notice that you were doing Z-axis rotation in the code. I vaguely remember warnings in the Unity documentation about problems associated with z-axis rotation.

Just to be sure, you might want to draw differently colored spheres (shades of gray) along the expected path to verify it's doing what you expect.

l3lessed
Posts: 1399
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Assistance on Rotate Quaternion & Eluer

Post by l3lessed »

Yeah, I was seeing this warning, so I knew it was something to do with it, but I wasn't understanding the math. Using the debug.logs and rethinking the whole approach provided the answer without me having to be some calculus+ level mathematician.

One last update. If you want to also lock the raycast to the cameras look up and down, so said object/raycast angles upward and downward properly, just add the players x rotation property to the quaternion angle being used to rotate the final raycast vector3.

Turn this top line of code (It forces the object to always rotate to the forward facing camera position and then uses a basic angle to rotate it one more time to fix an offset bug):

Code: Select all

Quaternion objectRotation = Quaternion.LookRotation(GameManager.Instance.MainCamera.transform.forward) * Quaternion.Euler(0, -20f, 0);
Into this (It forces the object to always rotate to the forward facing camera position; after that, it grabs the players up/down look rotation, and finally, it, uses a quaternion angle to rotate it so it faces forward, matches players up and down angle, and offsets/fixes the misalignment issue by 20 degrees):

Code: Select all

Quaternion objectRotation = Quaternion.LookRotation(GameManager.Instance.MainCamera.transform.forward) * Quaternion.Euler(GameManager.Instance.MainCamera.transform.rotation.x, -20f, 0);
I already have debug raycasts setup to shootout at the exact spot the actual raycast does. And yes, this works. As stated, the issue is trying to lerp an vector3 while rotating the object, which causes distortion from spatial rotation (again, just think of a giant ball/sphere and drawing on it while it rotates multiple directions).

If anyone ever is rotating anything, the safest method is first setup the vector3 cordinates in the world space then use the quaternion's to rotate it after it is setup. If you do not, you will most likely run into this infamous problem with rotating making the x-axis/z-axis rotations go haywire from spatial distortion.
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

User avatar
DunnyOfPenwick
Posts: 275
Joined: Wed Apr 14, 2021 1:58 am
Location: Southeast US

Re: Assistance on Rotate Quaternion & Eluer

Post by DunnyOfPenwick »

I think I'm still a little confused. The other swings were all simple arcs, but the StrikeDownLeft would appear to be a somewhat strangely shaped curve (I haven't tested it, just guessing). Was that intentional? I would have expected StrikeDownLeft to be more or less the mirror opposite of StrikeDownRight...

l3lessed
Posts: 1399
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Assistance on Rotate Quaternion & Eluer

Post by l3lessed »

Well, that was because the previous method was not working correctly, so the numbers were not actually right.

Now I have fixed the rotation stretching/distortion issue, I came across another one while refactoring debugging. My raycast seem to be moving left and right okay no matter where I am.

BUT I STILL NEED HELP AS I'M STILL GETTING A WEIRD NEW BUG

However, the up, down rotation is still buggy in ways. When I spawn in and swing, the arc cast is where it is supposed to be, including angling it up and down. However, when I walk around, the up down angle randomly changes based on where I am. As an example, if I start at the beginning dungeon I have perfect arc casts in the large starting cave, but the moment I go up the stairs after the first rat encounter, my attacks randomly start arcing upwards.

I can't find the property that would be causing this issue. I locked the angles every way imaginable to ensure the rotations themselves were not the issue; I even locked the euler angles directly to the camera transform rotation angle and locked all others to the player position, and it still happens.

What in the world would cause the camera up/down, X rotation from shifting randomly upon moving around in the world? It's the last major bug I can't seem to squash.
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

Post Reply