RigidbodyFPSWalker

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(Description)
m (Reverted edits by Casemon (Talk); changed back to last version by Joeante)
Line 1: Line 1:
 
==Description==
 
==Description==
Slight update to Joaquim's rigidbody script based first person controller; includes the latest 'air control' & the moving object / parenting  additions from the forums. Plus added separate walk, backward & sidestep speeds, & run toggles (Fire2 / Left Alt). My first Wiki script change... it was fun!
+
This is a rigidbody based first person controller. 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.
 
+
*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.
 
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.
Line 14: Line 11:
 
==JavaScript - RigidbodyFPSController.js==
 
==JavaScript - RigidbodyFPSController.js==
 
<javascript>
 
<javascript>
var walkSpeed = 8.0;
+
var speed = 10.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;
var inAirControl = 0.1;
 
 
var canJump = true;
 
var canJump = true;
 
var jumpHeight = 2.0;
 
var jumpHeight = 2.0;
 +
private var grounded = false;
  
 +
@script RequireComponent(Rigidbody, CapsuleCollider)
  
// 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 ()
 
function Awake ()
 
{
 
{
  rigidbody.freezeRotation = true;
+
rigidbody.freezeRotation = true;
  rigidbody.useGravity = false;
+
rigidbody.useGravity = false;
  capsule = GetComponent(CapsuleCollider);
+
 
}
 
}
+
 
 
function FixedUpdate ()
 
function FixedUpdate ()
 
{
 
{
    if (grounded)
+
if (grounded)
    {
+
{
        // Calculate how fast we should rotate
+
// Calculate how fast we should be moving
        // var rotation = Input.GetAxis("Horizontal") * rotateSpeed;
+
var targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
       
+
targetVelocity = transform.TransformDirection(targetVelocity);
        // Set 'Horizontal' input based on rotate variable
+
targetVelocity *= speed;
        /*var targetVelocity = (canRotate) ? new Vector3(0, rotation, Input.GetAxis("Vertical"))
+
        : new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));*/
+
// Apply a force that attempts to reach our target velocity
       
+
var velocity = rigidbody.velocity;
        // Calculate how fast we should be moving
+
var velocityChange = (targetVelocity - velocity);
 
+
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
        targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
+
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
 
+
velocityChange.y = 0;
        targetVelocity = transform.TransformDirection(targetVelocity);
+
rigidbody.AddForce(velocityChange, ForceMode.VelocityChange);
        if (Input.GetAxis("Vertical") > 0)
+
        {
+
// Jump
            targetVelocity.x *= (canRun && Input.GetButton("Fire2")) ? runSpeed : walkSpeed;
+
if (canJump && Input.GetButton("Jump"))
        }
+
{
        else
+
rigidbody.velocity = Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
        {
+
}
            targetVelocity.x *= (canRun && Input.GetButton("Fire2")) ? runBackwardSpeed : walkBackwardSpeed;
+
}
        }
+
 
+
// We apply gravity manually for more tuning control
        targetVelocity.z *= (canRunSidestep && Input.GetButton("Fire2")) ? runSidestepSpeed : sidestepSpeed;
+
rigidbody.AddForce(Vector3 (0, -gravity * rigidbody.mass, 0));
       
+
       
+
grounded = false;
        // 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)  
+
function OnCollisionStay ()
 
{
 
{
  var minimumHeight = capsule.bounds.min.y + capsule.radius;
+
grounded = true;
  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 CalculateJumpVerticalSpeed ()
function OnCollisionExit (col : Collision)  
+
 
{
 
{
  if (col.transform == transform.parent) transform.parent = null;
+
// 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);
 
}
 
}
 
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>
 
</javascript>

Revision as of 00:20, 24 July 2007

Description

This is a rigidbody based first person controller. 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 speed = 10.0; var gravity = 10.0; var maxVelocityChange = 10.0; var canJump = true; var jumpHeight = 2.0; private var grounded = false;

@script RequireComponent(Rigidbody, CapsuleCollider)

function Awake () { rigidbody.freezeRotation = true; rigidbody.useGravity = false; }

function FixedUpdate () { if (grounded) { // Calculate how fast we should be moving var targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); targetVelocity = transform.TransformDirection(targetVelocity); targetVelocity *= speed;

// Apply a force that attempts to reach our target velocity var velocity = rigidbody.velocity; var velocityChange = (targetVelocity - velocity); 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); } }

// We apply gravity manually for more tuning control rigidbody.AddForce(Vector3 (0, -gravity * rigidbody.mass, 0));

grounded = false; }

function OnCollisionStay () { grounded = true; }

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