RigidbodyFPSWalker
From Unify Community Wiki
(Difference between revisions)
(→Description) |
(I just added the C# translation) |
||
(6 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
==Description== | ==Description== | ||
− | This is a | + | 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. |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | 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 15: | Line 10: | ||
==JavaScript - RigidbodyFPSController.js== | ==JavaScript - RigidbodyFPSController.js== | ||
− | <javascript> | + | <syntaxhighlight lang="javascript"> |
− | var | + | var speed = 10.0; |
− | + | ||
var gravity = 10.0; | var gravity = 10.0; | ||
var maxVelocityChange = 10.0; | var maxVelocityChange = 10.0; | ||
− | |||
var canJump = true; | var canJump = true; | ||
var jumpHeight = 2.0; | var jumpHeight = 2.0; | ||
+ | private var grounded = false; | ||
+ | @script RequireComponent(Rigidbody, CapsuleCollider) | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
function Awake () | function Awake () | ||
{ | { | ||
− | + | rigidbody.freezeRotation = true; | |
− | + | rigidbody.useGravity = false; | |
− | + | ||
} | } | ||
− | + | ||
function FixedUpdate () | function FixedUpdate () | ||
{ | { | ||
if (grounded) | if (grounded) | ||
− | { | + | { |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
// Calculate how fast we should be moving | // Calculate how fast we should be moving | ||
− | + | var targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); | |
targetVelocity = transform.TransformDirection(targetVelocity); | targetVelocity = transform.TransformDirection(targetVelocity); | ||
− | + | targetVelocity *= speed; | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
// 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) | + | var velocityChange = (targetVelocity - velocity); |
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); | |
− | + | } | |
− | + | ||
− | + | ||
} | } | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
// We apply gravity manually for more tuning control | // We apply gravity manually for more tuning control | ||
rigidbody.AddForce(Vector3 (0, -gravity * rigidbody.mass, 0)); | rigidbody.AddForce(Vector3 (0, -gravity * rigidbody.mass, 0)); | ||
+ | |||
+ | grounded = false; | ||
} | } | ||
− | function | + | function OnCollisionStay () |
{ | { | ||
− | + | grounded = true; | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
} | } | ||
− | + | function CalculateJumpVerticalSpeed () | |
− | function | + | |
{ | { | ||
− | + | // 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); | ||
} | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | |||
− | |||
− | |||
− | |||
− | |||
− | + | ==C# - RigidbodyFPSController.cs== | |
− | + | <syntaxhighlight lang="csharp"> | |
− | + | using UnityEngine; | |
− | + | using System.Collections; | |
− | + | [RequireComponent (typeof (Rigidbody))] | |
− | + | [RequireComponent (typeof (CapsuleCollider))] | |
− | { | + | |
− | // From the jump height and gravity we deduce the upwards speed | + | public class CharacterControls : MonoBehaviour { |
− | + | ||
− | + | public float speed = 10.0f; | |
− | } | + | public float gravity = 10.0f; |
− | </ | + | public float maxVelocityChange = 10.0f; |
+ | public bool canJump = true; | ||
+ | public float jumpHeight = 2.0f; | ||
+ | private bool grounded = false; | ||
+ | |||
+ | |||
+ | |||
+ | void Awake () { | ||
+ | rigidbody.freezeRotation = true; | ||
+ | rigidbody.useGravity = false; | ||
+ | } | ||
+ | |||
+ | void FixedUpdate () { | ||
+ | if (grounded) { | ||
+ | // Calculate how fast we should be moving | ||
+ | Vector3 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 | ||
+ | Vector3 velocity = rigidbody.velocity; | ||
+ | Vector3 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 = new Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // We apply gravity manually for more tuning control | ||
+ | rigidbody.AddForce(new Vector3 (0, -gravity * rigidbody.mass, 0)); | ||
+ | |||
+ | grounded = false; | ||
+ | } | ||
+ | |||
+ | void OnCollisionStay () { | ||
+ | grounded = true; | ||
+ | } | ||
+ | |||
+ | float 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); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> |
Latest revision as of 10:25, 7 May 2012
Contents |
[edit] 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.
[edit] Usage
You can download a sample project with the complete setup here:
[edit] JavaScript - RigidbodyFPSController.js
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); }
[edit] C# - RigidbodyFPSController.cs
using UnityEngine; using System.Collections; [RequireComponent (typeof (Rigidbody))] [RequireComponent (typeof (CapsuleCollider))] public class CharacterControls : MonoBehaviour { public float speed = 10.0f; public float gravity = 10.0f; public float maxVelocityChange = 10.0f; public bool canJump = true; public float jumpHeight = 2.0f; private bool grounded = false; void Awake () { rigidbody.freezeRotation = true; rigidbody.useGravity = false; } void FixedUpdate () { if (grounded) { // Calculate how fast we should be moving Vector3 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 Vector3 velocity = rigidbody.velocity; Vector3 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 = new Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z); } } // We apply gravity manually for more tuning control rigidbody.AddForce(new Vector3 (0, -gravity * rigidbody.mass, 0)); grounded = false; } void OnCollisionStay () { grounded = true; } float 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); } }