3rd person movement with camera between platforms with gravity
This is my first question on the community forum so I hope I can properly articulate my problem.
I've been trying to make a 3rd person controller that derives the players movement direction from the camera rotation similar to the Brackeys video in this link: - https://www.youtube.com/watch?v=4HpC--2iowE&t=996s&ab_channel=Brackeys
I've tried adapting various 3d person character controllers to allow the player to walk on differently oriented platforms with their own gravity when jumping between other platforms. This has been demonstrated before on youtube by various creators such as Slug Glove. However, I don't believe any of these examples have used a free orbiting camera to direct the players movement. - https://www.youtube.com/watch?v=aZOyZJhreSU&ab_channel=SlugGlove - https://www.youtube.com/watch?v=QSDUA9YpVwQ&t=71s&ab_channel=SlugGlove
I've come close to a solution... My player has no trouble maintaining left and right movement level with the platform they are standing on as the character adapts to the platforms rotation in space. On the other hand, forward and backward movement, can only move directly in the camera's forward transform. This means the character will walk into the ground if the camera looks at the player down from above. This also work for making the player fly if the camera is looking up.
I've been struggling for a solution to keep the player level with the platform when moving forward and backwards. I'm very grateful for any advice on how to solve this problem.
Bellow is currently what my script looks like. At the moment, player forward direction is linked to "cam.transform.forward" which I've tried editing through various methods including using the platforms normal to somehow derive some kind of level forward direction.
void Update()
{
//THINK ABOUT DERRIVING MOVEMENT DIRECTION FROM NORMAL
Cursor.visible = false;
//walk
//grab mouse axis input
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
Debug.Log("Vertical: " + vertical);
Vector3 direction = new Vector3(horizontal, 0f, vertical).normalized;
//LEFT AND RIGHT WORK
Vector3 screenMovementRight = cam.transform.right;
Vector3 screenMovementForward = cam.transform.forward;
if (Physics.Raycast(transform.position, Vector3.down, out hit, raycastDistance))
{
dir = cam.transform.forward - hit.normal;
angle = Vector3.Angle(hit.normal, cam.transform.forward);
Debug.Log("Angle difference: " + angle);
}
Debug.DrawRay(transform.position, screenMovementForward*3);
//Debug.Log("Camera Forward Transform" + screenMovementForward);
Vector3 h = screenMovementRight * horizontal;
Vector3 v = screenMovementForward * vertical;
Vector3 moveDirectionRL = (h).normalized;
Vector3 moveDirectionFB = (v).normalized;
if (GetComponent<GravityTransform>().gravityHost)
{
//GRAB GRAVITY PLATFORM OBJECT
gravHost = GetComponent<GravityTransform>().gravityHost.transform;
//ROTATE PLAYER TO GRAVHOST LOCAL UP ROTATION
RotateSelf(gravHost.transform.up);
//LOOKS FOR GRAVEHOST OBJ WITH DOWNWARD RAYCAST TO PRINT OUT NORMAL
if (Physics.Raycast(transform.position, Vector3.down, out hit, raycastDistance))
{
//Debug.Log(hit.normal);
//targetDir = targetDir + (hit.normal - targetDir);
}
}
if (direction.magnitude >= .1f)
{
// if (Input.GetKey(KeyCode.W))
// rb.AddForce(speed * targetDir);
if (Input.GetKey(KeyCode.W))
RotateMesh(moveDirectionFB);
//lookDir = Quaternion.LookRotation(moveDirectionFB);
transform.position += Time.deltaTime * speed * moveDirectionFB;
if (Input.GetKey(KeyCode.S))
RotateMesh(moveDirectionFB);
//lookDir = Quaternion.LookRotation(moveDirectionFB);
transform.position += Time.deltaTime * speed * moveDirectionFB;
if (Input.GetKey(KeyCode.A))
RotateMesh(moveDirectionRL);
//lookDir = Quaternion.LookRotation(moveDirectionRL);
transform.position += Time.deltaTime * speed * moveDirectionRL;
if (Input.GetKey(KeyCode.D))
RotateMesh(moveDirectionRL);
//lookDir = Quaternion.LookRotation(moveDirectionRL);
transform.position += Time.deltaTime * speed * moveDirectionRL;
if (Input.GetKey(KeyCode.Space))
transform.position += Time.deltaTime * speed * gravHost.transform.up;
//controller.Move(targetDir.normalized * speed * Time.deltaTime);
}
}
void RotateSelf(Vector3 Direction)
{
Vector3 LerpDir = Vector3.Lerp(transform.up, Direction, turnSmoothTime * 2);
transform.rotation = Quaternion.FromToRotation(transform.up, LerpDir) * transform.rotation;
}
void RotateMesh(Vector3 LookRotationDir)
{
Quaternion SlerpRot = Quaternion.LookRotation(LookRotationDir, transform.up);
//float targetAngle = Mathf.Atan2(LookDir.x, LookDir.z) * Mathf.Rad2Deg;
//transform.rotation = Quaternion.Euler(0f, targetAngle, 0f);
transform.rotation = Quaternion.Slerp(transform.rotation, SlerpRot, 2 * turnSmoothTime);
}
void RaycastAngle()
{
if (Physics.Raycast(transform.position, Vector3.down, out hit, raycastDistance))
{
Quaternion rotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
}
}
}