How does ApplyGravity() in 2DPlatformer work?

I applied the following script to make a opponent gameobject jump. It can jump but never fall down to ground.

How should I change the ApplyGravity()?

class OpponentControllerJumping 
{
	var enabled = true;
	var height = 10.0; 
	var extraHeight = 4.1;
	@System.NonSerialized
	var repeatTime = 0.05;
	@System.NonSerialized
	var timeout = 0.15;
	@System.NonSerialized
	var jumping = false;
	@System.NonSerialized
	var reachedApex = false;
	@System.NonSerialized
	var lastButtonTime = -10.0;
	@System.NonSerialized
	var lastTime = -1.0;
	@System.NonSerialized
	var lastStartHeight = 0.0;
	var jumpSpeed : float = 20;
	@System.NonSerialized
	var isJumping = false; 
	@System.NonSerialized
	var direction = Vector3.zero;
	@System.NonSerialized
	var verticalSpeed = 0.0;
	@System.NonSerialized
	var inAirVelocity = Vector3.zero;
	@System.NonSerialized
	var hangTime = 0.0;
	@System.NonSerialized
	var speed = 0.0;
	var inAirControlAcceleration = 1.0;
    var gravity = 60.0;
	var maxFallSpeed = 20.0;
}
var jump : OpponentControllerJumping;
private var activePlatform : Transform;
private var activeLocalPlatformPoint : Vector3;
private var activeGlobalPlatformPoint : Vector3;
private var lastPlatformVelocity : Vector3;

function Update () 
{	  	
	if(transform.position.y == 1)
	{
	    jump.lastButtonTime = Time.time;
	    ApplyJumping ();
	    ApplyGravity ();
	    transform.Translate(jump.direction * jump.jumpSpeed * Time.deltaTime);
	}	
}

function ApplyJumping () 
{
	if (jump.lastTime > Time.time) 
		return;

	if (transform.position.y == 1) 
	{	
		  if (jump.enabled  Time.time < jump.lastButtonTime + jump.timeout) 
		  {
			jump.direction = transform.TransformDirection( Vector3( 0, transform.position.y, 0 )); 
	        jump.direction.Normalize(); 
	        jump.direction *= jump.jumpSpeed ;
	        var h = jump.direction.y;	
	        jump.isJumping = Mathf.Abs(h) > 0.1;

            if (jump.isJumping) 
	        {		
		         jump.direction = Vector3 (0, h, 0);
		         var curSmooth = jump.extraHeight * Time.deltaTime;
		         var targetSpeed = Mathf.Min (Mathf.Abs(h), 1.0);			
		         targetSpeed *= jump.jumpSpeed;
		         jump.speed = Mathf.Lerp (jump.speed, targetSpeed, curSmooth);
		         jump.hangTime = 0.0;
	        }
	        else 
	        {
		         jump.hangTime += Time.deltaTime;
		         if (jump.isJumping)
		         {
			     jump.inAirVelocity += Vector3 (Mathf.Sign(h), 0, 0) * Time.deltaTime * jump.inAirControlAcceleration;
		    }
	      }
	
			jump.verticalSpeed = CalculateJumpVerticalSpeed (jump.height);
			jump.inAirVelocity = lastPlatformVelocity;
			SendMessage ("DidJump", SendMessageOptions.DontRequireReceiver);
		}
	}
}

function ApplyGravity () 
{
	if (transform.position.y == 1)
	{
		jump.verticalSpeed = -jump.gravity * Time.deltaTime;
	}
	else
	{
		jump.verticalSpeed -= jump.gravity * Time.deltaTime;
	}
	jump.verticalSpeed = Mathf.Max (jump.verticalSpeed, -jump.maxFallSpeed);
}

function CalculateJumpVerticalSpeed (targetJumpHeight : float) 
{
	return Mathf.Sqrt (2 * targetJumpHeight * jump.gravity);
}

function DidJump () 
{
	jump.jumping = true;
	jump.reachedApex = false;
	jump.lastTime = Time.time;
	jump.lastStartHeight = transform.position.y;
	jump.lastButtonTime = -10;
}

You could look through the FPSWalker script and see how that handles falling back down to Earth and adapt that to yours?

You are setting jump.verticalSpeed in the ApplyGravity function, but you don’t refer to that value in the Update function. I’m not really sure what the character is supposed to be doing. Is it jumping from place to place or does it walk around but also jump up into the air?

  1. It is an opponent GameObject, NOT character
  2. it walks around but also jumps up into the air

Walk and Jump

I edited the code, it still jumps to air but not down to ground where y = 1.

if(transform.position.y == 1)
	{
	    jump.lastButtonTime = Time.time;
	    ApplyJumping ();
	    transform.Translate(jump.direction * jump.jumpSpeed * Time.deltaTime);
	    ApplyGravity ();
	    transform.Translate(jump.inAirVelocity * jump.verticalSpeed * Time.deltaTime);
	}

Hi

Any advice on the code?

You might find it easier to use a CharacterController for this (despite the name, you can use them for enemy NPCs as well). That way, you can create gravity simply by adding a downward component to the movement vector each frame.

In Opponent GameObject, I added the following code:

private var controller : CharacterController;

function Awake () 
{
	movement.direction = transform.TransformDirection (Vector3.forward);
	controller = GetComponent (CharacterController);
}

function ApplyJumping () {
	if (jump.lastTime > Time.time) 
		return;

	if (controller.isGrounded) {	
		if (jump.enabled  Time.time < jump.lastButtonTime + jump.timeout) {
			movement.verticalSpeed = CalculateJumpVerticalSpeed (jump.height);
			movement.inAirVelocity = lastPlatformVelocity;
			SendMessage ("DidJump", SendMessageOptions.DontRequireReceiver);
		}
	}
}

function ApplyGravity () 
{
	if (controller.isGrounded)
		movement.verticalSpeed = -movement.gravity * Time.deltaTime;
	else
		movement.verticalSpeed -= movement.gravity * Time.deltaTime;
	movement.verticalSpeed = Mathf.Max (movement.verticalSpeed, -movement.maxFallSpeed);
}

function CalculateJumpVerticalSpeed (targetJumpHeight : float) 
{
	return Mathf.Sqrt (2 * targetJumpHeight * jump.gravity);
}

function DidJump () 
{
	jump.jumping = true;
	jump.reachedApex = false;
	jump.lastTime = Time.time;
	jump.lastStartHeight = transform.position.y;
	jump.lastButtonTime = -10;
}

function Update () 
{	    	
	if(controller.isGrounded)
	{
	    jump.lastButtonTime = Time.time;
	    ApplyJumping ();
	    ApplyGravity ();
	}	
}

@script RequireComponent (CharacterController)

But, it throws error:

MissingComponentException: There is no ‘CharacterController’ attached to the “Opponent” game object, but a script is trying to access it.
You probably need to add a CharacterController to the game object “Opponent”. Or your script needs to check if the component is attached before using it.

Since I added Character Controller to Character, I cannot add Character Controller to Opponent gameobject.

How should I work it out?

I searched and read

http://forum.unity3d.com/viewtopic.php?p=271578

http://unity3d.com/support/documentation/ScriptReference/index.Accessing_Other_Game_Objects.html

and edited the code:

controller = GameObject.Find("Opponent").GetComponent (CharacterController);

But, it has the same MissingComponentException when I run it.