Some slight bugs

Hello, so I followed the course and completed it, however, I do have a couple of bugs. First off I don’t have any errors or crashes, so finding the exact reason why these are happening are hard.

This is a video of all my current bugs, as you can see the enemy can hit me twice but can’t do any damage after that.

The 2nd bug you can also see is that when I get hit the character moves too deep into the floor. I know the reason is that the character’s controller is at their knees and not at their feet, I had to add different numbers than are given in the series. However in this video, you can see if I do swap it to the correct numbers the character is floating off the ground and I am not sure why, despite having the same stuff as the series had.

In this video, I switch the character controller to the right values, but as you can see I am off the floor.

I am not sure what scripts/values I should give to help lead you in the right direction for the bugs though.

Here is the enemy attacking state

public class EnemyAttackingState : EnemyBaseState
{
    private readonly int AttackHash = Animator.StringToHash("Attack");

    private const float TransitionDuration = 0.1f;

    public EnemyAttackingState(EnemyStateMachine stateMachine) : base(stateMachine)
    {
    }

    public override void Enter()
    {
        stateMachine.Weapon.SetAttack(stateMachine.AttackDamage, stateMachine.AttackKnockback);
        stateMachine.Animator.CrossFadeInFixedTime(AttackHash, TransitionDuration);
    }

    public override void Tick(float deltaTime)
    {
        
        if (GetNormalizedTime(stateMachine.Animator, "Attack") >= 1)
        {
            stateMachine.SwitchState(new EnemyChasingState(stateMachine));
        }
        FacePlayer();
    }

    public override void Exit()
    {
    }

   
}

and the chasing state

public class EnemyChasingState : EnemyBaseState
{

    private readonly int locomotionHash = Animator.StringToHash("Locomotion");
    private readonly int SpeedHash = Animator.StringToHash("Speed");

    private const float CrossFadeDuration = 0.1f;
    private const float AnimatorDampTime = 0.1f;

    public EnemyChasingState(EnemyStateMachine stateMachine) : base(stateMachine)
    {
    }

    public override void Enter()
    {
        stateMachine.Animator.CrossFadeInFixedTime(locomotionHash, CrossFadeDuration);

    }

    public override void Tick(float deltaTime)
    {
        Move(deltaTime);


        if (!IsInChaseRanger())
        {
            stateMachine.SwitchState(new EnemyIdleState(stateMachine));
            return;
        }else if(IsInAttackRange())
        {
            stateMachine.SwitchState(new EnemyAttackingState(stateMachine));
            return;
        }
        MoveToPlayer(deltaTime);
        FacePlayer();

        stateMachine.Animator.SetFloat(SpeedHash, 1f, AnimatorDampTime, deltaTime);
    }

    public override void Exit()
    {
        stateMachine.agent.ResetPath();
        stateMachine.agent.velocity = Vector3.zero;
    }

    private void MoveToPlayer(float deltaTime)
    {
        if(stateMachine.agent.isOnNavMesh)
        {
            stateMachine.agent.destination = stateMachine.Player.transform.position;

            Move(stateMachine.agent.desiredVelocity.normalized * stateMachine.MovementSpeed, deltaTime);
        }

        stateMachine.agent.velocity = stateMachine.Controller.velocity;
    }
    
    private bool IsInAttackRange()
    {
        if(stateMachine.Player.IsDead) { return false; }

        float playerDistanceSqr = (stateMachine.Player.transform.position - stateMachine.transform.position).sqrMagnitude;

        return playerDistanceSqr <= stateMachine.AttackRange * stateMachine.AttackRange;
    }

}

also, the targeted.cs

public class Targeter : MonoBehaviour
{
    [SerializeField]
    private CinemachineTargetGroup cineTargetGroup;

    private Camera maincamera;

    private List<Target> targets = new List<Target>();

    public Target CurrentTarget { get; private set; }

    private void Start()
    {
        maincamera = Camera.main; 
    }

    private void OnTriggerEnter(Collider other)
    {
        Target target = other.GetComponent<Target>();

        if (target == null) { return; }

        targets.Add(target);
        target.OnDestroyed += RemoveTarget;
    }

    private void OnTriggerExit(Collider other)
    {
        Target target = other.GetComponent<Target>();

        if(target == null) { return; }

        RemoveTarget(target);
    }

