RigidbodyFPSWalker

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(JavaScript - RigidbodyFPSController.js)
(JavaScript - RigidbodyFPSController.js)
Line 18: Line 18:
 
var walkSpeed = 8.0;
 
var walkSpeed = 8.0;
 
var walkBackwardSpeed = 4.0;
 
var walkBackwardSpeed = 4.0;
 +
var sidestepSpeed = 8.0;
 
var gravity = 10.0;
 
var gravity = 10.0;
 
var maxVelocityChange = 10.0;
 
var maxVelocityChange = 10.0;
Line 25: Line 26:
  
  
// added for run (must set "Run" input to something in Project Settings / Input e.g. left shift)
+
// added for run (set to Fire2. Change in Project Settings / Input if different desired.)
 +
var canRun = true;
 +
var runSpeed = 14.0; // negative values here makes game unhappy
 +
var runBackwardSpeed = 6.0; // negative values here makes game unhappy
 +
// var runSpeedChange = 4.0; // negative values here makes game unhappy
 +
 
 +
var canRunSidestep = true;
 +
var runSidestepSpeed = 12.0;
  
var canRun = false;
 
var runSpeedChange = 4.0; // negative values here makes game unhappy
 
  
 
// added for keyboard rotation ('Horizontal' rotates instead of translates / strafe)
 
// added for keyboard rotation ('Horizontal' rotates instead of translates / strafe)
var canRotate = false;  
+
/*var canRotate = false;  
 
var rotateSpeed = 1.0;
 
var rotateSpeed = 1.0;
 
var rotateInAir = false;
 
var rotateInAir = false;
 
+
*/
 
private var grounded = false;
 
private var grounded = false;
 
private var groundVelocity : Vector3;
 
private var groundVelocity : Vector3;
Line 51: Line 57:
 
