Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

[Released] 2D Platform Controller

Discussion in 'Assets and Asset Store' started by JohnnyA, Mar 11, 2013.

  1. indy2005

    indy2005

    Joined:
    Aug 22, 2009
    Posts:
    81
    ...also, in platformers, the longer you hold the button down, the longer the jump...how do you achieve that effect?

    Thanks

    i
     
  2. indy2005

    indy2005

    Joined:
    Aug 22, 2009
    Posts:
    81
    I cant work this framework out. I take a demo scene, add my own bone animation from Smooth Move, replicate the movement and jump settings from the 2D toolkit sample, and when I run the scene, Jump...it leaps 40 feet in the air like superman....
     
  3. indy2005

    indy2005

    Joined:
    Aug 22, 2009
    Posts:
    81
    Now I add a rigid body to my sprite, and when it hits a platform, the thing shuffles off to the right on it's own!

    I was hoping this would simplify the workflow....I appreciate it is likely all my fault, but wasn't expecting it to be so difficult to drop your stuff in and have it work out of the box.
     
  4. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Hi Indy, please use the support channels for specific support requests. As to your general questions:

    1. For a less floaty jump increase Physics.gravity in the Unity settings (and maybe movement.terminal velocity too).

    2. Set the jump held time and the jump frame velocity in the jump details:

    Code (csharp):
    1.  
    2. /// <summary>
    3.     /// How long after pressing jump it can be held down to add extra force. use this if you want jumps to
    4.     /// get bigger when you hold jump.
    5.     /// </summary>
    6.     public float jumpHeldTime = 0.25f;
    7.     /// <summary>
    8.     /// How much extra acceleration is added when you hold the jump button down. Set to zero for fixed height jumps.
    9.     /// </summary>
    10.     public float jumpFrameVelocity = 25.0f;
    11.  
    3. You probably need to adjust gravity.

    4. The system is a replacement for rigidbodies so you cant add rigidbodies to your character (unless they are correctly-configured for the trigger system, but get movement sorted first).

    And I am aware that it can be a bit overwhelming, thats one of the things I am trying to improve in PlatformerPRO. More wizards, lots of help boxes, and less confusing settings.
     
  5. indy2005

    indy2005

    Joined:
    Aug 22, 2009
    Posts:
    81
    Great thanks...just seen the setupPhysics2D script attached to a game object in the scene...didn't spot that before.

    I removed the rigidbody, but now my character hits the ground and shuffles off to the right on his own accord!
     
  6. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Hi Indy, firstly, you can always send me your project file and I'll take a look.

    Other than this my recommendation is to start with a sample scene and adjust one thing at a time then test, until you have your base movements up and running.

    As to shuffling it suggests some kind of raycast misconfiguration (unless you left the collider on the character, you need to remove both the rigidbody and collider).

    - John A
     
  7. tahmzad

    tahmzad

    Joined:
    Jan 24, 2014
    Posts:
    15
    Hi John, hope you are feeling well man. I was looking at this asset http://u3d.as/content/cinopt-studios/2d-action-platformer-starter-kit-mobile-ready/56H for enemies in my game. Your 2DPC is perfect for my platforming part but i still need collectables such as health and items to throw at enemies + plus some enemies obviously. I was just wondering if you ever had a look at it?

    A small request - if you ever get a chance, would it be possible to make a video on changing hero character with custom character and animations?

    My uni project is due in a couple of months so that is probably why i am panicking a bit right now :). Looking forward to beta version.

    Thanks man.
     
  8. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Hi tahmzad,

    there are some basic enemy and collectible samples in 2DPC. In Platformer PRO collectibles, enemies health, etc are going to be as much a part of the kit as basic movement, you can already see some progress on youtube:

    http://www.youtube.com/watch?v=q3ouianebXU

    Some more tutorials will be on the agenda after the release of PRO. I can't really hold that up any more than I already have!

    As to your uni project it might be a bit tight to use Platformer PRO, so you might have to think about expanding the examples from 2DPC.

    - John A
     
  9. tahmzad

    tahmzad

    Joined:
    Jan 24, 2014
    Posts:
    15
    Thanks for the quick reply John. I will be done with my level design in about 2 weeks. WIll use what i can from 2DPC and use rest when PRO beta hits, hopefully sooner than later. From the looks of it, i only need two or three things from PRO at most. Keep doing what you are doing mate.

    Thanks.
     
  10. indy2005

    indy2005

    Joined:
    Aug 22, 2009
    Posts:
    81
    Hi

    Thanks. You have collides on your hit targets in your scenes?

    I
     
  11. indy2005

    indy2005

    Joined:
    Aug 22, 2009
    Posts:
    81

    He was shuffling because I put a side ray cast too close to the main characters feet (at ground level)
     
  12. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    That would do it, you need a little leeway.
     
  13. indy2005

    indy2005

    Joined:
    Aug 22, 2009
    Posts:
    81
    Hi,

    I cant seem to trigger my Falling animation. I copied your script and adjusted it slightly earlier in this thread for SmoothMoves, but the number of states it handles is very small. I am assuming something triggers the state from jumping to airborne, and then from airborne to falling, but can't see where.

    The number of states in the example you gave doesn't include wall jumping, wall sliding, ledge hanging or an airborne state, looking at some of the 2d samples the state transitions are very many.

    using UnityEngine;
    using System.Collections;

    using UnityEngine;
    using System.Collections;

    using System.Collections.Generic;

    /**
    * A sample animation classes that works with 3d models.
    */

    public class SmoothMovesAnimator : MonoBehaviour {

    public RaycastCharacterController2D controller;
    public SmoothMoves.BoneAnimation animation;
    protected int currentDirection;
    protected CharacterState currentState;

    void Start(){
    // Set all animations to loop
    animation.wrapMode = WrapMode.Loop;
    // except jumping
    if (animation["Jump"] != null) {
    animation["Jump"].wrapMode = WrapMode.Once;
    animation["Jump"].layer = 1;
    }

    // Register listeners
    controller.CharacterAnimationEvent += new RaycastCharacterController2D.CharacterControllerEventDelegate(CharacterAnimationEvent);
    }

    /// <summary>
    /// Respond to an animation event.
    /// </summary>
    /// <param name='state'>
    /// State.
    /// </param>
    /// <param name='previousState'>
    /// Previous state.
    /// </param>
    public void CharacterAnimationEvent (CharacterState state, CharacterState previousState) {
    switch (state) {
    case CharacterState.IDLE: Idle(); break;
    case CharacterState.WALKING: Walk(); break;
    case CharacterState.RUNNING: Run(); break;
    case CharacterState.JUMPING: Jump(); break;

    case CharacterState.FALLING: Fall(); break;
    case CharacterState.DOUBLE_JUMPING: Jump(); break;
    case CharacterState.WALL_JUMPING: Jump(); break;
    case CharacterState.HOLDING: Hold(); break;
    case CharacterState.CLIMBING: Climb(); break;
    }
    }

    protected void Idle () {
    Debug.Log("Animation: Idle");
    animation.Play("Idle");
    CheckDirection();
    }

    protected void Walk () {
    Debug.Log("Animation: Walk");
    animation.Play("Walk");
    CheckDirection();
    }

    protected void Run () {
    Debug.Log("Animation: Run");
    animation.Play("Run");
    CheckDirection();
    }


    protected void Jump() {
    Debug.Log("Animation: Jump");
    animation.Play("Jump");
    CheckDirection();
    }



    protected void Fall() {
    Debug.Log("Animation: Fall");
    animation.Play("Fall");
    CheckDirection();
    }

    protected void Hold() {
    Debug.Log("Animation: Hold");
    animation.Play("Hold");
    transform.localRotation = Quaternion.Euler (0.0f, 180.0f, 0.0f);
    }

    protected void Climb() {
    Debug.Log("Animation: Climb");
    animation.Play("Idle");
    transform.localRotation = Quaternion.Euler (0.0f, 180.0f, 0.0f);
    }


    /*protected void CheckDirection(){
    // You might need to switch 270 and 90 for other values depending on orientation of your model
    if (controller.Velocity.x > 0 ) {
    transform.localRotation = Quaternion.Euler (0.0f, 270.0f, 0.0f);
    } else if (controller.Velocity.x < 0) {
    transform.localRotation = Quaternion.Euler (0.0f, 90.0f, 0.0f);
    }
    }*/

    protected void CheckDirection() {
    currentDirection = controller.CurrentDirection;
    // Rope states
    if (currentState == CharacterState.ROPE_HANGING ||
    currentState == CharacterState.ROPE_CLIMBING) {
    // No need to rotate, stay in existing direction
    }
    // Climbing states
    else if (currentState == CharacterState.CLIMBING ||
    currentState == CharacterState.HOLDING ||
    currentState == CharacterState.CLIMB_TOP_OF_LADDER_UP ||
    currentState == CharacterState.CLIMB_TOP_OF_LADDER_DOWN) {
    // No need to rotate, stay in existing direction
    }
    // Wall slide
    else if (currentState == CharacterState.WALL_SLIDING) {
    if (controller.CurrentDirection > 0 ) {
    transform.localScale = new Vector3(1,1,1);
    } else if (controller.CurrentDirection < 0) {
    transform.localScale = new Vector3(-1,1,1);
    }
    }
    // Directional states
    else {
    if (controller.CurrentDirection > 0 ) {
    transform.localScale = new Vector3(1,1,1);
    } else if (controller.CurrentDirection < 0) {
    transform.localScale = new Vector3(-1,1,1);
    }
    }
    }
    }
     
  14. indy2005

    indy2005

    Joined:
    Aug 22, 2009
    Posts:
    81
    OK stole some code from the Hero2D animator controller and made some adjustments, but falling never gets called. Whats the trigger from idle, to jumping to airborne and then to falling?

    using UnityEngine;
    using System.Collections;

    using UnityEngine;
    using System.Collections;

    using System.Collections.Generic;

    /**
    * A sample animation classes that works with 3d models.
    */

    public class SmoothMovesAnimator : MonoBehaviour {

    public RaycastCharacterController2D controller;
    public SmoothMoves.BoneAnimation animation;
    protected int currentDirection;
    protected CharacterState currentState;
    private CharacterState previousState;

    public bool playWalkAnimationsWhileSwimming = true;

    private Quaternion targetRotation;

    private Vector3 rootOffset;

    void Start(){
    // Set all animations to loop
    animation.wrapMode = WrapMode.Loop;
    // except a few
    if (animation["Jump"] != null) {
    animation["Jump"].wrapMode = WrapMode.Once;
    }
    if (animation ["Slide3"] != null) {
    animation["Slide3"].wrapMode = WrapMode.Once;
    }
    if (animation ["Ledge_Climb"] != null) {
    animation["Ledge_Climb"].wrapMode = WrapMode.Clamp;
    }
    if (animation["Stun2"] != null) {
    animation["Stun2"].wrapMode = WrapMode.Once;
    }
    if (animation["Crouch"] != null) {
    animation["Crouch"].wrapMode = WrapMode.Clamp;
    }

    // Store root offset, we use this to reset position after animations this is only here to deal with a few rogue animations changing our root position
    // you probably wont need it!
    rootOffset = transform.localPosition;

    // Register listeners
    controller.CharacterAnimationEvent += new RaycastCharacterController2D.CharacterControllerEventDelegate (CharacterAnimationEvent);
    }

    /*void Start(){
    // Set all animations to loop
    animation.wrapMode = WrapMode.Loop;
    // except jumping
    if (animation["Jump"] != null) {
    animation["Jump"].wrapMode = WrapMode.Once;
    animation["Jump"].layer = 1;
    }

    // Register listeners
    controller.CharacterAnimationEvent += new RaycastCharacterController2D.CharacterControllerEventDelegate(CharacterAnimationEvent);
    }
    */

    /// <summary>
    /// Respond to an animation event.
    /// </summary>
    /// <param name='state'>
    /// State.
    /// </param>
    /// <param name='previousState'>
    /// Previous state.
    /// </param>
    ///
    ///

    /*public void CharacterAnimationEvent (CharacterState state, CharacterState previousState) {
    switch (state) {
    case CharacterState.IDLE: Idle(); break;
    case CharacterState.WALKING: Walk(); break;
    case CharacterState.RUNNING: Run(); break;
    case CharacterState.JUMPING: Jump(); break;

    case CharacterState.FALLING: Fall(); break;
    case CharacterState.DOUBLE_JUMPING: Jump(); break;
    case CharacterState.WALL_JUMPING: Jump(); break;
    case CharacterState.HOLDING: Hold(); break;
    case CharacterState.CLIMBING: Climb(); break;
    }
    }*/

    public void CharacterAnimationEvent (CharacterState state, CharacterState previousState) {
    currentState = state;
    this.previousState = previousState;
    transform.localPosition = rootOffset;
    switch (state) {
    case CharacterState.IDLE: Idle(previousState); break;
    case CharacterState.WALKING: Walk(); break;
    case CharacterState.RUNNING: Run(); break;
    case CharacterState.SLIDING: Slide(); break;
    case CharacterState.JUMPING: Jump(); break;
    case CharacterState.AIRBORNE: Airborne(); break;
    case CharacterState.FALLING: Fall(); break;
    case CharacterState.DOUBLE_JUMPING: Jump(); break;
    case CharacterState.WALL_JUMPING: Jump(); break;
    case CharacterState.HOLDING: Hold(previousState); break;
    case CharacterState.CLIMBING: Climb(); break;
    case CharacterState.CLIMB_TOP_OF_LADDER_UP: ClimbTopUp(); break;
    case CharacterState.CLIMB_TOP_OF_LADDER_DOWN: ClimbTopDown(); break;
    case CharacterState.LEDGE_HANGING: LedgeHang(); break;
    case CharacterState.LEDGE_CLIMBING: LedgeClimb(); break;
    case CharacterState.LEDGE_CLIMB_FINISHED: Idle (previousState); break;
    case CharacterState.ROPE_CLIMBING: RopeClimb(); break;
    case CharacterState.ROPE_SWING: RopeSwing();break;
    case CharacterState.ROPE_HANGING: RopeHang();break;
    case CharacterState.WALL_SLIDING: WallSlide(); break;
    case CharacterState.CROUCHING: Crouch(); break;
    case CharacterState.CROUCH_SLIDING: CrouchSlide(); break;
    case CharacterState.STUNNED: Stunned(previousState); break;
    case CharacterState.PUSHING: Push(); break;
    case CharacterState.PULLING: Pull(); break;
    }
    }


    protected void Idle (CharacterState previousState) {
    Debug.Log("Idle");
    animation.CrossFade("Idle");
    CheckDirection();
    }

    protected void Walk ()
    {
    if (playWalkAnimationsWhileSwimming || !controller.IsSwimming) {
    Debug.Log("Running");
    animation.CrossFade ("Run");
    } else {
    Debug.Log("Falling");
    animation.CrossFade("Fall");
    }
    CheckDirection();
    }

    protected void Run ()
    {
    if (playWalkAnimationsWhileSwimming || !controller.IsSwimming) {
    Debug.Log("Running");
    animation.CrossFade ("Run");
    } else {
    Debug.Log("Falling");
    animation.CrossFade("Fall");
    }
    CheckDirection();
    }

    protected void Slide ()
    {
    if (playWalkAnimationsWhileSwimming || !controller.IsSwimming) {
    Debug.Log("Slide3 ing");
    animation.CrossFade ("Slide3");
    } else {
    Debug.Log("Falling");
    animation.CrossFade("Fall");
    }
    CheckDirection();
    }

    protected void Jump() {
    Debug.Log("Jumping");
    animation.CrossFade("Jump");
    CheckDirection();
    }

    protected void Airborne() {
    Debug.Log("Airborne");
    animation.CrossFade("Airborne");
    CheckDirection();
    }


    protected void Fall() {
    Debug.Log("Falling");
    animation.CrossFade("Fall");
    CheckDirection();
    }

    protected void Hold(CharacterState previousState) {
    if (previousState != CharacterState.CLIMBING) {
    Debug.Log("Climbing");
    animation.CrossFade ("climb");
    }
    animation["Climb"].speed = 0;
    animation["Ledge_Climb"].speed = 0;
    if (!animation.IsPlaying("Ledge_Climb")) {
    transform.localPosition= new Vector3(0, -0.75f, -1);
    }
    }

    protected void Climb() {
    animation["Climb"].speed = 1;
    Debug.Log("Climbing");
    animation.CrossFade("Climb");
    transform.localPosition = new Vector3(0, -0.75f,-1);
    }

    protected void ClimbTopUp() {
    animation["Ledge_Climb"].speed = 1;
    if ( animation["Ledge_Climb"].normalizedTime < 0.4f) animation["Ledge_Climb"].normalizedTime = 0.4f;
    Debug.Log("Ledge Climbing");
    animation.CrossFade("Ledge_Climb");
    }

    protected void ClimbTopDown() {
    //transform.localRotation = Quaternion.Euler (0.0f, 0.0f, 0.0f);
    animation["Ledge_Climb"].speed = -1;
    animation["Ledge_Climb"].normalizedTime = 0.9f;
    // if ( animation["ledge_climb"].normalizedTime < 0.4f) animation["ledge_climb"].normalizedTime = 0.4f;
    animation.Play("Ledge_Climb");
    }

    protected void LedgeHang() {
    Debug.Log("Ledge Hanging");
    animation.CrossFade("Ledge_Hang");
    }

    protected void LedgeClimb() {
    animation["ledge_climb"].speed = 1;
    Debug.Log("Ledge Climbing");
    animation.Play("ledge_climb");
    }

    protected void RopeHang() {
    Debug.Log("Rope Hanging");
    animation.CrossFade("rope_hang");
    }

    protected void RopeSwing() {
    // No animation here as yet
    }

    protected void RopeClimb() {
    Debug.Log("Rope Climbing");
    animation.CrossFade("Rope_Climb");
    }

    protected void WallSlide() {
    Debug.Log("Wall Sliding");
    animation.CrossFade("Wallslide");
    }

    protected void Crouch() {
    Debug.Log("Crouch3 ing");
    animation.CrossFade("Crouch3");
    }

    protected void CrouchSlide() {
    Debug.Log("Ground sliding");
    animation.CrossFade("Groundslide");
    }

    protected void Push() {
    Debug.Log("Pushing");
    animation.CrossFade ("Push");
    }

    protected void Pull() {
    Debug.Log("Pulling");
    animation.CrossFade ("Pull");
    }

    protected void Stunned(CharacterState previousState) {
    // Don't play animation if it doesn't fit (for example while climbing)
    // in a finished game we might have animations for different kinds of hit
    if (previousState != CharacterState.ROPE_HANGING
    previousState != CharacterState.ROPE_CLIMBING
    previousState != CharacterState.ROPE_SWING
    previousState != CharacterState.HOLDING
    previousState != CharacterState.CLIMBING) {
    Debug.Log("Stun2 ing");
    animation.CrossFade("Stun2");
    }
    }


    protected void CheckDirection() {
    currentDirection = controller.CurrentDirection;
    // Rope states
    if (currentState == CharacterState.ROPE_HANGING ||
    currentState == CharacterState.ROPE_CLIMBING) {
    // No need to rotate, stay in existing direction
    }
    // Climbing states
    else if (currentState == CharacterState.CLIMBING ||
    currentState == CharacterState.HOLDING ||
    currentState == CharacterState.CLIMB_TOP_OF_LADDER_UP ||
    currentState == CharacterState.CLIMB_TOP_OF_LADDER_DOWN) {
    // No need to rotate, stay in existing direction
    }
    // Wall slide
    else if (currentState == CharacterState.WALL_SLIDING) {
    if (controller.CurrentDirection > 0 ) {
    transform.localScale = new Vector3(1,1,1);
    } else if (controller.CurrentDirection < 0) {
    transform.localScale = new Vector3(-1,1,1);
    }
    }
    // Directional states
    else {
    if (controller.CurrentDirection > 0 ) {
    transform.localScale = new Vector3(1,1,1);
    } else if (controller.CurrentDirection < 0) {
    transform.localScale = new Vector3(-1,1,1);
    }
    }
    }
    }
     
  15. indy2005

    indy2005

    Joined:
    Aug 22, 2009
    Posts:
    81
    Got it...my Fall Velocity was set to -8!! Changed it to -1!
     
  16. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Its a good idea to expand the zipped documentation on your computer somewhere (not inUnity folder as it has javascrpt). It has a basic search fuction and can help when searching for settings.

    - John A
     
  17. indy2005

    indy2005

    Joined:
    Aug 22, 2009
    Posts:
    81
    would be great if there were was a playmaker state machine for this
     
  18. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Hi Indy this has been discussed before and the general feel is thats its not a great fit especially moving forward in Platformer Pro. You might want to search the thread for references to playmaker over the last few weeks and have a read.

    - John A
     
  19. Credd

    Credd

    Joined:
    Dec 4, 2013
    Posts:
    6
    Hi!

    In the AlienSample2D, if I set the sloped tile as in the attached pic I get a strange situation.
    When walking from A (on the slope) towards B, I expected the character to be stopped (because it walked into a wall).
    Instead it warps to on top of B, and sometimes ends up strangely rotated.

    Is there some way to make it behave more correctly?

    [edit]
    Oh hold on, seems like it just needs a SwitchColliders call?
    [edit2]
    Yup, ignore this post then.. :)
     

    Attached Files:

    Last edited: Mar 2, 2014
  20. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    This is likely of interest to some of you (although I'm sure some people don't appreciate me spending time away from Platform PRO).


    - - - - -

    Howdy folks, I'd like to introduce the 2D Character System, the video will do a better job than the text so check it out (best viewed at full screen):


    As with all assets from JNA Mobile, there will be frequent updates, there are already several new animations (including climbing, crouching) underway... not to mention some more costumes and weapons.

    - - - -

    Although you wont get this system in Platformer PRO they are integrated and compatible, and you will also get better demos as some of the sprites will be used to demonstrate attacking and smart enemies. Surely its a win-win?
     
  21. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Next update for platformer PRO is the attack and weapon system. Luckily I have some sprites I created with 2DCS ready to go with punch and kick animations... hurray!

    In other news I'm going to start looking for some coders to help with fleshing out the movements. It's going to take too long for me to get it done, and I'm very mindful of making everyone wait :s
     
    Last edited: Mar 5, 2014
  22. AMO_Noot

    AMO_Noot

    Joined:
    Aug 14, 2012
    Posts:
    431
    2D Character System looks neat Johnny; will definitely be a boon for some people!

    I tossed ya a ticket regarding the preview.
     
  23. KidSicarus

    KidSicarus

    Joined:
    Feb 3, 2014
    Posts:
    35
    Grappling hooks, Johnny. Grappling hooks.
     
  24. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    I'll check out your game when I get a chance. Don't get a lot of time for gaming (other than hearthstone of course) these days.
     
  25. Claymore

    Claymore

    Joined:
    Oct 17, 2012
    Posts:
    158
    Hello again JohnyA! I just wanted to ask,is there going to be rope system in 2d platformer,i mean rope system like in herosample,because to add that system in original 2d,is just impossible! Just asking. Thanks.
     
  26. KeepTrying

    KeepTrying

    Joined:
    Feb 23, 2011
    Posts:
    119
    Thank you JohnnyA, i'm working with Control Freak's Developer and still looking for a replacement for the character system.:
     
  27. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Everything in 2DPC will be in Platformer PRO, although it may not make initial release. I may look at moving the ropes to 2D in the current version too as I have had several requests to do this. Lodging a support ticket is the best way to get action :)
     
  28. Claymore

    Claymore

    Joined:
    Oct 17, 2012
    Posts:
    158
    Well okey Johny,you are good man,i will try to support your product as much possible..anyway i hope new 2d platformer update will come soon. JUST CANT.....WAIT :D
     
  29. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Working on attack systems today and a new level with a few characters generated by the 2D Character system... swashbuckling dan vs the ice ninja...

    $Screen Shot 2014-03-08 at 11.18.16 am.png
     
  30. tahmzad

    tahmzad

    Joined:
    Jan 24, 2014
    Posts:
    15
    Hi John, is this attack system close combat (swords) only or will it also include bullets/stars/knives etc?
     
  31. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    It will include projectiles.
     
  32. parnell

    parnell

    Joined:
    Jan 14, 2009
    Posts:
    206
    *drool*

    Does the new system work only with 2D?
    Thanks
    B
     
  33. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    2D physics yes, the controller is 2D so there's not a lot of reasons to make collisions work with 3D.

    Visually it will have 2D and 3D animators and examples. I'm mainly using 2D in my testing as its easier to see animation issues, and because I don't have to create the animation transitions (which I'm delaying for a while because I don't like doing it :) ). There is a basic 3D sample in the preview version.

    - John A
     
  34. tahmzad

    tahmzad

    Joined:
    Jan 24, 2014
    Posts:
    15
    Hey. I found this Enemy Floater (it waits for you to come near and then attacks you while floating in the air, like a bird) code in another asset that i have, Its designed for 2d only but since my game is 2.5D, im wondering if anybody knows how to put rotation in it so it always faces towards Hero character and when collides with Hero, reduce health? Right now it has transformation but its for 2d only (Textures) and I made a 3d model of a bird. Here's that code. Again I'm extremely sorry I'm not a coder so any help will be greatly appreciated.

    -----------------------------

    #pragma strict

    //public variables we use to make the floater characters
    //sound for when its hurt
    var hurtSound:AudioClip;
    //the textures of the floater
    var left1:Texture;
    var left2:Texture;
    var right1:Texture;
    var right2:Texture;
    //the death animation object
    var deathAnim:GameObject;
    //a heart that has a random chance of dropping on death
    var heartDrop:GameObject;
    var health:int = 4;
    var jumpSpeed:float = 2.0;

    //private variables that we use to help animate the floater
    private var counter:float = 0.0;
    private var colorCounter:float = 0.0;
    private var target:GameObject;
    private var direction = false;
    private var distance:float = 0.0;
    private var ydistance:float = 0.0;
    private var frameRate:float = 6.0;

    //we use the player to help animate the floater enemy by using the player's position.
    function Start () {
    target = GameObject.Find("Hero");
    }

    function Update () {
    //here we check the distance the player is from the floater.
    distance = target.transform.position.x - transform.position.x;
    ydistance = target.transform.position.y - transform.position.y;
    if(distance < 0){
    distance *= -1;
    }
    if(ydistance < 0){
    ydistance*= -1;
    }
    //here we check if the floater is to the left or to the right of the player so we can decide which textures to use while he's floating to make him look like he's looking at the player
    if(target.transform.position.x > transform.position.x){
    direction = true;
    }
    if(target.transform.position.x < transform.position.x){
    direction = false;
    }

    //if the player is close enough, start animating and moving.
    if(distance < 16 ydistance < 8){
    counter += Time.deltaTime*frameRate;
    if(direction == true){
    if(counter > 0 renderer.material.mainTexture != right1){
    renderer.material.mainTexture = right1;
    }
    if(counter > 1 renderer.material.mainTexture != right2){
    renderer.material.mainTexture = right2;
    }
    if(counter > 2){
    counter = 0.0;
    }
    }

    if(direction == false){
    if(counter > 0 renderer.material.mainTexture != left1){
    renderer.material.mainTexture = left1;
    }
    if(counter > 1 renderer.material.mainTexture != left2){
    renderer.material.mainTexture = left2;
    }
    if(counter > 2){
    counter = 0.0;
    }
    }

    //this is how we get the floating to always move towards the player if he's close enough.
    if(target != null){
    var dir = target.transform.position - transform.position;
    dir = dir.normalized;
    rigidbody.AddForce(dir * 800 * Time.deltaTime);
    }
    //end of direction < 16
    }

    //if the floater was hurt, his color would have been changed to show that he was hurt. here we give it some time to be seen then switch it back to normal.
    if(renderer.material.color.r == 0.5){
    colorCounter += Time.deltaTime;
    if(colorCounter > 0.125){
    renderer.material.color.r = 1;
    renderer.material.color.b = 1;
    }
    }

    //end of function update
    }




    //here we manage health of the enemy when a bullet hits it. if its health is 0 it will spawn the death animation, possibly spawn a heart, then destroy itself.
    function OnTriggerEnter (other : Collider){
    if(other.tag == "bullet"){
    audio.PlayOneShot(hurtSound);
    Destroy(other.gameObject);
    renderer.material.color.r = 0.5;
    renderer.material.color.b = 0.5;
    colorCounter = 0.0;
    health -= 1;
    if(health <= 0){
    Instantiate(deathAnim, transform.position, Quaternion.Euler(0,180,0));
    var randNum:int = Random.Range(1,4);
    if(randNum == 2){
    Instantiate(heartDrop, transform.position, Quaternion.Euler(0,180,0));
    }
    Destroy(gameObject);
    }
    }
    }

    -------------------------------------------------

    Thanks.
     
  35. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Latest Platformer PRO update, I really like this one:

    [video=youtube_share;1JiXksq7eXc]http://youtu.be/1JiXksq7eXc​
     
  36. msbranin

    msbranin

    Joined:
    Jan 19, 2009
    Posts:
    104
    Impressive.. its looking nice.

     
  37. AMO_Noot

    AMO_Noot

    Joined:
    Aug 14, 2012
    Posts:
    431
    Looking great, Johnny!
     
  38. The_Daleatron

    The_Daleatron

    Joined:
    Nov 26, 2013
    Posts:
    43
    Looking really good !
     
  39. KidSicarus

    KidSicarus

    Joined:
    Feb 3, 2014
    Posts:
    35
    Lookin' good, John.

    Regarding audio, can you add a random state to the sound file played and also add it directly as a source on the game object so it plays in stereo at location instead of mono?

    Where did you get your background and platform assets?

    Can't wait to see the ranged combat.
     
  40. robinball

    robinball

    Joined:
    Jan 1, 2013
    Posts:
    48
    That's looking great. Just the sort of thing a non-coding artist like me has been looking for.

    Can't wait to try it out :)
     
  41. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Random is coming, and the audio source can be anywhere, its just a component dragged on to the box.

    The assets are from Glitch: http://www.glitchthegame.com/public-domain-game-art/
     
  42. Dunkelheit

    Dunkelheit

    Joined:
    Sep 3, 2013
    Posts:
    81
    Could you please, Johnny, show us what is the main difference between these two versions? Wall issues like char "jumping off" the wall has been fixed?
     
  43. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Thats a new issue to me, as far as I know wall jumping works fine if you configure it correctly. Please send a support request. Maybe thats a good indicator of one of the core problems in 2DPC... almost everything can be done smoothly if you configure it right, but its really hard to configure it right.

    The main differences:

    1. By showing you only the settings you need for your character it will be easier to use. There will also be more custom editors with pop up help boxes, buttons for defaults, wizards, etc.

    2. Movements are pluggable and divided in to areas (air movement, ground movement, etc) which makes it much easier for me and for you to create new movement types.

    3. Its not just a controller its a complete kit. 2DPC was never intended to cater for enemies, collectables, etc. Those were extra features which as the manual says are samples on how to do things. Platformer PRO make these things (as well as attack system, event sytem etc) first class citizens. They will get as much love and support as the core controls.

    4. Lots of small enhancements:

    a) Ladders are now just a collider, no need for steps.
    b) Handles really fast characters without needing to write special raycast code.
    c) No popping on passthrough platforms (this is the only issue I know of which doesn't have a good workaround).
    d) Many more animations states.
    e) Built-in support for sprites that don't rotate.
    f) No need to create "smoothing geometry" to handle sharp slopes.
    g) Mecanim with root transform based movement
    h) Many more...
     
  44. nomad512

    nomad512

    Joined:
    Mar 7, 2014
    Posts:
    7
    I can't understand as to realize in 2d a platformer movement on a spiral at an angle 360 degrees, the sonic the hedgehog type.
    $??????????789.png

    С#
    Controler of the player:

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. using System.Collections;
    4.  
    5.  
    6.  
    7. [RequireComponent(typeof(PlayerPhysics))]
    8.  
    9. public class PlayerController :Entety
    10.  
    11. {
    12.  
    13.  
    14.  
    15.    
    16.  
    17.     public float gravity = 20;
    18.  
    19.     public float walkSpeed = 8;
    20.  
    21.     public float runSpeed = 12;
    22.  
    23.     public float acceleration = 30;
    24.  
    25.     public float jumpHeight = 12;
    26.  
    27.     public float slideDeceleration = 10;
    28.  
    29.  
    30.  
    31.     private float animationsSpeed;
    32.  
    33.     private float currentSpeed;
    34.  
    35.     private float targetSpeed;
    36.  
    37.     private Vector2 amountToMove;
    38.  
    39.  
    40.  
    41.    
    42.  
    43.     private bool Jumping;
    44.  
    45.     private bool sliding;
    46.  
    47.    
    48.  
    49.  
    50.  
    51.     private PlayerPhysics playerPhysics;
    52.  
    53.     private Animator animator;
    54.  
    55.    
    56.  
    57.  
    58.  
    59.     void Start()
    60.  
    61.     {
    62.  
    63.         playerPhysics = GetComponent<PlayerPhysics>();
    64.  
    65.         animator = GetComponent<Animator>();
    66.  
    67.        
    68.  
    69.         animator.SetLayerWeight(1,1);
    70.  
    71.     }
    72.  
    73.  
    74.  
    75.     void Update()
    76.  
    77.     {
    78.  
    79.  
    80.  
    81.         if (playerPhysics.movementStopped)
    82.  
    83.         {
    84.  
    85.             targetSpeed = 0;
    86.  
    87.             currentSpeed = 0;
    88.  
    89.         }
    90.  
    91.        
    92.  
    93.        
    94.  
    95.  
    96.  
    97.         if (playerPhysics.grounded)
    98.  
    99.         {
    100.  
    101.             amountToMove.y = 0;
    102.  
    103.  
    104.  
    105.             if (Jumping)
    106.  
    107.             {
    108.  
    109.                
    110.  
    111.                 Jumping = false;
    112.  
    113.                 animator.SetBool("Jumping", false);
    114.  
    115.             }
    116.  
    117.          
    118.  
    119.             if (sliding)
    120.  
    121.             {
    122.  
    123.                 if (Mathf.Abs(currentSpeed) < .25f)
    124.  
    125.                 {
    126.  
    127.                     sliding = false;
    128.  
    129.                     animator.SetBool("Sliding", false);
    130.  
    131.                     playerPhysics.ResetCollider();
    132.  
    133.                 }
    134.  
    135.             }
    136.  
    137.  
    138.  
    139.            
    140.  
    141.             if (Input.GetButtonDown("Jump"))
    142.  
    143.             {
    144.  
    145.                 amountToMove.y = jumpHeight;
    146.  
    147.  
    148.  
    149.                
    150.  
    151.                 Jumping = true;
    152.  
    153.                 animator.SetBool("Jumping", true);
    154.  
    155.  
    156.  
    157.             }
    158.  
    159.  
    160.  
    161.          
    162.  
    163.             if (Input.GetButtonDown("Slide"))
    164.  
    165.             {
    166.  
    167.                 sliding = true;
    168.  
    169.                 animator.SetBool("Sliding", true);
    170.  
    171.                 targetSpeed = 0;
    172.  
    173.  
    174.  
    175.              
    176.  
    177.                 playerPhysics.SetCollider(new Vector3(0.1f,0.02f,0.03f), new Vector3(0f, 0.01f,0f));
    178.  
    179.             }
    180.  
    181.         }
    182.  
    183.  
    184.  
    185.        
    186.  
    187.  
    188.  
    189.        
    190.  
    191.         animationsSpeed = IncrementTowards(animationsSpeed, Mathf.Abs(targetSpeed), acceleration);
    192.  
    193.         animator.SetFloat("Speed", animationsSpeed);
    194.  
    195.  
    196.  
    197.      
    198.  
    199.         if (!sliding)
    200.  
    201.         {
    202.  
    203.             float speed = (Input.GetButton("Run")) ? runSpeed : walkSpeed;
    204.  
    205.  
    206.  
    207.             targetSpeed = Input.GetAxisRaw("Horizontal") * speed;
    208.  
    209.             currentSpeed = IncrementTowards(currentSpeed, targetSpeed, acceleration);
    210.  
    211.  
    212.  
    213.            
    214.  
    215.             float moveDir = Input.GetAxisRaw("Horizontal");
    216.  
    217.             if (moveDir != 0)
    218.  
    219.             {
    220.  
    221.                 transform.eulerAngles = (moveDir > 0) ? Vector3.up * 180 : Vector3.zero;
    222.  
    223.             }
    224.  
    225.         }
    226.  
    227.         else
    228.  
    229.         {
    230.  
    231.             currentSpeed = IncrementTowards(currentSpeed, targetSpeed, slideDeceleration);
    232.  
    233.  
    234.  
    235.         }
    236.  
    237.  
    238.  
    239.        
    240.  
    241.         amountToMove.x = currentSpeed;
    242.  
    243.         amountToMove.y -= gravity * Time.deltaTime;
    244.  
    245.         playerPhysics.Move(amountToMove * Time.deltaTime);
    246.  
    247.  
    248.  
    249.      
    250.  
    251.     }
    252.  
    253.  
    254.  
    255.  
    256.  
    257.     private float IncrementTowards(float n, float target, float a)
    258.  
    259.     {
    260.  
    261.         if (n == target)
    262.  
    263.         {
    264.  
    265.             return n;
    266.  
    267.         }
    268.  
    269.         else
    270.  
    271.         {
    272.  
    273.             float dir = Mathf.Sign(target - n);
    274.  
    275.             n += a * Time.deltaTime * dir;
    276.  
    277.             return (dir == Mathf.Sign(target - n)) ? n : target;
    278.  
    279.         }
    280.  
    281.  
    282.  
    283.        
    284.  
    285.  
    286.  
    287.     }
    288.  
    289. }
    С#
    Physics of the player:

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. using System.Collections;
    4.  
    5.  
    6.  
    7.  
    8.  
    9. [RequireComponent(typeof(BoxCollider))]
    10.  
    11. public class PlayerPhysics : MonoBehaviour
    12.  
    13. {
    14.  
    15.  
    16.  
    17.     public LayerMask collisionMask;
    18.  
    19.  
    20.  
    21.     private BoxCollider collider;
    22.  
    23.     private Vector3 s;
    24.  
    25.     private Vector3 c;
    26.  
    27.  
    28.  
    29.     private Vector3 originalSize;
    30.  
    31.     private Vector3 originalCentre;
    32.  
    33.     private float colliderScale;
    34.  
    35.  
    36.  
    37.     private int collisionDivisionX = 3;
    38.  
    39.     private int collisionDivisionY = 10;
    40.  
    41.  
    42.  
    43.     private float skin = .005f;
    44.  
    45.  
    46.  
    47.     [HideInInspector]
    48.  
    49.     public bool grounded;
    50.  
    51.  
    52.  
    53.     [HideInInspector]
    54.  
    55.     public bool movementStopped;
    56.  
    57.  
    58.  
    59.     Ray ray;
    60.  
    61.     RaycastHit hit;
    62.  
    63.  
    64.  
    65.     void Start()
    66.  
    67.     {
    68.  
    69.         collider = GetComponent<BoxCollider>();
    70.  
    71.         colliderScale = transform.localScale.x;
    72.  
    73.  
    74.  
    75.         originalSize = collider.size;
    76.  
    77.         originalCentre = collider.center;
    78.  
    79.         SetCollider(originalSize, originalCentre);
    80.  
    81.     }
    82.  
    83.  
    84.  
    85.     public void Move(Vector2 moveAmount)
    86.  
    87.     {
    88.  
    89.  
    90.  
    91.         float deltaY = moveAmount.y;
    92.  
    93.         float deltaX = moveAmount.x;
    94.  
    95.         Vector2 p = transform.position;
    96.  
    97.  
    98.  
    99.        
    100.  
    101.         grounded = false;
    102.  
    103.  
    104.  
    105.         for (int i = 0; i < collisionDivisionX; i++)
    106.  
    107.         {
    108.  
    109.             float dir = Mathf.Sign(deltaY);
    110.  
    111.             float x = (p.x + c.x - s.x / 2) + s.x / (collisionDivisionX - 1) * i;
    112.  
    113.             float y = p.y + c.y + s.y / 2 * dir;
    114.  
    115.  
    116.  
    117.             ray = new Ray(new Vector2(x, y), new Vector2(0, dir));
    118.  
    119.             Debug.DrawRay(ray.origin, ray.direction);
    120.  
    121.  
    122.  
    123.             if (Physics.Raycast(ray, out hit, Mathf.Abs(deltaY) + skin, collisionMask))
    124.  
    125.             {
    126.  
    127.                
    128.  
    129.                 float dst = Vector3.Distance(ray.origin, hit.point);
    130.  
    131.  
    132.  
    133.              
    134.  
    135.                 if (dst > skin)
    136.  
    137.                 {
    138.  
    139.                     deltaY = dst * dir - skin * dir;
    140.  
    141.                 }
    142.  
    143.                 else
    144.  
    145.                 {
    146.  
    147.                     deltaY = 0;
    148.  
    149.                 }
    150.  
    151.  
    152.  
    153.                 grounded = true;
    154.  
    155.  
    156.  
    157.                 break;
    158.  
    159.  
    160.  
    161.             }
    162.  
    163.         }
    164.  
    165.  
    166.  
    167.      
    168.  
    169.        
    170.  
    171.         movementStopped = false;
    172.  
    173.  
    174.  
    175.         for (int i = 0; i < collisionDivisionY; i++)
    176.  
    177.         {
    178.  
    179.             float dir = Mathf.Sign(deltaX);
    180.  
    181.             float x = p.x + c.x + s.x / 2 * dir;
    182.  
    183.             float y = p.y + c.y - s.y / 2 + s.y / (collisionDivisionY - 1) * i;
    184.  
    185.  
    186.  
    187.             ray = new Ray(new Vector2(x, y), new Vector2(dir, 0));
    188.  
    189.             Debug.DrawRay(ray.origin, ray.direction);
    190.  
    191.  
    192.  
    193.             if (Physics.Raycast(ray, out hit, Mathf.Abs(deltaX) + skin, collisionMask))
    194.  
    195.             {
    196.  
    197.                
    198.  
    199.                 float dst = Vector3.Distance(ray.origin, hit.point);
    200.  
    201.  
    202.  
    203.                
    204.  
    205.                 if (dst > skin)
    206.  
    207.                 {
    208.  
    209.                     deltaX = dst * dir - skin * dir;
    210.  
    211.                 }
    212.  
    213.                 else
    214.  
    215.                 {
    216.  
    217.                     deltaX = 0;
    218.  
    219.                 }
    220.  
    221.  
    222.  
    223.                 movementStopped = true;
    224.  
    225.  
    226.  
    227.                 break;
    228.  
    229.  
    230.  
    231.             }
    232.  
    233.         }
    234.  
    235.  
    236.  
    237.         if (!grounded  !movementStopped)
    238.  
    239.         {
    240.  
    241.            
    242.  
    243.             Vector3 playerDir = new Vector3(deltaX, deltaY);
    244.  
    245.             Vector3 o = new Vector3(p.x + c.x + s.x / 2 * Mathf.Sign(deltaX), p.y + c.y + s.y / 2 * Mathf.Sign(deltaY));
    246.  
    247.             Debug.DrawRay(o, playerDir.normalized);
    248.  
    249.             ray = new Ray(o, playerDir.normalized);
    250.  
    251.  
    252.  
    253.             if (Physics.Raycast(ray, Mathf.Sqrt(deltaX * deltaX + deltaY * deltaY), collisionMask))
    254.  
    255.             {
    256.  
    257.                 grounded = true;
    258.  
    259.                 deltaY = 0;
    260.  
    261.             }
    262.  
    263.         }
    264.  
    265.  
    266.  
    267.         Vector2 finalTransform = new Vector2(deltaX, deltaY);
    268.  
    269.        
    270.  
    271.         transform.Translate(finalTransform,Space.World );
    272.  
    273.     }
    274.  
    275.  
    276.  
    277.    
    278.  
    279.     public void SetCollider(Vector3 size, Vector3 centre)
    280.  
    281.     {
    282.  
    283.         collider.size = size;
    284.  
    285.         collider.center = centre;
    286.  
    287.  
    288.  
    289.         s = size * colliderScale;
    290.  
    291.         c = centre * colliderScale;
    292.  
    293.     }
    294.  
    295.    
    296.  
    297.     public void ResetCollider()
    298.  
    299.     {
    300.  
    301.         SetCollider(originalSize, originalCentre);
    302.  
    303.     }
    304.  
    305. }
     
  45. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,039
    Are you using 2D Platform Controller it doesn't look like it? The kit doesn't officially support sonic style movement although a few people have got it going. Regardless at the moment I'm just a bit too busy to provided support to folks who aren't customers. Drop me a PM if you are still stuck in a weeks or two.
     
  46. TheValar

    TheValar

    Joined:
    Nov 12, 2012
    Posts:
    760
    On the subject of "sonic style movement"... would this be a good example of something that would be easily "pluggable" with version 2.0?
     
  47. Lioncirth

    Lioncirth

    Joined:
    Apr 7, 2009
    Posts:
    111
    I am currently using 2D Platformer Controller and combine some of it with playmaker (although not actually converting any of it too playmaker) I am loving it for my currently game, however cannot wait for the new version to come out :)

    Any ideas on release dates? :p
     
  48. The_Daleatron

    The_Daleatron

    Joined:
    Nov 26, 2013
    Posts:
    43
    Does anything in this conflict with playmaker, as i have that aswell and going to use it for dialog tree's etc, if anyone has tried that ?
     
  49. Lioncirth

    Lioncirth

    Joined:
    Apr 7, 2009
    Posts:
    111
    I have not tried dialog trees to be honest.

    I have not had any issues using it along with playmaker.

    The controller is currently focusing on moving the character, I then use playmaker to manage mobs, collectibles, interface etc - seems to work fine.

    A lot of this will change when version 2 comes, as that seems to manage a lot more
     
  50. The_Daleatron

    The_Daleatron

    Joined:
    Nov 26, 2013
    Posts:
    43
    Grand thanks for the reply!