I’m making a 2d game where gravity changes every time you touch a wall, celling or floor, the idea is that the entire tile-map would just rotate on the z axis, i have tried to rotate the player and the camera, rotate just the tilemap and nothing seems to work. If anyone can help, please.
If you need the scripts please say
Your question has a bunch of aspects so it so what specifically are you asking though?
How to change the global gravity?
How to detect a collision?
Something else?
For the collision detection i would just use on trigger enter 2d, but its the global gravity- more importantly the way to rotate every thing when they collide with a object, im trying to make a platformer with the idea that the map is forever changing. i have this script which kind of does what i want it to but the collision detection is not working,
using UnityEngine;
public class MapOrientationChanger : MonoBehaviour
{
public float gravityStrength = 9.8f; // Strength of gravity
private Rigidbody2D rb;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void FixedUpdate()
{
// Cast a ray downwards to detect the ground
RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, Mathf.Infinity, LayerMask.GetMask("Wall"));
if (hit.collider != null)
{
// Get the surface normal of the wall
Vector2 surfaceNormal = hit.normal;
// Calculate the new gravity direction based on the surface normal
Vector2 gravityDirection = -surfaceNormal * gravityStrength;
// Set the new gravity direction
rb.gravityScale = 0f;
rb.AddForce(gravityDirection, ForceMode2D.Force);
// Rotate the player to match the new gravity direction
Quaternion targetRotation = Quaternion.FromToRotation(Vector2.up, -surfaceNormal);
transform.rotation = targetRotation;
}
}
}
I’ve gone over it and its just not working
To change the global gravity I think you can just change Physics2D.gravity. However, the method you’re using to find the ground is not going to work as soon as the gravity is facing anywhere but downwards. You’ll need to adjust the direction of you raycast depending on the current gravity. Or, if you’re inside (or over) a “circular” surface perhaps you can use the direction between the player and the center.
Could you just show a very simple script using this so i can understand, thank you
Do you mean changing the gravity? Just use Physics2D.gravity = gravityDirection;
instead of
csharp** **rb.gravityScale = 0f; rb.AddForce(gravityDirection, ForceMode2D.Force);** **
I mean setting a new direction for the gravity so right to left or down to up.
Or the tilemap rotates to create the idea that gravity has changed
The yellow line is the collition, then that wall will become the new floor for gravity
Also how would i do the do the colition detection like you said
I would recommend starting with any one of these 748,000 first hits on Google:
lol, thxs 4 every thing every one
You could use something along these lines:
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public GameObject Ground;
public Rigidbody2D PlayerRigidbody;
public LayerMask GroundCollisionLayer;
public float MaxSpeed;
private float _gravityMagnitude;
private float _horizontalStick;
private Vector2 _lastUpDirection = Vector2.up;
private Vector2 _lastRightDirection = Vector2.right;
private void Start()
{
_gravityMagnitude = Physics2D.gravity.magnitude;
}
void Update()
{
_horizontalStick = Input.GetAxis("Horizontal");
}
private void FixedUpdate()
{
// To obtain the ground normal, make a raycast from the center of the ground to the player. Offset the position in the movement direction to be able to pick the next platform.
// NOTE: Not necessarily good enough depending on the terrain shape.
Vector2 groundCenter = Ground.transform.position;
const float raycastTargetOffset = 0.5f;
Vector2 raycastTarget = PlayerRigidbody.position + _horizontalStick * raycastTargetOffset * _lastRightDirection;
Vector2 raycastDirection = (groundCenter - raycastTarget).normalized;
RaycastHit2D groundHit = Physics2D.Raycast(groundCenter, raycastDirection, float.PositiveInfinity, GroundCollisionLayer);
Vector2 upDirection = groundHit.normal;
Vector2 rightDirection = Vector2.Perpendicular(upDirection);
// We need to keep the magintude of the vertical speed. Else we'd discard the gravity contribution.
float currentVerticalSpeed = Vector2.Dot(PlayerRigidbody.velocity, _lastUpDirection);
PlayerRigidbody.velocity = MaxSpeed * _horizontalStick * rightDirection + currentVerticalSpeed * upDirection;
Physics2D.gravity = upDirection * _gravityMagnitude;
_lastUpDirection = upDirection;
_lastRightDirection = rightDirection;
}
}
I’m including a test project in case you want to see the whole thing configured.
As mentioned, the idea is to use the direction from the ground center to the player (plus an offset) both as the raycast direction to obtain the normal and then just use that normal as the gravity direction. As mentioned in the coments, the position of the player is slighlty offset so the ray can touch the neighboring platforms. Depending on the actual shape of your scene this may or may not be good enough.
9770268–1399911–TestGravity.7z (50 KB)