First, we’ll create invisible set off colliders masking the amount of your map the place you need the gravity to level in a brand new path. Rotate these colliders in order that their “ahead” path (the blue arrow on the remodel gizmo in native translation mode) factors within the path you need gravity to level.
Create a physics layer known as “Gravity Zone” and guarantee these objects are on that layer. You’ll be able to filter collisions with this layer so solely objects that want to make use of this altered gravity course of detect overlaps with these objects – good for efficiency since you have got fewer collisions to examine, and it saves you some filtering code to manually ignore them in unrelated scripts.
Then we’ll make a script for the rigidbody (or our bodies) that ought to obey this altered gravity:
utilizing System.Collections;
utilizing System.Collections.Generic;
utilizing UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class VariableGravity : MonoBehaviour {
// Cache ID of gravity modification physics layer.
static readonly LayerMask GRAVITY_LAYER = LayerMask.NameToLayer("Gravity Zone");
// Reference to our hooked up physique, for modifying our physics.
[SerializeField, HideInInspector] Rigidbody _body;
// Present gravity acceleration vector - default to regular gravity.
Vector3 _gravity = Physics.gravity;
// Assortment of altered gravity zone set off volumes we're touching.
// These can overlap, so we retailer an ordered checklist of them,
// the place the final entry is all the time the latest one we have entered.
Listing<Collider> _zonesTouched = new Listing<Collider>();
// Change our gravity to level within the offered path.
public void SetGravityDirection(Vector3 path)
{
// We'll make our customized gravity precisely as robust because the default one.
_gravity = Physics.gravity.magnitude * path;
}
// Apply our gravity change each physics step.
void FixedUpdate() {
// If _gravity == Physics.gravity, then this can be a no-op (zero acceleration).
// In any other case, it undoes the conventional gravity and applies our new gravity.
_body.AddForce(_gravity - Physics.gravity, ForceMode.Acceleration);
}
// After we enter a gravity zone, apply its modifications to our gravity path.
void OnTriggerEnter(Collider different) {
// Ignore triggers that aren't gravity zones.
if (different.gameObject.layer != GRAVITY_LAYER) {
return;
}
// Add this zone to the tip of our checklist.
_zonesTouched.Add(different);
// Use this zone's gravity as our present falling path.
SetGravityDirection(different.remodel.ahead);
}
// After we exit a gravity zone, take away its impact.
void OnTriggerExit(Collider different) {
// Ignore triggers that aren't gravity zones.
if (different.gameObject.layer != GRAVITY_LAYER) {
return;
}
// After we depart a zone, we need to fall again on the results
// of the next-most-recent zone we touched, if any.
int zoneCount = _zonesTouched.Depend;
if (zoneCount > 1) {
// We've one other zone to fall again on.
// If "this" zone we're leaving is the one at present in impact,
// fall again on the following most up-to-date zone within the stack.
if (different == _zonesTouched[zoneCount - 1]) {
var fallback = _zonesTouched[zoneCount - 2];
SetGravityDirection(fallback.remodel.ahead);
}
// ...and take away the zone from our checklist, even when it wasn't the energetic one.
_zonesTouched.Take away(different);
} else {
// No different zones in our checklist, revert to regular gravity.
_zonesTouched.Clear();
_gravity = Physics.gravity;
}
}
// Mechanically wire up the _body variable so we do not have to set it.
void OnValidate()
{
// TryGet is an effective behavior for minimizing editor allocations,
// plus it is much less typing than out _body = GetComponent<Rigidbody>();
TryGetComponent(out _body);
}
}
A lot of the complexity right here is simply in making certain we deal with coming into/exiting a number of zones in any order – so in case you have a funny-shaped quantity to navigate, you’ll be able to construct it out of a number of colliders and this script will deal with the transitions between them sensibly.