    public bool SelectTarget()
    {
        if(targets.Count == 0)
        {
            return false;
        }

        Target closestTarget = null;
        float closestTargetDistance = Mathf.Infinity;

        foreach(Target target in targets)
        {
            Vector2 viewPos = maincamera.WorldToViewportPoint(target.transform.position);

            if(!target.GetComponentInChildren<Renderer>().isVisible)
            {
                continue;
            }

            Vector2 toCenter = viewPos = new Vector2(0.5f, 0.5f);
            if(toCenter.sqrMagnitude < closestTargetDistance)
            {
                closestTarget = target;
                closestTargetDistance = toCenter.sqrMagnitude;
            }
        }

        if(closestTarget == null) { return false; }

        CurrentTarget = closestTarget;
        cineTargetGroup.AddMember(CurrentTarget.transform, 1f, 2f);
        return true;
    }

    public void Cancel()
    {
        if(CurrentTarget == null) { return; }

        cineTargetGroup.RemoveMember(CurrentTarget.transform);
        CurrentTarget = null;
    }

    private void RemoveTarget(Target target)
    {
        if(CurrentTarget == target)
        {
            cineTargetGroup.RemoveMember(CurrentTarget.transform);
            CurrentTarget = null;
        }

        target.OnDestroyed -= RemoveTarget;
        targets.Remove(target);
    }
}

Unfortunately, the videos were set to Private, so we can’t watch them. Try adjusting the settings on the video from private to either public or anyone with a link can access.

Sorry, I made them unlisted now, so they should work.

I’m wondering if the WeaponDamage isn’t properly clearing it’s AlreadyCollidedWith list when the new animation starts…

There are a couple of possible causes for this… one is the animation not disabling the collider after the attack is finished, which would mean even though we’re enabling the collider in another pass, OnEnable() is not called because we’re already enabled.

Let’s add a Debug to WeaponDamage.cs… in both OnEnable and OnDisable:

Debug.Log($"WeaponDamage OnEnable"); //use OnDisable in the OnDisableMethod

Approach the enemy and let him whack away. These two messages should come (or the count be incremented) pretty close to one another.

So as far as I can tell we don’t have an OnDisable on the weaponDamage.cs, this https://gitlab.com/GameDevTV/unity-3rd-person-combat-and-traversal/third-person-combat-and-traversal/-/commit/2cb6a87a85fafeb407bd59fecf56523dcb82fb20 is has the last set of changes to the weapon damage file which does not include an OnDisable method.

As for what happens when I use that Debug I get the following
image

interestingly I tried running the game again but this time only got hit once and this was the debug for that
image

Each time he swings it does the Debug message.

I know on the sword animation we have
image
set to a certain frame along in the animation.

which is in this file

public class WeaponHandler : MonoBehaviour
{

    [SerializeField]
    private GameObject weaponLogic;

    private void EnableWeapon()
    {
        weaponLogic.SetActive(true);
    }

    private void DisableWeapon()
    {
        weaponLogic.SetActive(false);
    }
}

In this case, adding an OnDisable() method would have done the trick. That being said, OnEnable is not called if the object wasn’t disabled in the first place. I’m assuming that OnEnable is clearing the AlreadyHit list of objects.

There are a few more things to try here:

  1. Start the EnableWeapon sooner in the Animation and DisableWeapon later in the animation
  2. Enlarge the collider on the weapon. I have mine extended a bit beyond the edge of the weapon to ensure it has a chance to hit the CharacterController. I like to call this Movie Punch setup (In the movies, the stuntmen are reallly good at landing a haymaker without actually contacting the other guy, and our brain tricks us into believing it).

I tried both of those and they did not help, however in doing the testing I found the actual issue. I had Use Gractiy enabled on the rigid body on the Weapon Logic. So on every swing, the position of the weapon logic was being moved away. I only noticed since I was double checking the hitboxes and saw something moving in the air which happen to be the weapon logic.

Do you have any advice on the 2nd issue where the player character is floating above the ground but when they are hit they actually move to the floor. You can see it in the 2nd video at the top.

That one is actually puzzling… It appears to be happening on the PlayerImpactState, with the player returning to the hover when exiting that state.

First things first, put the CharacterController center back where it was, put the feet back on the ground. We see what’s happening, the question is why…

If the issue was in the ForceReceiver, I don’t think the Capsule Collider would be allowing the push through the terrain, so I think the issue is somehow in the animation being used for the impact state.

The first thing I would try is to find a different reaction animation and see if the same thing is happening.

So after looking through some more stuff with your tip to look at the character animations. It seems like the animation’s hip.y position on my animations was all higher by at least .3f or more. I think that either means when I downloaded the animations I did not have the character model selected. Since I have downloaded them with the characters selected and replaced them and it works now.

If anyone in the future has the MISSING tag in the animations when you have the player selected, it probably means you did not have the correct character selected when downloading animations.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms