Change gravity on button

Hey,

I am still quite new to Unity but searching the forums has yet to helped

I am trying to make gravity reverse on-press of a button so make character can walk on the ceiling

I have established the on press function but adding either ‘Physics.gravity = Vector3(0, -1.0, 0);’ or ‘Physics.gravity = -Physics.gravity’ (something like that) into a on press function inside the update function hasn’t helped

I am using a 2D platformer character controller I found online (quoted below, sorry for the length)… Maybe something inside that code is preventing it…

Thanks a lot

    #pragma strict
    
    // Does this script currently respond to Input?
    var canControl = true;
    
    // The character will spawn at spawnPoint's position when needed.  This could be changed via a script at runtime to implement, e.g. waypoints/savepoints.
    var spawnPoint : Transform;
    
    class LangmanControllerMovement {
    	// The speed when running 
    	var runSpeed = 7.0;
    
    	// The speed when sliding up and around corners 
    	var slideFactor = 0.05;
    	@System.NonSerialized
    	var slideX = 0.0;
    	
    	// The gravity for the character
    	var gravity = 60.0;
    	var maxFallSpeed = 20.0;
    
    	// How fast does the character change speeds?  Higher is faster.
    	var speedSmoothing = 20.0;
    
    	// This controls how fast the graphics of the character "turn around" when the player turns around using the controls.
    	var rotationSmoothing = 10.0;
    
    	// The current move direction in x-y.  This will always been (1,0,0) or (-1,0,0)
    	// The next line, @System.NonSerialized , tells Unity to not serialize the variable or show it in the inspector view.  Very handy for organization!
    	@System.NonSerialized
    	var direction = Vector3.zero;
    
    	// The current vertical speed
    	@System.NonSerialized
    	var verticalSpeed = 0.0;
    
    	// The current movement speed.  This gets smoothed by speedSmoothing.
    	@System.NonSerialized
    	var speed = 0.0;
    
    	// Is the user pressing the left or right movement keys?
    	@System.NonSerialized
    	var isMoving = false;
    
    	// The last collision flags returned from controller.Move
    	@System.NonSerialized
    	var collisionFlags : CollisionFlags; 
    
    	// We will keep track of an approximation of the character's current velocity, so that we return it from GetVelocity () for our camera to use for prediction.
    	@System.NonSerialized
    	var velocity : Vector3;
    	
    	// This will keep track of how long we have we been in the air (not grounded)
    	@System.NonSerialized
    	var hangTime = 0.0;
    }
    
    var movement : LangmanControllerMovement;
    
    // We will contain all the jumping related variables in one helper class for clarity.
    class LangmanControllerJumping {
    	// Can the character jump?
    	var enabled = true;
    
    	// How high do we jump when pressing jump and letting go immediately
    	var height = 0.5;
    	// We add extraHeight units (meters) on top when holding the button down longer while jumping
    	var extraHeight = 1.6;
    	
    	// How fast does the character change speeds?  Higher is faster.
    	var speedSmoothing = 3.0;
    
    	// How fast does the character move horizontally when in the air.
    	var jumpSpeed = 9.5;
    	
    	// This prevents inordinarily too quick jumping
    	// The next line, @System.NonSerialized , tells Unity to not serialize the variable or show it in the inspector view.  Very handy for organization!
    	@System.NonSerialized
    	var repeatTime = 0.05;
    
    	@System.NonSerialized
    	var timeout = 0.15;
    
    	// Are we jumping? (Initiated with jump button and not grounded yet)
    	@System.NonSerialized
    	var jumping = false;
    	
    	@System.NonSerialized
    	var reachedApex = false;
      
    	// Last time the jump button was clicked down
    	@System.NonSerialized
    	var lastButtonTime = -10.0;
    	
    	// Last time we were grounded
    	@System.NonSerialized
    	var lastGroundedTime = -10.0;
    
    	@System.NonSerialized
    	var groundingTimeout = 0.1;
    
    	// Last time we performed a jump
    	@System.NonSerialized
    	var lastTime = -1.0;
    
    	// the height we jumped from (Used to determine for how long to apply extra jump power after jumping.)
    	@System.NonSerialized
    	var lastStartHeight = 0.0;
    
    	@System.NonSerialized
    	var touchedCeiling = false;
    
    	@System.NonSerialized
    	var buttonReleased = true;
    }
    
    var jump : LangmanControllerJumping;
    
    private var controller : CharacterController;
    
    // Moving platform support.
    private var activePlatform : Transform;
    private var activeLocalPlatformPoint : Vector3;
    private var activeGlobalPlatformPoint : Vector3;
    private var lastPlatformVelocity : Vector3;
    
    private var sprite : GameObject;
    
    function Awake () {
    	movement.direction = transform.TransformDirection (Vector3.forward);
    	controller = GetComponent (CharacterController) as CharacterController;
    	sprite = transform.Find("Sprite").gameObject;
    }
    
    function Spawn () {
    	// reset the character's speed
    	movement.verticalSpeed = 0.0;
    	movement.speed = 0.0;
    	
    	// make sure we're not attached to a platform
    	activePlatform = null;
    	
    	// reset the character's position to the spawnPoint
    	transform.position = spawnPoint.position;
    	
    	sprite.active = true;
    	canControl = true;
    }
    
    function Unspawn() {
    	canControl = false;
    	sprite.active = false;
    }
    
    function UpdateSmoothedMovementDirection () {	
    	var h = Input.GetAxisRaw ("Horizontal");
    	
    	if (!canControl)
    		h = 0.0;
    	
    	movement.isMoving = Mathf.Abs (h) > 0.1;
    	
    	if (movement.isMoving){
    		// run
    		movement.direction = Vector3 (h, 0, 0);
    	}
    	
    	// Smooth the speed based on the current target direction
    	var curSmooth = 0.0;
    	// Choose target speed
    	var targetSpeed = Mathf.Min (Mathf.Abs(h), 1.0);
    
    	if(controller.isGrounded){
    		curSmooth = movement.speedSmoothing * Time.smoothDeltaTime;
    		targetSpeed *= movement.runSpeed;
    		movement.hangTime = 0.0;
    	}else{
    		curSmooth = jump.speedSmoothing * Time.smoothDeltaTime;
    		targetSpeed *= jump.jumpSpeed;
    		movement.hangTime += Time.smoothDeltaTime;
    	}
    	
    	movement.speed = Mathf.Lerp (movement.speed, targetSpeed, curSmooth);
    }
    
    function AnimateCharacter() {
    	// For an example of animating a sprite sheet, see:
    	// http://www.unifycommunity.com/wiki/index.php?title=Animating_Tiled_texture
    	if (movement.isMoving){
    		// run
    	}else if(controller.isGrounded){
    		// stand
    	}
    }
    
    function JustBecameUngrounded() {
    	return (Time.time < (jump.lastGroundedTime + jump.groundingTimeout) && jump.lastGroundedTime > jump.lastTime);
    }
    
    function ApplyJumping () {
    	if (Input.GetButtonDown ("Jump") && canControl) {
    		jump.lastButtonTime = Time.time;
    	}
    
    	// Prevent jumping too fast after each other
    	if (jump.lastTime + jump.repeatTime > Time.time){
    		return;
    	}
    
    	var isGrounded = controller.isGrounded;
    	
    	// Allow jumping slightly after the character leaves a ledge,
    	// as long as a jump hasn't occurred since we became ungrounded.
    	if (isGrounded || JustBecameUngrounded()) {
    		if(isGrounded){
    			jump.lastGroundedTime = Time.time;
    		}
    		
    		// Jump
    		// - Only when pressing the button down
    		// - With a timeout so you can press the button slightly before landing		
    		if (jump.enabled && Time.time < jump.lastButtonTime + jump.timeout) {
    			movement.verticalSpeed = CalculateJumpVerticalSpeed (jump.height);
    			// If we're on a platform, add the platform's velocity (times 1.4)
    			// to the character's velocity. We only do this if the platform
    			// is traveling upward.
    			if(activePlatform){
    				var apRb = activePlatform.rigidbody;
    				if(apRb){
    					var apRbY = activePlatform.rigidbody.velocity.y;
    					if(apRbY > 0.0){
    						apRbY *= 1.4;
    						movement.verticalSpeed += apRbY;
    					}
    				}
    			}
    			SendMessage ("DidJump", SendMessageOptions.DontRequireReceiver);
    		}
    	}
    }
    
    function ApplyGravity () {
    	// Apply gravity
    	var jumpButton = Input.GetButton ("Jump");
    	
    	if (!canControl)
    		jumpButton = false;
    		
    	// When we reach the apex of the jump we send out a message
    	if (jump.jumping && !jump.reachedApex && movement.verticalSpeed <= 0.0) {
    		jump.reachedApex = true;
    		SendMessage ("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
    	}
    	
    	// * When jumping up we don't apply gravity for some time when the user is holding the jump button
    	//   This gives more control over jump height by pressing the button longer
    	if (!jump.touchedCeiling && IsTouchingCeiling()){
    		jump.touchedCeiling = true; // store this so we don't allow extra power jump to continue after character hits ceiling.
    	}
    	if (!jumpButton){
    		jump.buttonReleased = true;
    	}
    	
    	var extraPowerJump = jump.jumping && movement.verticalSpeed > 0.0 && jumpButton && !jump.buttonReleased && transform.position.y < jump.lastStartHeight + jump.extraHeight && !jump.touchedCeiling;
    	
    	if (extraPowerJump){
    		return;
    	}else if (controller.isGrounded){
    		movement.verticalSpeed = -movement.gravity * Time.smoothDeltaTime;
    	}else{
    		movement.verticalSpeed -= movement.gravity * Time.smoothDeltaTime;
    	}
    		
    	// Make sure we don't fall any faster than maxFallSpeed.  This gives our character a terminal velocity.
    	movement.verticalSpeed = Mathf.Max (movement.verticalSpeed, -movement.maxFallSpeed);
    }
    
    function CalculateJumpVerticalSpeed (targetJumpHeight : float) {
    	// From the jump height and gravity we deduce the upwards speed 
    	// for the character to reach at the apex.
    	return Mathf.Sqrt (2 * targetJumpHeight * movement.gravity);
    }
    
    function DidJump () {
    	jump.jumping = true;
    	jump.reachedApex = false;
    	jump.lastTime = Time.time;
    	jump.lastStartHeight = transform.position.y;
    	jump.lastButtonTime = -10;
    	jump.touchedCeiling = false;
    	jump.buttonReleased = false;
    }
    
    function Update () {
    	// Make sure we are always in the 2D plane.
    	transform.position.z = 0.0;
    
    	UpdateSmoothedMovementDirection();
    	
    	AnimateCharacter();		
    
    	// Apply gravity
    	// - extra power jump modifies gravity
    	ApplyGravity ();
    
    	// Apply jumping logic
    	ApplyJumping ();
    	
    	var platformMovementOffset = Vector3.zero;
    	
    	// Moving platform support
    	if (activePlatform != null && !jump.jumping) {
    		var newGlobalPlatformPoint = activePlatform.TransformPoint(activeLocalPlatformPoint);
    		var moveDistance = (newGlobalPlatformPoint - activeGlobalPlatformPoint);
    		// Setting transform.position directly causes us to go through walls if we're on a rotating block.
    		// But it's necessary to make moving platforms work.
    		if(activePlatform.rigidbody.isKinematic && activePlatform.rigidbody.velocity.sqrMagnitude > 0.0){
    			// Moving platform. Change the position directly so the character
    			// won't fall through the platform.
    			transform.position = transform.position + moveDistance;
    		}else{
    			// Store the desired movement for use in CharacterController.Move.
    			platformMovementOffset = moveDistance;
    		}
    		lastPlatformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.smoothDeltaTime;
    	} else {
    		lastPlatformVelocity = Vector3.zero;	
    	}
    	
    	activePlatform = null;
    	
    	// Save lastPosition for velocity calculation.
    	var lastPosition = transform.position;
    	
    	// Calculate actual motion
    	var currentMovementOffset = (movement.direction * movement.speed) + Vector3 (0.0, movement.verticalSpeed, 0.0);
    	
    	// We always want the movement to be framerate independent.  Multiplying by Time.smoothDeltaTime does this.
    	currentMovementOffset *= Time.smoothDeltaTime;
    	currentMovementOffset += platformMovementOffset;
    	currentMovementOffset.x += movement.slideX * movement.slideFactor;
    	// Reset sliding to zero. It will be set in controller.Move
    	movement.slideX = 0.0;
    	
       	// Move our character!
       	// We can get null refs here
       	movement.collisionFlags = controller.Move (currentMovementOffset);
    	
    	// Calculate the velocity based on the current and previous position.  
    	// This means our velocity will only be the amount the character actually moved as a result of collisions.
    	movement.velocity = (transform.position - lastPosition) / Time.smoothDeltaTime;
    	
    	// Moving platforms support
    	if (activePlatform != null) {
    		activeGlobalPlatformPoint = transform.position;
    		activeLocalPlatformPoint = activePlatform.InverseTransformPoint (transform.position);
    	}
    	
    	// Set rotation to the move direction	
    	if (movement.direction.sqrMagnitude > 0.01)
    		transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (movement.direction), Time.smoothDeltaTime * movement.rotationSmoothing);
    	
    	// We are in jump mode but just became grounded
    	if (controller.isGrounded) {
    		if (jump.jumping) {
    			jump.jumping = false;
    			SendMessage ("DidLand", SendMessageOptions.DontRequireReceiver);
    
    			var jumpMoveDirection = movement.direction * movement.speed;
    			if (jumpMoveDirection.sqrMagnitude > 0.01)
    				movement.direction = jumpMoveDirection.normalized;
    		}
    	}
    }
    
    function OnControllerColliderHit (hit : ControllerColliderHit)
    {
    	// Make sure we are really standing on a straight platform
    	// Not on the underside of one and not falling down from it either!
    	if (hit.moveDirection.y < -0.9 && hit.normal.y > 0.9 
    		&& hit.rigidbody 
    		&& (!hit.rigidbody.isKinematic || hit.rigidbody.velocity.sqrMagnitude > 0.0)) {
    		activePlatform = hit.collider.transform;
    	}else if (jump.jumping && hit.moveDirection.y > 0.0 && hit.normal.y < 0.0 && Mathf.Abs(hit.normal.x) > 0.01){
    		movement.slideX = hit.normal.x;
    	}
    }
    
    // Various helper functions below:
    function GetSpeed () {
    	return movement.speed;
    }
    
    function GetVelocity () {
    	return movement.velocity;
    }
    
    
    function IsMoving () {
    	return movement.isMoving;
    }
    
    function IsJumping () {
    	return jump.jumping;
    }
    
    function IsTouchingCeiling () {
    	return (movement.collisionFlags & CollisionFlags.CollidedAbove) != 0;
    }
    
    function GetDirection () {
    	return movement.direction;
    }
    
    function GetHangTime() {
    	return movement.hangTime;
    }
    
    function Reset () {
    	gameObject.tag = "Player";
    }
    
    function SetControllable (controllable : boolean) {
    	canControl = controllable;
    }
    
    // Require a character controller to be attached to the same game object
    @script RequireComponent (CharacterController)
    @script AddComponentMenu ("2D Platformer/Langman Controller")

