I'm trying to get my 2D character to rotate around colliders based on the current ground normal (sort of like in Mario Galaxy) detected by Physics2D.CircleCast
, which I believe automatically interpolates the normals between two surfaces sharing a convex edge (e.g. the sharp edges of a BoxCollider2D
). I also want my character to maintain a constant forward direction, in this case, transform.right
.
To achieve this I'm setting my transform.eulerAngles.z
to the value created by Vector2.Angle(hit.normal, Vector2.up)
, but the problem is that this value is only accurate half of the time. If my character is moving around a circle, for example, only one half of the circle will provide an accurate rotation; the second half of the circle rotates me in the opposite direction. I'm not very comfortable with rotations or quaternions, but I've noticed that my z rotation will go from 0 to -180 on the "correct" half of the circle, and then start going in reverse again (-179, -178, etc.) on the other half. I've also noticed that the value shown in the inspector for my z rotation is not the same as the value I get when logging it to the console (console says 270, inspector shows -90).
using UnityEngine;
using DG.Tweening;
[RequireComponent(typeof(BoxCollider2D))]
public class RotationTest : MonoBehaviour
{
[SerializeField]
private float speed = 5;
[SerializeField]
private LayerMask rayMask;
private BoxCollider2D boxCollider;
private void Awake()
{
boxCollider = GetComponent<BoxCollider2D>();
}
void Update()
{
CheckForTerrainAndRotate();
}
private void CheckForTerrainAndRotate()
{
Vector2 direction = transform.right;
transform.Translate(speed * direction * Time.deltaTime, Space.World);
float circleCastRadius = boxCollider.bounds.extents.x + 0.05f;
RaycastHit2D hit = Physics2D.CircleCast(transform.position, circleCastRadius, -transform.up, 5, rayMask);
if (!hit)
{
transform.eulerAngles = Vector3.zero;
return;
}
// Sets rotation using transform's euler angles
transform.DORotate(new Vector3(0, 0, -Vector2.Angle(hit.normal, Vector2.up)), 0.1f, RotateMode.Fast);
}
}
I'm using the DOTween
library to handle lerping between two rotations, but am also having the same issue without it.
Vector2.SignedAngle
. But I still don't understand the discrepancy in z rotation between what I see in the inspector and inDebug.Log
. \$\endgroup\$270
and-90
are same actually. \$\endgroup\$