Search Unity

[RELEASED] Corgi Engine - Complete 2D/2.5D Platformer [new v8.0 : advanced damage system]

Discussion in 'Assets and Asset Store' started by reuno, Dec 18, 2014.

  1. affreuxgeorges

    affreuxgeorges

    Joined:
    Feb 13, 2013
    Posts:
    15
    Hi there !
    First, thank you for the great tool, with so much stuff and options ready to use.
    I have a question about implementing a character grappling hook ability.
    1st. Is there a way to add movementstates to the engine without modifying the enum directly in Corgi engine scripts ?
    2nd. How would you handle the physics of the grappling hook ?
    My first idea was to use a Distance2DJoint but it's not working because Corgi Controller is applying forces directly on the transform and do not use the 2D physics engine of unity.
    So I guess the best solution is to implement a custom CorgiCharacterDistanceJoint, and restrain the movement using the corgiController speed and externalforces parameters. The problem is I have no idea how to do that properly, my physics maths are terrible.
    The other solution would be to deactivate the corgi controller during grappling, and try to use unity physics...

    What's your advice here ?
    I would post my progress here, if anyone wants a grappling hook ability (not a grappling gun), I'm more than happy to share it.
    Thanks
     
  2. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @affreuxgeorges > 1. No, unfortunately in C# you can't extend enums, that's one of the rare cases where modifying the core class directly is the best way to go. Plus if you update and override that file, you'll get a very explicit error telling you about the missing state, so it's not hard to miss if you forget to merge your changes correctly.
    2. I wouldn't use physics for this, but just compute the trajectory using maths. If that's not an issue, you can simply disable the controller (or gravity) for the duration your hook is active. Similar to how the Grip ability works.
     
  3. affreuxgeorges

    affreuxgeorges

    Joined:
    Feb 13, 2013
    Posts:
    15
    Thanks for the quick reply. The only thing i'm struggling with would be how to apply the correct force for my character to rotate around the hook point while keeping a fixed distance with it, and not resetting the current velocity of the controller. If someone is at ease with these kind of physics maths, or know a tutorial about this, I would be very happy <3
     
  4. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @affreuxgeorges > I wouldn't use forces for that, I'd simply move the transform, but there are plenty of ways of doing it and applying forces would work too I suppose.
     
  5. moatdd

    moatdd

    Joined:
    Jan 13, 2013
    Posts:
    178
    Hey @reuno, I was able to add InControl support to the Corgi Engine by way of the following:

    These steps should be OK for stock Input setups if you haven't deviated from Corgi's default inputs.

    First, I had to add InControl's Assembly Reference to the MoreMountains.CorgiEngine Assembly Reference so that the InputManager could access InControl's functions.

    upload_2021-5-28_20-15-0.png

    upload_2021-5-28_20-14-22.png

    Then I added MMInControl.cs -- this is a component I made based off of MMSingleton.

    Code (CSharp):
    1. using InControl;
    2.  
    3. namespace MoreMountains.Tools
    4. {
    5.     using UnityEngine;
    6.  
    7.     public class MMInControl : MoreMountains.Tools.MMSingleton<MMInControl>
    8.     {
    9.         public MMInputActions playerActions;
    10.         string saveData;
    11.         public string MMPlayerPrefsKey = "MMInControlKeyBinds";
    12.  
    13.         void OnEnable()
    14.         {
    15.             // See PlayerActions.cs for this setup.
    16.             playerActions = MMInputActions.CreateWithDefaultBindings();
    17.             //playerActions.Move.OnLastInputTypeChanged += ( lastInputType ) => Debug.Log( lastInputType );
    18.  
    19.             LoadBindings();
    20.         }
    21.  
    22.  
    23.         void OnDisable()
    24.         {
    25.             // This properly disposes of the action set and unsubscribes it from
    26.             // update events so that it doesn't do additional processing unnecessarily.
    27.             playerActions.Destroy();
    28.         }
    29.  
    30.         public void SaveBindings()
    31.         {
    32.             saveData = playerActions.Save();
    33.             PlayerPrefs.SetString( MMPlayerPrefsKey, saveData );
    34.         }
    35.  
    36.  
    37.         void LoadBindings()
    38.         {
    39.             if (PlayerPrefs.HasKey( MMPlayerPrefsKey ))
    40.             {
    41.                 saveData = PlayerPrefs.GetString( MMPlayerPrefsKey );
    42.                 playerActions.Load( saveData );
    43.             }
    44.         }
    45.  
    46.  
    47.         void OnApplicationQuit()
    48.         {
    49.             PlayerPrefs.Save();
    50.         }
    51.  
    52.  
    53.     }
    54.  
    55.     public class MMInputActions : PlayerActionSet
    56.     {
    57.         public PlayerAction Jump           ;
    58.         public PlayerAction Swim           ;
    59.         public PlayerAction Glide          ;
    60.         public PlayerAction Interact       ;
    61.         public PlayerAction Jetpack        ;
    62.         public PlayerAction Run            ;
    63.         public PlayerAction Dash           ;
    64.         public PlayerAction Roll           ;
    65.         public PlayerAction Fly            ;
    66.         public PlayerAction Shoot          ;
    67.         public PlayerAction SecondaryShoot ;
    68.         public PlayerAction Reload         ;
    69.         public PlayerAction SwitchWeapon   ;
    70.         public PlayerAction Pause          ;
    71.         public PlayerAction Push           ;
    72.         public PlayerAction SwitchCharacter;
    73.         public PlayerAction TimeControl    ;
    74.         public PlayerAction Grab           ;
    75.         public PlayerAction Throw          ;
    76.         public PlayerAction Left;
    77.         public PlayerAction Right;
    78.         public PlayerAction Up;
    79.         public PlayerAction Down;
    80.         public PlayerAction DLeft;
    81.         public PlayerAction DRight;
    82.         public PlayerAction DUp;
    83.         public PlayerAction DDown;
    84.         public PlayerOneAxisAction MoveHorizontal;
    85.         public PlayerOneAxisAction MoveVertical;
    86.         public PlayerOneAxisAction MoveHorizontalSecondary;
    87.         public PlayerOneAxisAction MoveVerticalSecondary;
    88.  
    89.  
    90.  
    91.         public MMInputActions()
    92.         {
    93.             Jump                    = CreatePlayerAction( "Player1_Jump" );
    94.             Swim                    = CreatePlayerAction( "Player1_Swim" );
    95.             Glide                   = CreatePlayerAction( "Player1_Glide" );
    96.             Interact                = CreatePlayerAction( "Player1_Interact" );
    97.             Jetpack                 = CreatePlayerAction( "Player1_Jetpack" );
    98.             Run                     = CreatePlayerAction( "Player1_Run" );
    99.             Dash                    = CreatePlayerAction( "Player1_Dash" );
    100.             Roll                    = CreatePlayerAction( "Player1_Roll" );
    101.             Fly                     = CreatePlayerAction( "Player1_Fly" );
    102.             Shoot                   = CreatePlayerAction( "Player1_Shoot" );
    103.             SecondaryShoot          = CreatePlayerAction( "Player1_SecondaryShoot" );
    104.             Reload                  = CreatePlayerAction( "Player1_Reload" );
    105.             SwitchWeapon            = CreatePlayerAction( "Player1_SwitchWeapon" );
    106.             Pause                   = CreatePlayerAction( "Player1_Pause" );
    107.             Push                    = CreatePlayerAction( "Player1_Push" );
    108.             SwitchCharacter         = CreatePlayerAction( "Player1_SwitchCharacter" );
    109.             TimeControl             = CreatePlayerAction( "Player1_TimeControl" );
    110.             Grab                    = CreatePlayerAction( "Player1_Grab" );
    111.             Throw                   = CreatePlayerAction( "Player1_Throw" );
    112.  
    113.             Left                    = CreatePlayerAction( "Move Left" );
    114.             Right                   = CreatePlayerAction( "Move Right" );
    115.             Up                      = CreatePlayerAction( "Move Up" );
    116.             Down                    = CreatePlayerAction( "Move Down" );
    117.             DLeft                   = CreatePlayerAction( "Alt Move Left");
    118.             DRight                  = CreatePlayerAction( "Alt Move Right");
    119.             DUp                     = CreatePlayerAction( "Alt Move Up");
    120.             DDown                   = CreatePlayerAction( "Alt Move Down");
    121.             MoveHorizontal          = CreateOneAxisPlayerAction(Left, Right);
    122.             MoveVertical            = CreateOneAxisPlayerAction(Down, Up);
    123.             MoveHorizontalSecondary = CreateOneAxisPlayerAction(DLeft, DRight);
    124.             MoveVerticalSecondary   = CreateOneAxisPlayerAction(DDown, DUp);
    125.         }
    126.  
    127.  
    128.         public static MMInputActions CreateWithDefaultBindings()
    129.         {
    130.             var playerActions = new MMInputActions();
    131.  
    132.             // How to set up mutually exclusive keyboard bindings with a modifier key.
    133.             // playerActions.Back.AddDefaultBinding( Key.Shift, Key.Tab );
    134.             // playerActions.Next.AddDefaultBinding( KeyCombo.With( Key.Tab ).AndNot( Key.Shift ) );
    135.  
    136.             playerActions.Shoot.AddDefaultBinding          ( InputControlType.Action3 );
    137.             playerActions.Shoot.AddDefaultBinding          ( Mouse.LeftButton );
    138.  
    139.             playerActions.SecondaryShoot.AddDefaultBinding (InputControlType.RightBumper);
    140.  
    141.             playerActions.SwitchCharacter.AddDefaultBinding(InputControlType.Action4);
    142.  
    143.             playerActions.Jump.AddDefaultBinding           ( Key.Space );
    144.             playerActions.Jump.AddDefaultBinding           ( InputControlType.Action1 );
    145.  
    146.             playerActions.Up.AddDefaultBinding             ( Key.W );
    147.             playerActions.Down.AddDefaultBinding           ( Key.S );
    148.             playerActions.Left.AddDefaultBinding           ( Key.A );
    149.             playerActions.Right.AddDefaultBinding          ( Key.D );
    150.  
    151.             playerActions.Run.AddDefaultBinding            (Key.Shift);
    152.             playerActions.Run.AddDefaultBinding            (InputControlType.Action3);
    153.  
    154.             playerActions.Pause.AddDefaultBinding          (Key.Escape);
    155.             playerActions.Pause.AddDefaultBinding          (InputControlType.Start);
    156.             playerActions.Grab.AddDefaultBinding           (Key.Tab);
    157.             playerActions.Throw.AddDefaultBinding          (InputControlType.Back);
    158.  
    159.             playerActions.Left.AddDefaultBinding           ( InputControlType.LeftStickLeft );
    160.             playerActions.Right.AddDefaultBinding          ( InputControlType.LeftStickRight );
    161.             playerActions.Up.AddDefaultBinding             ( InputControlType.LeftStickUp );
    162.             playerActions.Down.AddDefaultBinding           ( InputControlType.LeftStickDown );
    163.  
    164.             playerActions.DLeft.AddDefaultBinding          ( InputControlType.DPadLeft );
    165.             playerActions.DRight.AddDefaultBinding         ( InputControlType.DPadRight );
    166.             playerActions.DUp.AddDefaultBinding            ( InputControlType.DPadUp );
    167.             playerActions.DDown.AddDefaultBinding          ( InputControlType.DPadDown );
    168.  
    169.  
    170.             playerActions.ListenOptions.IncludeUnknownControllers = true;
    171.             playerActions.ListenOptions.MaxAllowedBindings = 2;
    172.             playerActions.ListenOptions.MaxAllowedBindingsPerType = 2;
    173.             playerActions.ListenOptions.AllowDuplicateBindingsPerSet = true;
    174.             // playerActions.ListenOptions.UnsetDuplicateBindingsOnSet = true;
    175.             playerActions.ListenOptions.IncludeMouseButtons = true;
    176.             playerActions.ListenOptions.IncludeMouseButtons = true;
    177.             playerActions.ListenOptions.IncludeMouseScrollWheel = true;
    178.             // playerActions.ListenOptions.IncludeModifiersAsFirstClassKeys = true;
    179.  
    180.             playerActions.ListenOptions.OnBindingFound = ( action, binding ) => {
    181.                 if (binding == new KeyBindingSource( Key.Escape ))
    182.                 {
    183.                     action.StopListeningForBinding();
    184.                     return false;
    185.                 }
    186.                 return true;
    187.             };
    188.  
    189.             playerActions.ListenOptions.OnBindingAdded += ( action, binding ) => {
    190.                 Debug.Log( "Binding added... " + binding.DeviceName + ": " + binding.Name );
    191.             };
    192.  
    193.             playerActions.ListenOptions.OnBindingRejected += ( action, binding, reason ) => {
    194.                 Debug.Log( "Binding rejected... " + reason );
    195.             };
    196.  
    197.             return playerActions;
    198.         }
    199.     }
    200.  
    201. }
    202.  
    203.  
    InControl users can then drag one instance of MMInControl onto a GameObject within their scene. I recommend sticking it on the InControl Manager for organizational purposes.

    upload_2021-5-28_20-17-39.png

    The MM Player Prefs Key value is the name of the PlayerPrefs registry key that it will attempt to save/restore from.

    I had to make a few edits to InputManager.cs. My edits are all encapuslated within #if USE_INCONTROL preprocs:

    Code (CSharp):
    1. // Comment this out if you wish to use stock Unity input
    2. #define USE_INCONTROL
    3.  
    4. using UnityEngine;
    5. using System.Collections;
    6. using MoreMountains.Tools;
    7. using UnityEngine.Events;
    8. using System.Collections.Generic;
    9.  
    10. #if USE_INCONTROL
    11. using InControl;
    12. #endif
    13.  
    14. namespace MoreMountains.CorgiEngine
    15. {
    16.  
    17.     public struct ControlsModeEvent
    18.     {
    19.         public bool Status;
    20.         public InputManager.MovementControls MovementControl;
    21.  
    22.         /// <summary>
    23.         /// Initializes a new instance of the <see cref="MoreMountains.MMInterface.MMFadeOutEvent"/> struct.
    24.         /// </summary>
    25.         /// <param name="duration">Duration.</param>
    26.         public ControlsModeEvent(bool status, InputManager.MovementControls movementControl)
    27.         {
    28.             Status = status;
    29.             MovementControl = movementControl;
    30.         }
    31.  
    32.         static ControlsModeEvent e;
    33.         public static void Trigger(bool status, InputManager.MovementControls movementControl)
    34.         {
    35.             e.Status = status;
    36.             e.MovementControl = movementControl;
    37.             MMEventManager.TriggerEvent(e);
    38.         }
    39.     }
    40.  
    41.     /// <summary>
    42.     /// This persistent singleton handles the inputs and sends commands to the player.
    43.     /// IMPORTANT : this script's Execution Order MUST be -100.
    44.     /// You can define a script's execution order by clicking on the script's file and then clicking on the Execution Order button at the bottom right of the script's inspector.
    45.     /// See https://docs.unity3d.com/Manual/class-ScriptExecution.html for more details
    46.     /// </summary>
    47.     [AddComponentMenu("Corgi Engine/Managers/Input Manager")]
    48.     public class InputManager : MMSingleton<InputManager>
    49.     {
    50.         [Header("Status")]
    51.  
    52.         /// set this to false to prevent input to be detected
    53.         [Tooltip("set this to false to prevent input to be detected")]
    54.         public bool InputDetectionActive = true;
    55.  
    56.         [Header("Player binding")]
    57.         [MMInformation("The first thing you need to set on your InputManager is the PlayerID. This ID will be used to bind the input manager to your character(s). You'll want to go with Player1, Player2, Player3 or Player4.",MMInformationAttribute.InformationType.Info,false)]
    58.  
    59.         /// a string identifying the target player(s). You'll need to set this exact same string on your Character, and set its type to Player
    60.         [Tooltip("a string identifying the target player(s). You'll need to set this exact same string on your Character, and set its type to Player")]
    61.         public string PlayerID = "Player1";
    62.         /// the possible modes for this input manager
    63.         public enum InputForcedMode { None, Mobile, Desktop }
    64.         /// the possible kinds of control used for movement
    65.         public enum MovementControls { Joystick, Arrows }
    66.  
    67.         [Header("Mobile controls")]
    68.         [MMInformation("If you check Auto Mobile Detection, the engine will automatically switch to mobile controls when your build target is Android or iOS. You can also force mobile or desktop (keyboard, gamepad) controls using the dropdown below.\nNote that if you don't need mobile controls and/or GUI this component can also work on its own, just put it on an empty GameObject instead.",MMInformationAttribute.InformationType.Info,false)]
    69.  
    70.         /// if this is set to true, the InputManager will try to detect what mode it should be in, based on the current target device
    71.         [Tooltip("if this is set to true, the InputManager will try to detect what mode it should be in, based on the current target device")]
    72.         public bool AutoMobileDetection = true;
    73.         /// use this to force desktop (keyboard, pad) or mobile (touch) mode
    74.         [Tooltip("use this to force desktop (keyboard, pad) or mobile (touch) mode")]
    75.         public InputForcedMode ForcedMode;
    76.         /// if this is true, mobile controls will be hidden in editor mode, regardless of the current build target or the forced mode
    77.         [Tooltip("if this is true, mobile controls will be hidden in editor mode, regardless of the current build target or the forced mode")]
    78.         public bool HideMobileControlsInEditor = false;
    79.         /// use this to specify whether you want to use the default joystick or arrows to move your character
    80.         [Tooltip("use this to specify whether you want to use the default joystick or arrows to move your character")]
    81.         public MovementControls MovementControl = MovementControls.Joystick;
    82.         /// if this is true, button state changes are offset by one frame (usually useful on Android)
    83.         [Tooltip("if this is true, button state changes are offset by one frame (usually useful on Android)")]
    84.         public bool DelayedButtonPresses = false;
    85.         /// if this is true, we're currently in mobile mode
    86.         public bool IsMobile { get; protected set; }
    87.  
    88.         [Header("Movement settings")]
    89.         [MMInformation("Turn SmoothMovement on to have inertia in your controls (meaning there'll be a small delay between a press/release of a direction and your character moving/stopping). You can also define here the horizontal and vertical thresholds.",MMInformationAttribute.InformationType.Info,false)]
    90.  
    91.         /// If set to true, acceleration / deceleration will take place when moving / stopping
    92.         [Tooltip("If set to true, acceleration / deceleration will take place when moving / stopping")]
    93.         public bool SmoothMovement=true;
    94.         /// the minimum horizontal and vertical value you need to reach to trigger movement on an analog controller (joystick for example)
    95.         [Tooltip("the minimum horizontal and vertical value you need to reach to trigger movement on an analog controller (joystick for example)")]
    96.         public Vector2 Threshold = new Vector2(0.1f, 0.4f);
    97.      
    98.         /// the jump button, used for jumps
    99.         public MMInput.IMButton JumpButton { get; protected set; }
    100.         /// the swim button, used to swim
    101.         public MMInput.IMButton SwimButton { get; protected set; }
    102.         /// the glide button, used to glide in the air
    103.         public MMInput.IMButton GlideButton { get; protected set; }
    104.         /// the activate button, used for interactions with zones
    105.         public MMInput.IMButton InteractButton { get; protected set; }
    106.         /// the jetpack button
    107.         public MMInput.IMButton JetpackButton { get; protected set; }
    108.         /// the fly button
    109.         public MMInput.IMButton FlyButton { get; protected set; }
    110.         /// the run button
    111.         public MMInput.IMButton RunButton { get; protected set; }
    112.         /// the dash button
    113.         public MMInput.IMButton DashButton { get; protected set; }
    114.         /// the roll button
    115.         public MMInput.IMButton RollButton { get; protected set; }
    116.         /// the dash button
    117.         public MMInput.IMButton GrabButton { get; protected set; }
    118.         /// the dash button
    119.         public MMInput.IMButton ThrowButton { get; protected set; }
    120.         /// the shoot button
    121.         public MMInput.IMButton ShootButton { get; protected set; }
    122.         /// the shoot button
    123.         public MMInput.IMButton SecondaryShootButton { get; protected set; }
    124.         /// the reload button
    125.         public MMInput.IMButton ReloadButton { get; protected set; }
    126.         /// the push button
    127.         public MMInput.IMButton PushButton { get; protected set; }
    128.         /// the pause button
    129.         public MMInput.IMButton PauseButton { get; protected set; }
    130.         /// the button used to switch character (either via model or prefab switch)
    131.         public MMInput.IMButton SwitchCharacterButton { get; protected set; }
    132.         /// the switch weapon button
    133.         public MMInput.IMButton SwitchWeaponButton { get; protected set; }
    134.         /// the time control button
    135.         public MMInput.IMButton TimeControlButton { get; protected set; }
    136.         /// the shoot axis, used as a button (non analogic)
    137.         public MMInput.ButtonStates ShootAxis { get; protected set; }
    138.         /// the shoot axis, used as a button (non analogic)
    139.         public MMInput.ButtonStates SecondaryShootAxis { get; protected set; }
    140.         /// the primary movement value (used to move the character around)
    141.         public Vector2 PrimaryMovement {get { return _primaryMovement; } }
    142.         /// the secondary movement (usually the right stick on a gamepad), used to aim
    143.         public Vector2 SecondaryMovement {get { return _secondaryMovement; } }
    144.  
    145.         protected List<MMInput.IMButton> ButtonList;
    146.         protected Vector2 _primaryMovement = Vector2.zero;
    147.         protected Vector2 _secondaryMovement = Vector2.zero;
    148.         protected string _axisHorizontal;
    149.         protected string _axisVertical;
    150.         protected string _axisSecondaryHorizontal;
    151.         protected string _axisSecondaryVertical;
    152.         protected string _axisShoot;
    153.         protected string _axisShootSecondary;
    154.  
    155.         /// <summary>
    156.         /// On Start we look for what mode to use, and initialize our axis and buttons
    157.         /// </summary>
    158.         protected virtual void Start()
    159.         {
    160.             Initialization();
    161.         }
    162.  
    163.         protected virtual void Initialization()
    164.         {
    165.             ControlsModeDetection();
    166.             InitializeButtons();
    167.             InitializeAxis();
    168.         }
    169.  
    170.         /// <summary>
    171.         /// Turns mobile controls on or off depending on what's been defined in the inspector, and what target device we're on
    172.         /// </summary>
    173.         public virtual void ControlsModeDetection()
    174.         {
    175.             ControlsModeEvent.Trigger(false, MovementControls.Joystick);
    176.             IsMobile=false;
    177.             if (AutoMobileDetection)
    178.             {
    179.                 #if UNITY_ANDROID || UNITY_IPHONE
    180.                     ControlsModeEvent.Trigger(true, MovementControl);
    181.                     IsMobile = true;
    182.                 #endif
    183.             }
    184.             if (ForcedMode==InputForcedMode.Mobile)
    185.             {
    186.                 ControlsModeEvent.Trigger(true, MovementControl);
    187.                 IsMobile = true;
    188.             }
    189.             if (ForcedMode==InputForcedMode.Desktop)
    190.             {
    191.                 ControlsModeEvent.Trigger(false, MovementControls.Joystick);
    192.                 IsMobile = false;                  
    193.             }
    194.             if (HideMobileControlsInEditor)
    195.             {
    196.                 #if UNITY_EDITOR
    197.                 ControlsModeEvent.Trigger(false, MovementControls.Joystick);
    198.                     IsMobile = false;  
    199.                 #endif
    200.             }          
    201.         }
    202.  
    203.         /// <summary>
    204.         /// Initializes the buttons. If you want to add more buttons, make sure to register them here.
    205.         /// </summary>
    206.         protected virtual void InitializeButtons()
    207.         {
    208.             ButtonList = new List<MMInput.IMButton> ();
    209.             ButtonList.Add(JumpButton = new MMInput.IMButton(PlayerID, "Jump", JumpButtonDown, JumpButtonPressed, JumpButtonUp));
    210.             ButtonList.Add(SwimButton = new MMInput.IMButton(PlayerID, "Swim", SwimButtonDown, SwimButtonPressed, SwimButtonUp));
    211.             ButtonList.Add(GlideButton = new MMInput.IMButton(PlayerID, "Glide", GlideButtonDown, GlideButtonPressed, GlideButtonUp));
    212.             ButtonList.Add(InteractButton = new MMInput.IMButton (PlayerID, "Interact", InteractButtonDown, InteractButtonPressed, InteractButtonUp));
    213.             ButtonList.Add(JetpackButton = new MMInput.IMButton (PlayerID, "Jetpack", JetpackButtonDown, JetpackButtonPressed, JetpackButtonUp));
    214.             ButtonList.Add(RunButton  = new MMInput.IMButton (PlayerID, "Run", RunButtonDown, RunButtonPressed, RunButtonUp));
    215.             ButtonList.Add(DashButton = new MMInput.IMButton(PlayerID, "Dash", DashButtonDown, DashButtonPressed, DashButtonUp));
    216.             ButtonList.Add(RollButton = new MMInput.IMButton(PlayerID, "Roll", RollButtonDown, RollButtonPressed, RollButtonUp));
    217.             ButtonList.Add(FlyButton = new MMInput.IMButton(PlayerID, "Fly", FlyButtonDown, FlyButtonPressed, FlyButtonUp));
    218.             ButtonList.Add(ShootButton = new MMInput.IMButton(PlayerID, "Shoot", ShootButtonDown, ShootButtonPressed, ShootButtonUp));
    219.             ButtonList.Add(SecondaryShootButton = new MMInput.IMButton(PlayerID, "SecondaryShoot", SecondaryShootButtonDown, SecondaryShootButtonPressed, SecondaryShootButtonUp));
    220.             ButtonList.Add(ReloadButton = new MMInput.IMButton (PlayerID, "Reload", ReloadButtonDown, ReloadButtonPressed, ReloadButtonUp));
    221.             ButtonList.Add(SwitchWeaponButton = new MMInput.IMButton (PlayerID, "SwitchWeapon", SwitchWeaponButtonDown, SwitchWeaponButtonPressed, SwitchWeaponButtonUp));
    222.             ButtonList.Add(PauseButton = new MMInput.IMButton (PlayerID, "Pause", PauseButtonDown, PauseButtonPressed, PauseButtonUp));
    223.             ButtonList.Add(PushButton = new MMInput.IMButton(PlayerID, "Push", PushButtonDown, PushButtonPressed, PushButtonUp));
    224.             ButtonList.Add(SwitchCharacterButton = new MMInput.IMButton(PlayerID, "SwitchCharacter", SwitchCharacterButtonDown, SwitchCharacterButtonPressed, SwitchCharacterButtonUp));
    225.             ButtonList.Add(TimeControlButton = new MMInput.IMButton(PlayerID, "TimeControl", TimeControlButtonDown, TimeControlButtonPressed, TimeControlButtonUp));
    226.             ButtonList.Add(GrabButton = new MMInput.IMButton(PlayerID, "Grab", GrabButtonDown, GrabButtonPressed, GrabButtonUp));
    227.             ButtonList.Add(ThrowButton = new MMInput.IMButton(PlayerID, "Throw", ThrowButtonDown, ThrowButtonPressed, ThrowButtonUp));
    228.         }
    229.  
    230.         /// <summary>
    231.         /// Initializes the axis strings.
    232.         /// </summary>
    233.         protected virtual void InitializeAxis()
    234.         {
    235.             _axisHorizontal = PlayerID+"_Horizontal";
    236.             _axisVertical = PlayerID+"_Vertical";
    237.             _axisSecondaryHorizontal = PlayerID+"_SecondaryHorizontal";
    238.             _axisSecondaryVertical = PlayerID+"_SecondaryVertical";
    239.             _axisShoot = PlayerID + "_ShootAxis";
    240.             _axisShootSecondary = PlayerID + "_SecondaryShootAxis";
    241.         }
    242.  
    243.         /// <summary>
    244.         /// On LateUpdate, we process our button states
    245.         /// </summary>
    246.         protected virtual void LateUpdate()
    247.         {
    248.             ProcessButtonStates();
    249.         }
    250.  
    251.         /// <summary>
    252.         /// At update, we check the various commands and update our values and states accordingly.
    253.         /// </summary>
    254.         protected virtual void Update()
    255.         {      
    256.             if (!IsMobile && InputDetectionActive)
    257.             {  
    258.                 SetMovement();  
    259.                 SetSecondaryMovement ();
    260.                 SetShootAxis();
    261.                 GetInputButtons ();
    262.             }                                  
    263.         }
    264.  
    265.         /// <summary>
    266.         /// If we're not on mobile, watches for input changes, and updates our buttons states accordingly
    267.         /// </summary>
    268.         protected virtual void GetInputButtons()
    269.         {
    270.             foreach(MMInput.IMButton button in ButtonList)
    271.             {
    272. #if USE_INCONTROL
    273.                 PlayerAction playerAction = MMInControl.Instance.playerActions.GetPlayerActionByName(button.ButtonID);
    274.                 if (playerAction == null)
    275.                     Debug.Log(button.ButtonID);
    276.                 if (playerAction.IsPressed)
    277.                 {
    278.                     button.TriggerButtonPressed();
    279.                 }
    280.                 if (playerAction.IsPressed && playerAction.HasChanged)
    281.                 {
    282.                     button.TriggerButtonDown();
    283.                 }
    284.                 if (playerAction.WasReleased)
    285.                 {
    286.                     button.TriggerButtonUp();
    287.                 }
    288. #else
    289.                 if (Input.GetButton(button.ButtonID))
    290.                 {
    291.                     button.TriggerButtonPressed ();
    292.                 }
    293.                 if (Input.GetButtonDown(button.ButtonID))
    294.                 {
    295.                     button.TriggerButtonDown ();
    296.                 }
    297.                 if (Input.GetButtonUp(button.ButtonID))
    298.                 {
    299.                     button.TriggerButtonUp ();
    300.                 }
    301. #endif
    302.             }
    303.         }
    304.  
    305.         /// <summary>
    306.         /// Called at LateUpdate(), this method processes the button states of all registered buttons
    307.         /// </summary>
    308.         public virtual void ProcessButtonStates()
    309.         {
    310.             // for each button, if we were at ButtonDown this frame, we go to ButtonPressed. If we were at ButtonUp, we're now Off
    311.             foreach (MMInput.IMButton button in ButtonList)
    312.             {
    313.                 if (button.State.CurrentState == MMInput.ButtonStates.ButtonDown)
    314.                 {
    315.                     if (DelayedButtonPresses)
    316.                     {
    317.                         StartCoroutine(DelayButtonPress(button));
    318.                     }
    319.                     else
    320.                     {
    321.                         button.State.ChangeState(MMInput.ButtonStates.ButtonPressed);
    322.                     }
    323.  
    324.                 }  
    325.                 if (button.State.CurrentState == MMInput.ButtonStates.ButtonUp)
    326.                 {
    327.                     if (DelayedButtonPresses)
    328.                     {
    329.                         StartCoroutine(DelayButtonRelease(button));
    330.                     }
    331.                     else
    332.                     {
    333.                         button.State.ChangeState(MMInput.ButtonStates.Off);
    334.                     }
    335.                 }  
    336.             }
    337.         }
    338.  
    339.         /// <summary>
    340.         /// A coroutine that changes the pressed state one frame later
    341.         /// </summary>
    342.         /// <param name="button"></param>
    343.         /// <returns></returns>
    344.         IEnumerator DelayButtonPress(MMInput.IMButton button)
    345.         {
    346.             yield return null;
    347.             button.State.ChangeState(MMInput.ButtonStates.ButtonPressed);
    348.         }
    349.  
    350.         /// <summary>
    351.         /// A coroutine that changes the pressed state one frame later
    352.         /// </summary>
    353.         /// <param name="button"></param>
    354.         /// <returns></returns>
    355.         IEnumerator DelayButtonRelease(MMInput.IMButton button)
    356.         {
    357.             yield return null;
    358.             button.State.ChangeState(MMInput.ButtonStates.Off);
    359.         }
    360.  
    361.         /// <summary>
    362.         /// Called every frame, if not on mobile, gets primary movement values from input
    363.         /// </summary>
    364.         public virtual void SetMovement()
    365.         {
    366.             if (!IsMobile && InputDetectionActive)
    367.             {
    368. #if USE_INCONTROL
    369.                 _primaryMovement.x = MMInControl.Instance.playerActions.MoveHorizontal.Value;
    370.                 _primaryMovement.y = MMInControl.Instance.playerActions.MoveVertical.Value;
    371. #else
    372.                 if (SmoothMovement)
    373.                 {
    374.                     _primaryMovement.x = Input.GetAxis(_axisHorizontal);
    375.                     _primaryMovement.y = Input.GetAxis(_axisVertical);      
    376.                 }
    377.                 else
    378.                 {
    379.                     _primaryMovement.x = Input.GetAxisRaw(_axisHorizontal);
    380.                     _primaryMovement.y = Input.GetAxisRaw(_axisVertical);      
    381.                 }
    382. #endif
    383.             }
    384.         }
    385.  
    386.         /// <summary>
    387.         /// Called every frame, if not on mobile, gets secondary movement values from input
    388.         /// </summary>
    389.         public virtual void SetSecondaryMovement()
    390.         {
    391.             if (!IsMobile && InputDetectionActive)
    392.             {
    393. #if USE_INCONTROL
    394.                 _secondaryMovement.x = MMInControl.Instance.playerActions.MoveHorizontalSecondary.Value;
    395.                 _secondaryMovement.y = MMInControl.Instance.playerActions.MoveVerticalSecondary.Value;
    396. #else
    397.                 if (SmoothMovement)
    398.                 {
    399.                     _secondaryMovement.x = Input.GetAxis(_axisSecondaryHorizontal);
    400.                     _secondaryMovement.y = Input.GetAxis(_axisSecondaryVertical);      
    401.                 }
    402.                 else
    403.                 {
    404.                     _secondaryMovement.x = Input.GetAxisRaw(_axisSecondaryHorizontal);
    405.                     _secondaryMovement.y = Input.GetAxisRaw(_axisSecondaryVertical);      
    406.                 }
    407. #endif
    408.             }
    409.         }
    410.  
    411.         /// <summary>
    412.         /// Called every frame, if not on mobile, gets shoot axis values from input
    413.         /// </summary>
    414.         protected virtual void SetShootAxis()
    415.         {
    416.             if (!IsMobile && InputDetectionActive)
    417.             {
    418. #if USE_INCONTROL
    419.                 ShootAxis = MMInput.ProcessAxisAsButton(_axisShoot, Threshold.y, ShootAxis, MMInput.AxisTypes.Positive);
    420.                 SecondaryShootAxis = MMInput.ProcessAxisAsButton(_axisShootSecondary, -Threshold.y, SecondaryShootAxis, MMInput.AxisTypes.Negative);
    421. #else
    422.                 ShootAxis = MMInput.ProcessAxisAsButton(_axisShoot, Threshold.y, ShootAxis, MMInput.AxisTypes.Positive);
    423.                 SecondaryShootAxis = MMInput.ProcessAxisAsButton(_axisShootSecondary, -Threshold.y, SecondaryShootAxis, MMInput.AxisTypes.Negative);
    424. #endif
    425.             }
    426.         }
    427.  
    428.         /// <summary>
    429.         /// If you're using a touch joystick, bind your main joystick to this method
    430.         /// </summary>
    431.         /// <param name="movement">Movement.</param>
    432.         public virtual void SetMovement(Vector2 movement)
    433.         {
    434.             if (IsMobile && InputDetectionActive)
    435.             {
    436.                 _primaryMovement.x = movement.x;
    437.                 _primaryMovement.y = movement.y;  
    438.             }
    439.         }
    440.  
    441.         /// <summary>
    442.         /// If you're using a touch joystick, bind your secondary joystick to this method
    443.         /// </summary>
    444.         /// <param name="movement">Movement.</param>
    445.         public virtual void SetSecondaryMovement(Vector2 movement)
    446.         {
    447.             if (IsMobile && InputDetectionActive)
    448.             {
    449.                 _secondaryMovement.x = movement.x;
    450.                 _secondaryMovement.y = movement.y;  
    451.             }
    452.         }
    453.  
    454.         /// <summary>
    455.         /// If you're using touch arrows, bind your left/right arrows to this method
    456.         /// </summary>
    457.         /// <param name="">.</param>
    458.         public virtual void SetHorizontalMovement(float horizontalInput)
    459.         {
    460.             if (IsMobile && InputDetectionActive)
    461.             {
    462.                 _primaryMovement.x = horizontalInput;
    463.             }
    464.         }
    465.  
    466.         /// <summary>
    467.         /// If you're using touch arrows, bind your secondary down/up arrows to this method
    468.         /// </summary>
    469.         /// <param name="">.</param>
    470.         public virtual void SetVerticalMovement(float verticalInput)
    471.         {
    472.             if (IsMobile && InputDetectionActive)
    473.             {
    474.                 _primaryMovement.y = verticalInput;
    475.             }
    476.         }
    477.  
    478.         /// <summary>
    479.         /// If you're using touch arrows, bind your secondary left/right arrows to this method
    480.         /// </summary>
    481.         /// <param name="">.</param>
    482.         public virtual void SetSecondaryHorizontalMovement(float horizontalInput)
    483.         {
    484.             if (IsMobile && InputDetectionActive)
    485.             {
    486.                 _secondaryMovement.x = horizontalInput;
    487.             }
    488.         }
    489.  
    490.         /// <summary>
    491.         /// If you're using touch arrows, bind your down/up arrows to this method
    492.         /// </summary>
    493.         /// <param name="">.</param>
    494.         public virtual void SetSecondaryVerticalMovement(float verticalInput)
    495.         {
    496.             if (IsMobile && InputDetectionActive)
    497.             {
    498.                 _secondaryMovement.y = verticalInput;
    499.             }
    500.         }
    501.  
    502.         public virtual void JumpButtonDown()                { JumpButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    503.         public virtual void JumpButtonPressed()             { JumpButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    504.         public virtual void JumpButtonUp()                  { JumpButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    505.  
    506.         public virtual void SwimButtonDown()                { SwimButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    507.         public virtual void SwimButtonPressed()             { SwimButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    508.         public virtual void SwimButtonUp()                  { SwimButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    509.  
    510.         public virtual void GlideButtonDown()               { GlideButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    511.         public virtual void GlideButtonPressed()            { GlideButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    512.         public virtual void GlideButtonUp()                 { GlideButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    513.  
    514.         public virtual void InteractButtonDown()            { InteractButton.State.ChangeState (MMInput.ButtonStates.ButtonDown); }
    515.         public virtual void InteractButtonPressed()            { InteractButton.State.ChangeState (MMInput.ButtonStates.ButtonPressed); }
    516.         public virtual void InteractButtonUp()                { InteractButton.State.ChangeState (MMInput.ButtonStates.ButtonUp); }
    517.  
    518.         public virtual void DashButtonDown()                { DashButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    519.         public virtual void DashButtonPressed()             { DashButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    520.         public virtual void DashButtonUp()                  { DashButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    521.  
    522.         public virtual void RollButtonDown()                { RollButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    523.         public virtual void RollButtonPressed()             { RollButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    524.         public virtual void RollButtonUp()                  { RollButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    525.  
    526.         public virtual void FlyButtonDown()                 { FlyButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    527.         public virtual void FlyButtonPressed()              { FlyButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    528.         public virtual void FlyButtonUp()                   { FlyButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    529.  
    530.         public virtual void RunButtonDown()                    { RunButton.State.ChangeState (MMInput.ButtonStates.ButtonDown); }
    531.         public virtual void RunButtonPressed()                { RunButton.State.ChangeState (MMInput.ButtonStates.ButtonPressed); }
    532.         public virtual void RunButtonUp()                    { RunButton.State.ChangeState (MMInput.ButtonStates.ButtonUp); }
    533.  
    534.         public virtual void JetpackButtonDown()                { JetpackButton.State.ChangeState (MMInput.ButtonStates.ButtonDown); }
    535.         public virtual void JetpackButtonPressed()            { JetpackButton.State.ChangeState (MMInput.ButtonStates.ButtonPressed); }
    536.         public virtual void JetpackButtonUp()                { JetpackButton.State.ChangeState (MMInput.ButtonStates.ButtonUp); }
    537.  
    538.         public virtual void ReloadButtonDown()              { ReloadButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    539.         public virtual void ReloadButtonPressed()           { ReloadButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    540.         public virtual void ReloadButtonUp()                { ReloadButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    541.      
    542.         public virtual void PushButtonDown()                { PushButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    543.         public virtual void PushButtonPressed()             { PushButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    544.         public virtual void PushButtonUp()                  { PushButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    545.  
    546.         public virtual void ShootButtonDown()               { ShootButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    547.         public virtual void ShootButtonPressed()            { ShootButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    548.         public virtual void ShootButtonUp()                 { ShootButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    549.  
    550.         public virtual void SecondaryShootButtonDown()      { SecondaryShootButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    551.         public virtual void SecondaryShootButtonPressed()   { SecondaryShootButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    552.         public virtual void SecondaryShootButtonUp()        { SecondaryShootButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    553.  
    554.         public virtual void PauseButtonDown()                { PauseButton.State.ChangeState (MMInput.ButtonStates.ButtonDown); }
    555.         public virtual void PauseButtonPressed()            { PauseButton.State.ChangeState (MMInput.ButtonStates.ButtonPressed); }
    556.         public virtual void PauseButtonUp()                    { PauseButton.State.ChangeState (MMInput.ButtonStates.ButtonUp); }
    557.  
    558.         public virtual void SwitchWeaponButtonDown()        { SwitchWeaponButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    559.         public virtual void SwitchWeaponButtonPressed()     { SwitchWeaponButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    560.         public virtual void SwitchWeaponButtonUp()          { SwitchWeaponButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    561.  
    562.         public virtual void SwitchCharacterButtonDown()     { SwitchCharacterButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    563.         public virtual void SwitchCharacterButtonPressed()  { SwitchCharacterButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    564.         public virtual void SwitchCharacterButtonUp()       { SwitchCharacterButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    565.  
    566.         public virtual void TimeControlButtonDown()         { TimeControlButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    567.         public virtual void TimeControlButtonPressed()      { TimeControlButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    568.         public virtual void TimeControlButtonUp()           { TimeControlButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    569.  
    570.         public virtual void GrabButtonDown() { GrabButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    571.         public virtual void GrabButtonPressed() { GrabButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    572.         public virtual void GrabButtonUp() { GrabButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    573.  
    574.         public virtual void ThrowButtonDown() { ThrowButton.State.ChangeState(MMInput.ButtonStates.ButtonDown); }
    575.         public virtual void ThrowButtonPressed() { ThrowButton.State.ChangeState(MMInput.ButtonStates.ButtonPressed); }
    576.         public virtual void ThrowButtonUp() { ThrowButton.State.ChangeState(MMInput.ButtonStates.ButtonUp); }
    577.  
    578.     }
    579. }
     

    Attached Files:

    Sazem and reuno like this.
  6. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    moatdd likes this.
  7. moatdd

    moatdd

    Joined:
    Jan 13, 2013
    Posts:
    178
  8. moatdd

    moatdd

    Joined:
    Jan 13, 2013
    Posts:
    178
    In CharacterCrouch.cs, there is a small bug that may make it difficult to crouch without crawling if you're using an analog controller.

    This should take care of it.

    Code (CSharp):
    1.         /// <summary>
    2.         /// Runs every frame to check if we should switch from crouching to crawling or the other way around
    3.         /// </summary>
    4.         protected virtual void DetermineState()
    5.         {
    6.             if ((_movement.CurrentState == CharacterStates.MovementStates.Crouching) || (_movement.CurrentState == CharacterStates.MovementStates.Crawling))
    7.             {
    8.                 // if ( (Mathf.Abs(_horizontalInput) > 0) && (CrawlAuthorized) ) // moat: Changed "0" to _inputManager.Threshold.x
    9.                 if ( (Mathf.Abs(_horizontalInput) > _inputManager.Threshold.x) && (CrawlAuthorized) )
    10.                 {
    11.                     _movement.ChangeState(CharacterStates.MovementStates.Crawling);
    12.                 }
    13.                 else
    14.                 {
    15.                     _movement.ChangeState(CharacterStates.MovementStates.Crouching);
    16.                 }
    17.             }
    18.         }
    19.  
     
    reuno likes this.
  9. EarlyDarkEntertainment

    EarlyDarkEntertainment

    Joined:
    Oct 8, 2018
    Posts:
    15
    Hello I noticed that Rolling recovers health

    *fixed it by using _health.Invulnerable instead of _health.enabled
     

    Attached Files:

    Last edited: May 31, 2021
  10. moatdd

    moatdd

    Joined:
    Jan 13, 2013
    Posts:
    178
    Are your items not respawning even though they have an AutoRespawn component with a delay set on them?

    Make sure DisableObjectOnPick is FALSE!

    Also make these changes:

    PickableItem.cs PickItem(GameObject picker)

    Code (CSharp):
    1.         /// <summary>
    2.         /// Check if the item is pickable and if yes, proceeds with triggering the effects and disabling the object
    3.         /// </summary>
    4.         public virtual void PickItem(GameObject picker)
    5.         {
    6.             if (CheckIfPickable ())
    7.             {
    8.                 Effects ();
    9.                 PickableItemEvent.Trigger(this);
    10.                 Pick ();
    11.                 if (DisableObjectOnPick)
    12.                 {
    13.                     // we desactivate the gameobject
    14.                     gameObject.SetActive (false);  
    15.                 }
    16.                 else
    17.                 {
    18.                     if (DisableColliderOnPick)
    19.                     {
    20.                         _collider.enabled = false;
    21.                     }
    22.                     if (DisableRendererOnPick && (_renderer != null))
    23.                     {
    24.                         _renderer.enabled = false;
    25.                     }
    26.  
    27.                     if (c_AutoRespawn) c_AutoRespawn.Kill();
    28.                 }
    29.             }
    30.         }
    31.         private AutoRespawn __AutoRespawn;
    32.         public AutoRespawn c_AutoRespawn { get { __AutoRespawn ??= GetComponent<AutoRespawn>(); return __AutoRespawn; } }
    33.  
    upload_2021-5-30_17-16-14.png

    The AutoRespawner's Kill() function has to be called to initiate its respawn countdown. This fix does that.
     
  11. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @moatdd > If you think you've found a bug, please don't hesitate to use the support form to report it, thanks.
     
  12. moatdd

    moatdd

    Joined:
    Jan 13, 2013
    Posts:
    178
    @reuno I'm stubborn and I try to fix everything myself!!!

    Actually, despite my amazing technical prowess I was unable to find the support form.
     
    reuno likes this.
  13. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
  14. moatdd

    moatdd

    Joined:
    Jan 13, 2013
    Posts:
    178
    Lol I was looking for a dedicated "Report a bug" form and didn't consider the general-purpose contact form (which many sites use for sales inquiries). Thanks.
     
    reuno likes this.
  15. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @moatdd > A long time ago I had many forms, it ended up generating more confusion than good :) Now it's a very multi purpose form.
     
  16. starvanger

    starvanger

    Joined:
    Oct 4, 2010
    Posts:
    19
    Hi reuno,

    I found a bug in character jump.
    Our player just should be able to do one jump, so I set one jump.
    If the player enters a dialogue zone, and you skip through the dialogue using space, the player can not jump anymore after the dialogue ended.
    Reason: NumberOfJumpsLeft is set to 0 after jumpstart.
    The dialogue freezes the player and on unfreeze, there is no jump left.
    Looks as if you did not test in your engine with the player just doing on jump.
    The error is not happening, when your player is set to do 2 jumps as NumberOfJumpsLeft still is 1.

    I made a hotfix in our game, but, I am sure you need to fix that bug in one future update.

    To prevent my hotfix being overwritten in the next update, it might be good to know, where you will fix it ...

    My hotfix is in character unfreeze, where I just reset the Number of Jumps.

    public virtual void UnFreeze()
    {
    _controller.GravityActive(true);
    ConditionState.ChangeState(CharacterStates.CharacterConditions.Normal);
    FindAbility<CharacterJump>().NumberOfJumpsLeft = FindAbility<CharacterJump>().NumberOfJumps;
    }

    Please tell me, where you would to fix it, so I could make sure our content will not break.

    Thanks in advance

    Starry
     
  17. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @starvanger > If you think you've found a bug, please use the support form to report it, and make sure you provide context info (what version you're in, how to reproduce, in what demo, etc), thanks.
     
  18. Creotronic

    Creotronic

    Joined:
    Oct 31, 2020
    Posts:
    10
    A quick question regarding falling platforms: I'm having a little problem where my character touches the platform, it starts to fall and the player falls with it. However, the player does not keep standing on the falling platform (that's what I would expect), it falls slightly slower, stuttering in the air (falling and landing on the falling platform again and then falling again). The issue seems to be present in the demos as well, albeit not that visible (the retro corgi character, for example, is also slightly stuttering when standing on a falling block). Is this a known issue or is there something I could change to prevent this from happening? Apart from that, all collisions and player movements work perfectly fine.
     
  19. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @Creotronic > That seems normal, that's likely gravity fighting the speed of your falling platform. If you'd rather have them behave like moving platforms (where the player is anchored to the platform), you can use moving platforms instead.
     
    Creotronic likes this.
  20. Creotronic

    Creotronic

    Joined:
    Oct 31, 2020
    Posts:
    10
    Thanks for the fast response! I will check moving platforms then.
     
    reuno likes this.
  21. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    Good news everyone, I've just pushed a new update to the asset store, v7.1. It fixes quite a few bugs that popped with 7.0 including a pretty breaking ladder bug, and also introduces a bunch of quality of life improvements. Here are the full release notes :

    - Adds public methods to save/load/reset to the MMSoundManager, on top of the event based ones that already existed
    - Adds the AutomaticallySetPhysicsSettings option to CorgiController, to set a number of physics settings on init to ensure they're correctly setup. It's false by default to not break existing projects, but it's a recommended setting
    - Proportional jumps now support input buffer duration
    - Adds AutoRespawn after X support to PickableItems
    - Adds extra bool methods to MMInput to test for recently pressed/released input
    - Adds support for 2D cinemachine confiners, via the new BoundsMode setting on the LevelManager
    - LevelManager's PointsOfEntry is now a list (and not an array anymore). Removes PointsOfEntryLegacy
    - AIBrain's ResetBrain method now forces OnExitState
    - The CharacterCrouch input detection now checks against the input manager's x threshold if the character is input driven
    - Adds extra sanity checks to AIActions/Decisions' OnExitState
    - Replaces ExecuteInEditMode with ExecuteAlways.
    - Fixes wrong bindings in the startscreen's options menu
    - Fixes a wrong resize on crouch scale on Rectangle and RectangleWithInventory prefabs
    - Fixes a bug that would cause WeaponAim's clamps to not apply correctly when flipped
    - Fixes a bug that would cause InstantAcceleration to not be applied correctly when in the air
    - Removes a useless attribute in LevelManager
    - Fixes a bug where CharacterFallDamage would also erroneously apply damage when jumping and landing very high
    - Fixes a bug that would cause exiting ladder by touching the ground to lock the character in place
    - Fixes a bug that would cause melee weapons to not keep track of damage events if manually disabled/enabled at runtime
    - Fixes a bug that would cause double jumps when dealing with very small jumps while having an input buffer duration bigger than minimum air time
    - Fixes a bug that would cause CinemachineCameraControllers to ignore a false ConfineCameraToLevelBounds setting.
    - Fixes a bug that would cause the roll ability to reset Health values.
    - Fixes a typo in the InventoryEngine readme
    - Changes some MMFeedbacks editor icons due to Unity apparently removing them from more recent versions without any mention of that anywhere
    - Switch animations are now snappier
    - Renames TilemapLevelGenerator's GenerateOnStart to GenerateOnAwake, to reflect what it actually does
    - Removes useless variables in HitscanWeapon
    - Fixes a few typos in comments in Loot and Tilemap classes
    - Adds a component menu entry to MMSoundManager
     
  22. moatdd

    moatdd

    Joined:
    Jan 13, 2013
    Posts:
    178
    I reworked the steps for InControl support to make it more self-contained so that it won't break when the Corgi Engine is updated:

    First, find the InControl Assembly Reference and...
    upload_2021-6-4_16-55-48.png

    ...add these two assembly def refs from the Corgi Engine
    upload_2021-6-4_16-56-12.png

    Make a CorgiEngine directory in your InControl directory
    upload_2021-6-4_17-1-2.png

    Within this new CorgiEngine directory, add MMInControl.cs and MMInControlInputManager.cs (attached to post)

    Use MMInControlInputManager instead of Corgi's InputManager if you want to use InControl. It's a subclass that inherits from Corgi's InputManager and overrides the following methods with equivalents that pull input from InControl.
    • GetInputButtons()
    • SetMovement()
    • SetSecondaryMovement()
    • SetShootAxis().
     

    Attached Files:

    Sazem and reuno like this.
  23. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    Good news everyone, I've just pushed v7.2 to the asset store.
    This small update adds a bounce ability, updates MMFeedbacks to its latest version, and fixes a few minor bugs. Full release notes :

    - Adds the CharacterBounce ability, that will have your character jump back up every time it touches the ground
    - Adds MMFeedbacks v2.3
    - Removes old FormerlySerializedAs attributes in CharacterJump, DamageOnTouch, Weapon and TilemapLevelGenerator
    - Removes Physics2D autosimulation bool, deprecated in 2020+
    - Fixes a bug that could cause a non magazine based weapon to get stuck if forced to reload
    - Fixes a bug in BouncyProjectile that could result in incorrect normals
     
    ifhd likes this.
  24. ifhd

    ifhd

    Joined:
    Jul 20, 2020
    Posts:
    7
    Now I feel like your reading my mind. I was thinking about perlin noise and drunken procedural generation levels and it get implemented. Next I want to create a Mario bouncy star and you add bounce ability. Now I am thinking of a spelunky style 4x4 procedural generation levels.
     
    reuno likes this.
  25. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @ifhd > Ok now it's getting weird, that's next on my list :)
     
    ifhd likes this.
  26. Creotronic

    Creotronic

    Joined:
    Oct 31, 2020
    Posts:
    10
    Hey, a quick question regarding horizontal movement: I want to adjust the time it takes for my character to reach its maximum walk speed (which, as far as I understand it, is the value I enter for "Walk Speed"). I thought I can adjust the time it takes to reach walk speed with the setting for speed acceleration on the ground. If I set that really low (like 1), it takes quite a while to reach the maximum walk speed. However, it seems I can set this as high as I want, it always takes a minimum amount of time to reach the maximum walk speed. Is there anything I'm overlooking?
     
  27. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @Creotronic > You can set InstantAcceleration to true on your HorizontalMovement ability, and turn SmoothMovement off on your InputManager.
     
    Creotronic likes this.
  28. Creotronic

    Creotronic

    Joined:
    Oct 31, 2020
    Posts:
    10
    Thanks for the quick reply. Instant-acceleration gets very close to what I want, so I might just use that. I'm not sure if something like "almost" instant-acceleration would be even better (like, you can adjust the time it takes to reach max speed), but that should be barely noticeable in my case.
     
  29. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    You can also play on the actual input settings (dead zone, sensitivity, etc) in Unity's input manager settings.
     
  30. KONDRAT_GAMES

    KONDRAT_GAMES

    Joined:
    Apr 30, 2021
    Posts:
    6
    Hello, how can I add unity ads or google ads to the corgi engine so that ads appear when passing a level?
     
  31. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @Pilcompot > You can do that like you would in any Unity project, it's entirely unrelated to the engine (which focuses on gameplay mechanics only).
     
  32. KONDRAT_GAMES

    KONDRAT_GAMES

    Joined:
    Apr 30, 2021
    Posts:
    6
    Hello again, how to make a scene similar to "PauseSplash" when taking an object such as "coin"?
     
  33. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @Pilcompot > The PauseSplash isn't a scene, it's just a UI element. And you could display one like you would in any other Unity project, it's not something that'd be specific to the engine. I'd recommend extending the Coin class, to have it trigger an event of yours. Then have another class catch that event, and display any UI element you want. There are other ways of course but this one would be the cleanest.
     
  34. Creotronic

    Creotronic

    Joined:
    Oct 31, 2020
    Posts:
    10
    Hello, I'm trying to get a dialog zone to enable a character ability (dash, in this case), but it does not work as expected. On my character prefab, I have unchecked the "permit ability" for the dash component – the character can not dash, works fine. On the dialog zone, I added an action (on activation) and selected the player character prefab with CharacterDash.PermitAbility (and then checked the box, so the ability gets permitted on activation). What happens when I run the game in the editor, is that after interacting with the dialog zone, my character still can't dash. If I stop and start the game in the editor again, however, the character can dash (even before interacting with the dialog zone). I tried switching between "runtime" and "editor and runtime" for the action, but that did not help.

    Is there anything I am overlooking here? Maybe there is an example in one of the demos of a dialog zone enabling a character ability I could look at?
     
  35. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @Creotronic > No, there are no examples of a dialogue zone enabling an ability (that's oddly specific), but you can look at the PickableJetpack for an example of ability activation (on pick, in this case).
     
    Creotronic likes this.
  36. Creotronic

    Creotronic

    Joined:
    Oct 31, 2020
    Posts:
    10
    Perfect, that works!
     
    reuno likes this.
  37. LukiSouki

    LukiSouki

    Joined:
    May 21, 2021
    Posts:
    5
    Hello Corgi Team,
    i am new to Unity and new to the Corgi engine but i have some experience with game creation. I always wanted to make a Contra like 16bit jump and shoot kind of game and i figured now is the time before i get too old. I figured out how to make my character move and shoot, i know it is kind of trivial but i´d be very grateful if someone can help me out: i want my character to behave like the character in Contra 3 on SNES or Contra Hard Corps on Genesis. Everything is working so far, what i cannot figure out is how to make my character shoot forward (not down) while crouching. Also i need to have additional animations for my character when shooting diagonally and i cannot properly implement it.

    Thanks for the great engine, i am having a lot of fun!
    Cheers, Luke
     
  38. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @LukiSouki > Hey Luke! Right now, there's no Contra-like feature in the engine regarding aiming while crouched. It's never been requested before that I can tell, but I'd be happy to add that to the todo list if you'd like. In the meantime, it's already doable if you know a bit of C#.

    One way to do it would be to extend WeaponAim, to add a check on the weapon owner's current state, and if it's crouching/crawling, then prevent aim (or force its direction).

    As for diagonal animations, that's something you can fix in your animator. The engine exposes animation parameters you can use to implement any animation setup you want. In this case you could use your weapon's angle relative anim parameter (see https://corgi-engine-docs.moremountains.com/animations.html#weapon-animation-parameters for details).
     
  39. LukiSouki

    LukiSouki

    Joined:
    May 21, 2021
    Posts:
    5
    Thank you for the quick reply! I will try to implement your suggestions into my draft and see if i can get it to work. Please add it to the todo list if possible.
    Thank you and keep up the great work
     
    reuno likes this.
  40. SirusAmory

    SirusAmory

    Joined:
    Feb 27, 2016
    Posts:
    4
    Hiya! I'm enjoying playing with the engine so far. I was just wondering if there was support planned for any of the scriptable renderer pipelines, more specifically the URP?
     
  41. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @SirusAmory > The engine doesn't do any rendering, it focuses on gameplay mechanics, so it'll work on any render pipeline, URP included. The demos are built using the standard RP, which is still the best option out there, and the most common denominator. No plans to change that in the current messy state of URP.
     
    Fed81 and SirusAmory like this.
  42. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    @SirusAmory
    I think the demos should convert to URP automatically, for the most part, with the possible exception of the particle effects. Unity has a built-in converter for the most common built-in shaders. In my experiments the standard shader and sprite shader converted automatically, but the particle shaders weren't handled. In URP, however, you have the benefit of shader graph, so recreating these shaders is easy. Try it yourself. YMMV

    Additionally, there's really no need for the demo assets to work because you can just start your game from scratch using URP-ready assets from the beginning.
     
    SirusAmory and reuno like this.
  43. SirusAmory

    SirusAmory

    Joined:
    Feb 27, 2016
    Posts:
    4
    Okay, gotcha. Just curious. I'll fiddle with graphics stuff after I'm ready to tackle art stuff.

    BTW: I'm trying to recreate the beams from the 2D Metroid games using a Projectile Weapon and the Multi Object Pooler and there seems to be a delay in switching between each nested pool. Am I doing something here?
     
  44. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @SirusAmory > No, there's no delay when switching between pools. But without knowing how you're doing it, it's hard to tell if you're doing something wrong, or what.
     
  45. SirusAmory

    SirusAmory

    Joined:
    Feb 27, 2016
    Posts:
    4
    I have a script that switches off each pool and then on update that script checks the index of the pooler and if it reaches the limit of the projectile gameobject, it resets the index to the first instance of that gameobject.

    Code (CSharp):
    1.  void SwitchAmmo()
    2.     {
    3.         switch (CurrentPoolIndex)
    4.         {
    5.             case 0:
    6.             {
    7.                 BeamAmmo.Pool[CurrentPoolIndex].Enabled = false;
    8.                 CurrentPoolIndex = 1;
    9.                 BeamAmmo.Pool[CurrentPoolIndex].Enabled = true;
    10.                 BeamAmmo.UpdateCurrentIndex(21);
    11.                 break;
    12.             }
    13.             case 1:
    14.             {
    15.                 BeamAmmo.Pool[CurrentPoolIndex].Enabled = false;
    16.                 CurrentPoolIndex = 2;
    17.                 BeamAmmo.Pool[CurrentPoolIndex].Enabled = true;
    18.  
    19.                 BeamAmmo.UpdateCurrentIndex(41);
    20.                 break;
    21.             }
    22.  
    23. void Update()
    24.     {
    25.         switch (CurrentPoolIndex)
    26.         {
    27.             case 0:
    28.             {
    29.                 if (BeamAmmo.GetCurrentIndex() >= 21)
    30.                 {
    31.                    
    32.                     BeamAmmo.UpdateCurrentIndex(1);
    33.                 }
    34.  
    35.                 break;
    36.             }
    37.             case 1:
    38.             {
    39.                 if (BeamAmmo.GetCurrentIndex() >= 41)
    40.                 {
    41.                     BeamAmmo.UpdateCurrentIndex(21);
    42.                 }
    43.                 break;
    44.             }
    This is the addendum I made to the WeaponUse function in ProjectileWeapon

    Code (CSharp):
    1.  protected override void WeaponUse()
    2.         {
    3.             base.WeaponUse();
    4.  
    5.             DetermineSpawnPosition();
    6.             if (bUsesMultiPooler)
    7.             {
    8.                 if (ObjectPooler.GetComponent<MMMultipleObjectPooler>().Pool[0] == ObjectPooler.GetComponent<MMMultipleObjectPooler>().GetCurrentPoolerObject())
    9.                 {
    10.                     if (ObjectPooler.GetComponent<MMMultipleObjectPooler>().GetCurrentIndex() > 20)
    11.                     {
    12.                         ObjectPooler.GetComponent<MMMultipleObjectPooler>().ResetCurrentIndex();
    13.                     }
    14.              
    15.                 }
    16.  
    17.                 if (ObjectPooler.GetComponent<MMMultipleObjectPooler>().Pool[1].Enabled)
    18.                 {
    19.                     if (ObjectPooler.GetComponent<MMMultipleObjectPooler>().Pool[1] == ObjectPooler.GetComponent<MMMultipleObjectPooler>().GetCurrentPoolerObject())
    20.                     {
    21.                    
    22.                         if (ObjectPooler.GetComponent<MMMultipleObjectPooler>().GetCurrentIndex() > 40)
    23.                         {
    24.                             ObjectPooler.GetComponent<MMMultipleObjectPooler>().UpdateCurrentIndex(21);
    25.                         }
    26.              
    27.                     }
    28.                 }
    29.             }
    30.  
    31.             for (int i = 0; i < ProjectilesPerShot; i++)
    32.             {
    33.                 SpawnProjectile(SpawnPosition, i, ProjectilesPerShot, true);
    34.             }
    35.         }
     
  46. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @SirusAmory > At first glance, I'd recommend avoiding GetComponents on each WeaponUse like that, these can be cached. Although I doubt they're causing delays. What exactly do you mean by delays? Is it a freeze? I can add an example of that in a future update if you'd like. I don't think there's anything using it in the Corgi Engine, but the Infinite Runner Engine is built entirely on that same pool system, and uses it extensively, without any delay whatsoever.
     
  47. LorenzoSampietro

    LorenzoSampietro

    Joined:
    Jun 28, 2017
    Posts:
    20
    Hi @reuno,

    I have implemented a scene where the player jumps (space bar or tap).

    I would like to completely change the input mode when the player collides with the enemy: in this case the jump (space bar or tap) becomes a shoot, the player no longer jumps and no longer moves. Only after a few seconds does it return to normal game mode.

    In fact, the input manager changes and the game play changes
    I hope I have explained.

    Do you have any suggestions about it?

    thank you for your help :)
     
  48. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @LorenzoSampietro > there is no such feature in the engine at the moment, you'd have to implement it. I suppose extending the InputManager to add different control schemes, and having a dedicated ability would help. You could also swap your prefab for another one, it really depends on your exact steps. These are the two first avenues I'd explore!
     
  49. LorenzoSampietro

    LorenzoSampietro

    Joined:
    Jun 28, 2017
    Posts:
    20
    Thanks @reuno for your quick reply.
    I keep you updated. Have a nice weekend
     
    reuno likes this.
  50. LorenzoSampietro

    LorenzoSampietro

    Joined:
    Jun 28, 2017
    Posts:
    20
    Hello,
    I would like to use the gyroscope to adjust the left and right movement of the player.

    I saw that there is a class called MMGyroscope and I would like to implement a small script that executes SetHorizontalMove to the player's ability using this script.

    Among the gyroscope reading functions I found CalibratedGyroscopeGravity. Is it correct to use this?

    Thank you for your feedback