# Trying to Keep a reference frame for tangent movement

This topic is 2435 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello!

I'm trying to make an open source universal platformer engine (on unity3D) that can do stuff like sonic and mario galaxy, ie a character that move on arbitrary surface without problem in varying gravity condition. But achieving 360° navigation is hard. I have made many research through internet and forums to solve my problem but still stumble on some aspect.

My current problem deal with alignment of the character regarding the world reference.

The beige square under the feet in picture below is the local reference frame in which movements are calculated! If it's wrong, movement are wrong, It should always be align to the world ref:

Correctly align

After a lot of whoopee loop de loop de loop on various angle MISALIGN F*****

The way movement is calculated is that the collider translate along his local coordinate (on its XZ plane for horizontal movement and its Y for jumping) and should match the world axis when his Y is up. What the code do is it translate the collider and aligning the local Y to surface normal (no explicit rotation). But if you do it too much it lost his reference alignment (correct alignment along XZ plane (horizontal) to the world once local Y is globally up and align with global Y) and that mess the movement of the player like slope friction.

The bit of code that do that is pretty simple:

 //adapt to character controller MoveController=new Vector3 ( this.Motion_Speed.x * Time.deltaTime, this.Motion_Speed.y * Time.deltaTime - (0.015f/5f + (this.Motion_Speed.magnitude * 0.33f * Time.deltaTime)),//keep feet planted this.Motion_Speed.z * Time.deltaTime); this.AlignForward(); this.body.transform.Translate(MoveController,Space.Self); 

Basically what it does is:

- I take the motion data (motion speed)
- Apply an expression to Y of motion speed to keep feet on the ground
- Align the character with a special function that fixed locally a previous gimbal lock case that was caused by a naive alignment (which does not track XZ data).
- simply translate it along his local coordinate using motion data to move tangentially to the ground

The problem lie in the alignment, previously, despite using vector alignment and quaternion (no explicit rotation), I had a gimbal lock, searching the forums and asking questions like now solved partially the problem, here is the code for the AlignForward() (transform is the structure that contain spatial info of the character like position, scale and rotation):

 Vector3 fwd = Trans.transform.forward; Vector3 proj = fwd - (Vector3.Dot (fwd, Align)) * Align; this.transform.rotation = Quaternion.LookRotation(proj, Align);

What it does is that it calculate a projection of the GameObject's forward vector on a plane defined with Align vector, then generate a rotation that looks in direction of the projected vector and has the align vector as up vector. What I understood is that the forward vector projection lose the reference to the world and mess up alignment when back to a visual reference frame that match his Y axis.

The align vector is passed either as gravity vector when on air (currently the Y axis of the world) or the surface normal when on ground. I tried to force alignment to the world at each step (using the older code) and then align him back to surface normal but gimbal lock reappear along the axis I choosed to align to! Here is the old code (who keep the reference of the world once both Y match):

 Trans.transform.rotation = Quaternion.Lerp( Trans.transform.rotation,//from Quaternion.FromToRotation(AlignAxis,Vect),//to this Rate//at this rate );

What it does is that it linearly interpolate the current rotation to a target rotation define by the function FromToRotation, which take in input the axis to align and the destination vector.

This code was discard because it was explain to me that:

I suspect this may be your problem. Your input information is a Quaternion (representing your character's current rotation) and a Vector3 (representing the surface normal). You can interpolate to take your character's local Y ("up") onto that normal, but you need to also set your character's local Z ("forward") to a suitable tangent. This is not uniquely defined by your two input. Now informally it's obvious to both of us which particular tangent you want, but how are you calculating it? Because it sounds like you're ending up with the wrong one![/QUOTE]

I think I understand where the gimbal lock came from, when two axis are align it does not matter if it's quaternion or euler you lose one degree of freedom. In my code as soon as the local up align with his global axis we lost sense of direction (generally the antipode for Y Quaternion alignment). When I tried to fix it by first putting the object into a neutral pose realtive to some axis before applying alignment, i had a gimbal lock in that axis. So I remove reference all together, define a local plane to align movement and it worked well (the new code). Except now I need to keep a correct horizontal frame whatever happen! How I could do that?

Problem will happen as soon as I implement varying gravity! (no more corrective jump with the old code, and jump is already mess up when the change in reference coordinate happen).

I'm not proficient with math stuff, I think I pretty much reach my level of competence, can you help me resolve that case or suggest me better way to implement all that stuff?

You can try the game here:

http://dl.dropbox.com/u/24530447/build.rar (exe and package)
http://dl.dropbox.com/u/24530447/script.rar (script in *.cs file)

Control:
Reconfigurable before playing

QSDZ (azerty) + arrows: movement relatif cam
Click left: jump
Click Right: instant stop
Both click: spindash
Mousewheel scrolling: zoom in/out (broken)

debug toggle cheat (beware: no feedback on activation):
R: sticky mode (don't fall from steep angle and ceiling)
G: galaxy mode (jump relative to current slope, beware don't reattach! on steep angle)

[size="1"]Current known problem:

1. The character is F**** sticky!
- Cause: The collision engine in unity is way more powerful than Blitz3D and this is the consequence of this, it solve the occasional "bump fly" blitzsonic is known for but now you can't fall edge.
> status: solvable with raytracing and flags, secondary priority.

2. The camera is strange, it have a small delay which get bigger with ample movement!
- Cause: Unknown, it's like a desync of unity's internal loop with rendering and physics.
> Status: solvable, create from scratch a new camera system based on unity internal working. Secondary priority

3. You can't jump from ceiling, the character stick to the ground!
- Cause Unknown, it does not happen when i trigger the "galaxy mode", it may come from some magic with realignment after a jump.
> Status: Researching! this is a fundamental element of the 360° movement engine! Maximum priority! request help and info!

4. The character misAlign after some 90° movement (and lower angle) and mess up movement!
- Cause: Unknown, to solve Gimbal lock (yes without rotation and with quaternion for you math headed) I use a vector projection but it has it's own flaws, it mess up on certain angle configuration, I don't do math I have no idea why.
> Status: Researching! Core 360° movements is the whole game, [color="red"]CRITICAL priority! request help and info!

[s]5. The character visual mesh became wacky and spin non relative to movement, lost direction!
- Cause: Gimbal lock (because it happen on pole even more wildly)! The vector math is not immune to gimbal lock, the solution used for the collider does not work because the mesh rotate and the collider don't (fixed reference frame). I'm not math headed enough.
> Status: Researching! Core 360° movements is the whole game, [color="red"]CRITICAL priority! request help and info![/s]

6.The character is repel in outward slope upward after some loop de loop onto sphere or other outward shape!
- Cause: Unknown! look like the game lose tracks of reference, damizean also hard coded the dot product to evaluate slope vertical friction in the Y value of the motion alignment vector which is in global scene space (gravity is supposedly always align to Y).
> Status: Researching! this is a fundamental element of the 360° movement engine! Maximum priority! request help and info!

7. The character animation is too low relative to speed
- Cause: Difference between the build setup and the editor test.
> Status: solvable, cosmetic, low priority

Cool spot on the test stage to test the broken aspect: look for the big sphere! walk on ceiling and under the level, laugh![/font]