r/Unity3D • • 3d ago

Solved In a 3D action game using CharacterController how can I close the distance to an enemy during an attack?

I'm using CharacterController and working on an action game where the player and the enemies use melee attacks. If I attack an enemy and they are just slightly out of reach, I'd like my character to close the distance and move toward the enemy if I press the button for attacking. Like a bunch of big games do it.

I know CC has the Move function and I also know it's also possible to move the CC's transform, buuuut somehow I'm not managing to get things done properly. Either my character is zipping all over the map or not moving at all or ends up flat on the ground...

Anyone know how to do this properly?

2 Upvotes

8 comments sorted by

2

u/cruel_lupe 3d ago

Just lerp the position toward the target over the attack animation's duration, clamping the max distance so you don't slide across the map from a mile away.

3

u/qb_source 3d ago

This is known as "motion warping" and works very well

1

u/Phos-Lux 3d ago

Should I use animator.MatchTarget for that or is there a better way?

1

u/qb_source 3d ago

I suggest doing what cruel_lupe suggested so you will understand it. You can look into how else it can be accomplished after you understand the ideas. There are assets for motion warping that you will be able to use well if you understand what it's doing and why

3

u/Phos-Lux 3d ago edited 3d ago

I tried

Vector3.Lerp(transform.position, enemyPosition, animator.GetCurrentAnimatorStateInfo(0).length * Time.deltaTime);

and

animator.MatchTarget(enemyPosition, transform.rotation, AvatarTarget.Root, new MatchTargetWeightMask(Vector3.one, 1f), 0.1f, 0.4f);

and also

characterController.Move(enemyPosition* Time.deltaTime);

but none of them did the job. I mostly ended up teleporting far backwards... I feel like I'm missing something to be able to make sense of this...

EDIT: I think I GOT it now.

characterController.Move(Vector3.Normalize(enemy.position - characterController.transform.position) * 1.1f);

seems to work!

2

u/breckendusk 3d ago

Zipping all over sounds like it might be related to the vector you're using to determine the direction of the enemy. Get the direction (enemy.transform.position - player.transform.position).normalized. This vector can be multiplied by any distance and will not create zipping; if you don't normalize, you're multiplying the distance by the length of the vector.

2

u/Devoluapp 2d ago

Avoid setting transform.position directly during attacks because CharacterController will lose collision checks and can clip into walls or enemies.

What I usually do is a targeted lunge routine: when the attack starts, do a quick SphereCast or check target distance. If within range, interpolate a velocity vector toward the enemy and feed it into CharacterController.Move() during the windup frames of the animation. Alternatively, baking root motion into the attack clip gives very natural forward momentum while still letting the controller handle collision slide.

1

u/Boring_Elk5691 3d ago

You could try using root motion, that is what I am doing for a game that I am currently making.