{
 
{
 
     if (grounded)
 
     if (grounded)
  {  
+
    {
       
+
 
         // Calculate how fast we should rotate
 
         // Calculate how fast we should rotate
 
+
         // var rotation = Input.GetAxis("Horizontal") * rotateSpeed;
         var rotation = Input.GetAxis("Horizontal") * rotateSpeed;
+
 
          
 
          
 
         // Set 'Horizontal' input based on rotate variable
 
         // Set 'Horizontal' input based on rotate variable
 +
        /*var targetVelocity = (canRotate) ? new Vector3(0, rotation, Input.GetAxis("Vertical"))
 +
        : new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));*/
 +
       
 +
        // Calculate how fast we should be moving
  
         var targetVelocity = (canRotate) ? new Vector3(0, rotation, Input.GetAxis("Vertical"))
+
         targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
        : new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
+
        // targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
+
 
+
        // Calculate how fast we should be moving
+
  
 
         targetVelocity = transform.TransformDirection(targetVelocity);
 
         targetVelocity = transform.TransformDirection(targetVelocity);
      if (Input.GetAxis("Vertical") > 0)
+
        if (Input.GetAxis("Vertical") > 0)
            {
+
        {
                targetVelocity *= (canRun && Input.GetButton("Run")) ? walkSpeed + runSpeedChange : walkSpeed;
+
            targetVelocity.x *= (canRun && Input.GetButton("Fire2")) ? runSpeed : walkSpeed;
          }
+
        }
 
         else  
 
         else  
            {  
+
        {  
                targetVelocity *= (canRun && Input.GetButton("Run")) ? walkBackwardSpeed + runSpeedChange : walkBackwardSpeed;
+
            targetVelocity.x *= (canRun && Input.GetButton("Fire2")) ? runBackwardSpeed : walkBackwardSpeed;
          }
+
        }
 +
 
 +
        targetVelocity.z *= (canRunSidestep && Input.GetButton("Fire2")) ? runSidestepSpeed : sidestepSpeed;
 +
       
 
          
 
          
 
         // Rotate if rotate is enabled
 
         // Rotate if rotate is enabled
 
+
         /*if (canRotate)
         if (canRotate)
+
        {
            {
+
            transform.Rotate(0, rotation, 0);
                transform.Rotate(0, rotation, 0);
+
        }
            }
+
        */
 
          
 
          
 
         // Apply a force that attempts to reach our target velocity
 
         // Apply a force that attempts to reach our target velocity
    var velocity = rigidbody.velocity;
+
        var velocity = rigidbody.velocity;
      var velocityChange = (targetVelocity - velocity) + groundVelocity;
+
        var velocityChange = (targetVelocity - velocity) + groundVelocity;
      velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
+
        velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
 
         velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
 
         velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
 
         velocityChange.y = 0;
 
         velocityChange.y = 0;
      rigidbody.AddForce(velocityChange, ForceMode.VelocityChange);
+
        rigidbody.AddForce(velocityChange, ForceMode.VelocityChange);
 
        
 
        
 
         // Jump
 
         // Jump
    if (canJump && Input.GetButton("Jump"))
+
        if (canJump && Input.GetButton("Jump"))
        {
+
        {
              rigidbody.velocity = Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
+
            rigidbody.velocity = Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
        }
+
        }
 
        
 
        
 
         grounded = false;
 
         grounded = false;
  }
+
    }
  else
+
   
 +
    else
 
     {
 
     {
      // Add in air
+
        // Add in air
 
+
 
          
 
          
 
         // Calculate how fast we should rotate
 
         // Calculate how fast we should rotate
 
+
         /*rotation = Input.GetAxis("Horizontal") * rotateSpeed;
         rotation = Input.GetAxis("Horizontal") * rotateSpeed;
+
          
         /*
+
 
         // Set 'Horizontal' input behavior based on whether we can rotate in air
 
         // Set 'Horizontal' input behavior based on whether we can rotate in air
 
+
         targetVelocity = (rotateInAir) ? new Vector3(0, rotation, Input.GetAxis("Vertical"))
         targetVelocity = (rotateInAir) ? new Vector3(0, rotation, Input.GetAxis("Vertical"))  
+
 
         : new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
 
         : new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
 
         */     
 
         */     
Line 115: Line 120:
  
 
         targetVelocity = transform.TransformDirection(targetVelocity) * inAirControl;
 
         targetVelocity = transform.TransformDirection(targetVelocity) * inAirControl;
 
       
 
        // Rotate if rotate in air is enabled.
 
 
        if (rotateInAir)
 
            {
 
                transform.Rotate(0, rotation, 0);
 
            }
 
 
          
 
          
 +
        // Rotate if rotate in air is enabled.
 +
        /*if (rotateInAir)
 +
        {
 +
            transform.Rotate(0, rotation, 0);
 +
        }
 +
        */
 
         rigidbody.AddForce(targetVelocity, ForceMode.VelocityChange);
 
         rigidbody.AddForce(targetVelocity, ForceMode.VelocityChange);
  }
+
    }
 
        
 
        
 
     // We apply gravity manually for more tuning control
 
     // We apply gravity manually for more tuning control

Revision as of 12:38, 21 October 2006

Description

This is a minor update to Joaquim's rigidbody script based first person controller; includes the latest 'air control' & the moving object / parenting additions from the forums.

Plus have added separate walk & backward speeds, run option (need to map "Run" key to in Project Settings / Input to enable), and rotate view option (instead of strafe). It's my first extensive change to a script, so feel free to change as needed!

  • original notes:

Traditionally first person controllers are done using the character controller and this is the recommended way, but sometimes you want it to use real physics. So forces automatically affect the rigidbody, and joints can be used to eg. make a rope swinging game.

The script works by adding a force in the direction of desired movement, it subtracts the current velocity from it, thus when letting go of all keys the character will stop. A maximum velocity change can be specified which will make the character come to reset slower faster and in effect apply more or less force to object the character runs into.

Usage

You can download a sample project with the complete setup here:

RigidbodyFPS.zip

JavaScript - RigidbodyFPSController.js

<javascript> var walkSpeed = 8.0; var walkBackwardSpeed = 4.0; var sidestepSpeed = 8.0; var gravity = 10.0; var maxVelocityChange = 10.0; var inAirControl = 0.1; var canJump = true; var jumpHeight = 2.0;


// added for run (set to Fire2. Change in Project Settings / Input if different desired.) var canRun = true; var runSpeed = 14.0; // negative values here makes game unhappy var runBackwardSpeed = 6.0; // negative values here makes game unhappy // var runSpeedChange = 4.0; // negative values here makes game unhappy

var canRunSidestep = true; var runSidestepSpeed = 12.0;


// added for keyboard rotation ('Horizontal' rotates instead of translates / strafe) /*var canRotate = false; var rotateSpeed = 1.0; var rotateInAir = false;

  • /

private var grounded = false; private var groundVelocity : Vector3; private var capsule : CapsuleCollider;

@script RequireComponent(Rigidbody, CapsuleCollider)

function Awake () {

  rigidbody.freezeRotation = true;
  rigidbody.useGravity = false;
  capsule = GetComponent(CapsuleCollider);

}

function FixedUpdate () {

   if (grounded)
   {
       // Calculate how fast we should rotate
       // var rotation = Input.GetAxis("Horizontal") * rotateSpeed;
       
       // Set 'Horizontal' input based on rotate variable
       /*var targetVelocity = (canRotate) ? new Vector3(0, rotation, Input.GetAxis("Vertical")) 
       : new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));*/
       
       // Calculate how fast we should be moving
       targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
       targetVelocity = transform.TransformDirection(targetVelocity);
       if (Input.GetAxis("Vertical") > 0)
       {
           targetVelocity.x *= (canRun && Input.GetButton("Fire2")) ? runSpeed : walkSpeed;
       }
       else 
       { 
           targetVelocity.x *= (canRun && Input.GetButton("Fire2")) ? runBackwardSpeed : walkBackwardSpeed;
       }
       targetVelocity.z *= (canRunSidestep && Input.GetButton("Fire2")) ? runSidestepSpeed : sidestepSpeed;
       
       
       // Rotate if rotate is enabled
       /*if (canRotate)
       {
           transform.Rotate(0, rotation, 0);
       }
       */
       
       // Apply a force that attempts to reach our target velocity
       var velocity = rigidbody.velocity;
       var velocityChange = (targetVelocity - velocity) + groundVelocity;
       velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
       velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
       velocityChange.y = 0;
       rigidbody.AddForce(velocityChange, ForceMode.VelocityChange);
      
       // Jump
       if (canJump && Input.GetButton("Jump"))
       {
           rigidbody.velocity = Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
       }
      
       grounded = false;
   }
   
   else
   {
       // Add in air
       
       // Calculate how fast we should rotate
       /*rotation = Input.GetAxis("Horizontal") * rotateSpeed;
       
       // Set 'Horizontal' input behavior based on whether we can rotate in air
       targetVelocity = (rotateInAir) ? new Vector3(0, rotation, Input.GetAxis("Vertical"))
       : new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
       */    
       targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
       targetVelocity = transform.TransformDirection(targetVelocity) * inAirControl;
       
       // Rotate if rotate in air is enabled.
       /*if (rotateInAir)
       {
           transform.Rotate(0, rotation, 0);
       }
       */
       rigidbody.AddForce(targetVelocity, ForceMode.VelocityChange);
   }
      
   // We apply gravity manually for more tuning control
   rigidbody.AddForce(Vector3 (0, -gravity * rigidbody.mass, 0));

}

function TrackGrounded (col : Collision) {

  var minimumHeight = capsule.bounds.min.y + capsule.radius;
  for (var c : ContactPoint in col.contacts) 
  {
     if (c.point.y < minimumHeight) 
     {
        //we track velocity for rigidbodies we're standing on
        if (col.rigidbody) groundVelocity = col.rigidbody.velocity;
        //and become children of non-rigidbody colliders
        else transform.parent = col.transform;
        grounded = true;
     }
  }   

}

//unparent if we are no longer standing on our parent function OnCollisionExit (col : Collision) {

  if (col.transform == transform.parent) transform.parent = null;

}

function OnCollisionStay (col : Collision) {

  TrackGrounded (col);

}

function OnCollisionEnter (col : Collision) {

  TrackGrounded (col);

}


function CalculateJumpVerticalSpeed () {

  // From the jump height and gravity we deduce the upwards speed
  // for the character to reach at the apex.
  return Mathf.Sqrt(2 * jumpHeight * gravity);

} </javascript>

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox