Hey friends,
I translated the demo script into an input action script for Prime 31's open source 2d Character Controller:
https://github.com/prime31/CharacterController2DAdd the CharacterController2D Component to your player object and an FSM with this action on it. Be sure to configure the CharacterController2D with the appropriate tags and layers and what not.
The action uses the Horizontal/Vertical input axis. The original script controlled the animations as well, this script does not do this. Id suggest using an Axis Event to control animations.
using UnityEngine;
using System.Collections;
using Prime31;
namespace HutongGames.PlayMaker.Actions
{
[ActionCategory(ActionCategory.Character)]
[Tooltip("Moves a Game Object with a Character Controller 2D from Prime31")]
public class P31CharacerterController2D : FsmStateAction
{
[Tooltip("The GameObject to move.")]
public FsmOwnerDefault gameObject;
[Tooltip("Gravity is applied automatically")]
public FsmFloat gravity;
[Tooltip("Horizontal speed.")]
public FsmFloat runSpeed;
[Tooltip("How fast the player can change directions. Higher equal faster")]
public FsmFloat groundDamping;
[Tooltip("How much control we have over the character while in the air")]
public FsmFloat inAirDamping;
[Tooltip("How high we can jump")]
public FsmFloat jumpHeight;
// movement config
//public float gravity = -25f;
//public float runSpeed = 8f;
//public float groundDamping = 20f; // how fast do we change direction? higher means faster
//public float inAirDamping = 5f;
//public float jumpHeight = 3f;
[HideInInspector]
private float normalizedHorizontalSpeed = 0;
private CharacterController2D _controller;
private RaycastHit2D _lastControllerColliderHit;
private Vector3 _velocity;
public override void Reset()
{
gravity = -25f;
runSpeed = 8f;
groundDamping = 20f;
inAirDamping = 5f;
jumpHeight = 3f;
}
public void OnStart()
{
var go = Fsm.GetOwnerDefaultTarget(gameObject);
_controller = go.GetComponent<CharacterController2D>();
// listen to some events for illustration purposes
_controller.onControllerCollidedEvent += onControllerCollider;
_controller.onTriggerEnterEvent += onTriggerEnterEvent;
_controller.onTriggerExitEvent += onTriggerExitEvent;
}
#region Event Listeners
void onControllerCollider( RaycastHit2D hit )
{
// bail out on plain old ground hits cause they arent very interesting
if( hit.normal.y == 1f )
return;
// logs any collider hits if uncommented. it gets noisy so it is commented out for the demo
//Debug.Log( "flags: " + _controller.collisionState + ", hit.normal: " + hit.normal );
}
void onTriggerEnterEvent( Collider2D col )
{
Debug.Log( "onTriggerEnterEvent: " + col.gameObject.name );
}
void onTriggerExitEvent( Collider2D col )
{
Debug.Log( "onTriggerExitEvent: " + col.gameObject.name );
}
#endregion
// the Update loop contains a very simple example of moving the character around and controlling the animation
public override void OnUpdate()
{
var go = Fsm.GetOwnerDefaultTarget(gameObject);
_controller = go.GetComponent<CharacterController2D>();
// listen to some events for illustration purposes
_controller.onControllerCollidedEvent += onControllerCollider;
_controller.onTriggerEnterEvent += onTriggerEnterEvent;
_controller.onTriggerExitEvent += onTriggerExitEvent;
if (_controller.isGrounded)
_velocity.y = 0;
if( Input.GetAxisRaw("Horizontal") > 0)
{
normalizedHorizontalSpeed = 1;
if( go.transform.localScale.x < 0f )
go.transform.localScale = new Vector3( -go.transform.localScale.x, go.transform.localScale.y, go.transform.localScale.z );
}
else if( Input.GetAxisRaw("Horizontal") < 0 )
{
normalizedHorizontalSpeed = -1;
if( go.transform.localScale.x > 0f )
go.transform.localScale = new Vector3( -go.transform.localScale.x, go.transform.localScale.y, go.transform.localScale.z );
}
else
{
normalizedHorizontalSpeed = 0;
}
// we can only jump whilst grounded
if( _controller.isGrounded && Input.GetAxisRaw("Vertical") > 0)
{
_velocity.y = Mathf.Sqrt( 2f * jumpHeight.Value * -gravity.Value );
}
// apply horizontal speed smoothing it. dont really do this with Lerp. Use SmoothDamp or something that provides more control
var smoothedMovementFactor = _controller.isGrounded ? groundDamping.Value : inAirDamping.Value; // how fast do we change direction?
_velocity.x = Mathf.Lerp( _velocity.x, normalizedHorizontalSpeed * runSpeed.Value, Time.deltaTime * smoothedMovementFactor );
// apply gravity before moving
_velocity.y += gravity.Value * Time.deltaTime;
// if holding down bump up our movement amount and turn off one way platform detection for a frame.
// this lets uf jump down through one way platforms
if( _controller.isGrounded && Input.GetAxisRaw("Vertical") < 0)
{
_velocity.y *= 3f;
_controller.ignoreOneWayPlatformsThisFrame = true;
}
_controller.move( _velocity * Time.deltaTime );
// grab our current _velocity to use as a base for all calculations
_velocity = _controller.velocity;
}
}
}