This script controls a CharacterController, which isn’t affected by Physics.gravity. Unfortunately, this script is way too complex to be modified, so you must write your script from scratch.

If you want to make something like a Gravity Guy game, the script below may be a starting point:


var speed: float = 4; // horizontal speed
var gravity: float = -10.0;
var distance: float = 10; // camera distance from the player

private var cam: Camera;
private var curVel: Vector3;
private var cc: CharacterController;

function Start () {
	curVel = Vector3.right * speed;
	cc = GetComponent(CharacterController);
	cam = Camera.main;
}

function Update(){
	// space flips gravity:
	if (Input.GetKeyDown("space")){
		// flip gravity
		gravity = -gravity;
		if (gravity > 0){ // flip the character accordingly
			transform.up = Vector3.down;
		} else {
			transform.up = Vector3.up;
		}
		curVel.y = 0; // reset vertical speed 
	}
	// add the gravity effect and limit vertical speed to +/- 10
	curVel.y = Mathf.Clamp(curVel.y + gravity * Time.deltaTime, -10, 10);
	cc.Move(curVel * Time.deltaTime); // move the player
}

function LateUpdate(){ // update camera position in LateUpdate
	var pos = transform.position;
	pos.z = -distance;
	cam.transform.position = pos;
}

This script must be attached to the player: create an empty object (the Player), reset its position, add a CharacterController component and child the player model to it).

The character will move continuously to the right (the X axis), and the key space will flip gravity and the character. The CharacterController itself can’t flip, even if the transform is turned upside down - a good thing in this case, because the movement code remains the same.