Ability problems

ICC90

New member
Hello! I bought the third person controller recently, I love it but it has a big learning curve which is fine! I'm having some issues implementing a stealth kill ability. I'd like to start the ability when spherecasting to an unaware enemy (see code below for ability script) which works fine but I'm getting very inconsistent results. Sometimes the player's kill animation just doesn't play, also sometimes it does play but doesn't position behind the enemy, sometimes the player's and enemy's animations don't sync and when crouching it doesn't transition to the kill animation even though the kill is from any state. Also what would be the best way to smoothly lerp behind the enemy too instead of just teleporting there?

Here is the ability parameters
Unity_FyHlXZPFLZ.png

Here are the animator state transitions

Unity_286T90VO3L.png

Unity_cxOtIeLENC.png
Is there any visible reason why I'd be getting these random inconsistent results?
I'm not the best coder and this may be the wrong way to use the controller so happy to hear suggestions on how to use it better!

Stealth Kill Ability Script

Code:
public class StealthKill : Ability
{
    // Used to get normalized time of the animation playing.
    [SerializeField] private Animator animator;
    // Cannot exit the animation before this normalized time.
    [SerializeField] private float minimumPlayoutTime = 0.8f;


    private EnemyStateMachine enemy;
    private bool havePositioned = false;


    public override bool CanStartAbility()
    {
        if (CanStealthKill())
        {
            return true;
        }


        return false;
    }


    protected override void AbilityStarted()
    {
        base.AbilityStarted();


        // Received in the enemy state machine class, checks for enemy instance.
        EventHandler.ExecuteEvent(enemy, "StelthKill");
    }


    
    public override void UpdatePosition()
    {
        // After positioning behind the enemy, continue with moving with root motion.
        if (!havePositioned)
        {
            Vector3 newPos = enemy.transform.position + (enemy.transform.forward * -0.4f);
            m_CharacterLocomotion.SetPositionAndRotation(newPos, enemy.transform.rotation);
            havePositioned = true;
        }


        base.UpdatePosition();
        
    }


    // Ability checks every frame to see if it can be stopped. if the animation time is more than the playout time, we can stop.
    public override bool CanStopAbility(bool force)
    {
        AnimatorStateInfo currentInfo = animator.GetCurrentAnimatorStateInfo(0);
        AnimatorStateInfo nextInfo = animator.GetNextAnimatorStateInfo(0);


        if (animator.IsInTransition(0))
        {
            return nextInfo.normalizedTime > minimumPlayoutTime;
        }


        else if (!animator.IsInTransition(0))
        {
            return currentInfo.normalizedTime > minimumPlayoutTime;
        }


        return false;
    }


    protected override void AbilityStopped(bool force)
    {
        base.AbilityStopped(force);
    }


    // Checks for an unaware enemy in front of the player.
    private bool CanStealthKill()
    {
        Ray ray = new Ray(m_Transform.position + new Vector3(0, 1, 0), m_Transform.forward);
        Debug.DrawRay(ray.origin, ray.direction, Color.yellow, 1f);


        if (Physics.SphereCast(ray.origin, 0.5f, ray.direction, out RaycastHit hit, 1))
        {
            enemy = hit.transform.GetComponent<EnemyStateMachine>();
            if (enemy != null && !enemy.IsAlarmed)
            {
                return true;
            }


            return false;
        }


        return false;
    }
}
 
Happy to hear that you're enjoying the controller.

When you are transitioning to the stealth kill animation are you using the ability changed trigger as well? With this setup you should then get consistent results. Take a look at the transition to drive for example which checks the ability index and the trigger.

You can use the Move Towards Location in order to have the character move to a location first. The Drive ability also provides a good example of this - you will need to override the GetMoveTowardsLocations method.
 
Top