[ad_1]
First, we’ll create invisible set off colliders masking the quantity of your map the place you need the gravity to level in a brand new route. Rotate these colliders in order that their “ahead” route (the blue arrow on the rework gizmo in native translation mode) factors within the route you need gravity to level.
Create a physics layer known as “Gravity Zone” and guarantee these objects are on that layer. You can 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 could have fewer collisions to verify, 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 connected physique, for modifying our physics.
[SerializeField, HideInInspector] Rigidbody _body;
// Current gravity acceleration vector - default to regular gravity.
Vector3 _gravity = Physics.gravity;
// Collection 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 at all times the newest one we have entered.
List<Collider> _zonesTouched = new List<Collider>();
// Change our gravity to level within the offered route.
public void SetGravityCourse(Vector3 route)
{
// We'll make our customized gravity precisely as sturdy because the default one.
_gravity = Physics.gravity.magnitude * route;
}
// Apply our gravity change each physics step.
void FixedUpdate() {
// If _gravity == Physics.gravity, then this can be a no-op (zero acceleration).
// Otherwise, it undoes the traditional gravity and applies our new gravity.
_body.AddDrive(_gravity - Physics.gravity, ForceMode.Acceleration);
}
// When we enter a gravity zone, apply its adjustments to our gravity route.
void OnTriggerEnter(Collider different) {
// Ignore triggers that aren't gravity zones.
if (different.gameObject.layer != GRAVITY_LAYER) {
return;
}
// Add this zone to the top of our checklist.
_zonesTouched.Add(different);
// Use this zone's gravity as our present falling route.
SetGravityCourse(different.rework.ahead);
}
// When 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;
}
// When 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.Count;
if (zoneCount > 1) {
// We have 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];
SetGravityCourse(fallback.rework.ahead);
}
// ...and take away the zone from our checklist, even when it wasn't the lively one.
_zonesTouched.Remove(different);
} else {
// No different zones in our checklist, revert to regular gravity.
_zonesTouched.Clear();
_gravity = Physics.gravity;
}
}
// Automatically 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);
}
}
Most of the complexity right here is simply in making certain we deal with coming into/exiting a number of zones in any order – so if in case you have a funny-shaped quantity to navigate, you may construct it out of a number of colliders and this script will deal with the transitions between them sensibly.
[ad_2]
