0
\$\begingroup\$

So i have been struggling with this for ages and I have now decided to reach out for help.

The Problem:

The game has two NPCs for reference we will call them "Ally" and "Enemy"

Ally and Enemy each have their own weapon:

  • Ally has a sword with a reach 0.1 - 2 meters

  • Enemy has a long sword that has a reach of 0.5 - 3 meters.

Now these two NPC's wish to fight each other. They need to make sure that they stay within the reach of their weapons while also making sure that they don't bump into each other.

For this I attempted the following algorithm:

bool shouldMove = false;
Vector3 lToTarget = Target.transform.position - transform.position;
lToTarget.y = 0f;

Vector3 lToTargetDirection = lToTarget.normalized;
float lToTargetDistance = lToTarget.magnitude;
float lRange = MinMeleeReach + MaxRange;
if (!shouldMove && lToTargetDistance > lRange + 1f)
{
    shouldMove = true;
}

if (shouldMove && lToTargetDistance <= Mathf.Max(lRange))
{
    shouldMove = false;
}

if (shouldMove)
{
    float lSpeed = Mathf.Min(MovementSpeed * Time.deltaTime, lToTargetDistance);
    transform.position = transform.position + (lToTargetDirection * lSpeed);
}

Now if they should not move then they would attack their target.

However as you might have guessed this has an issue:

The agent tries to keep his distance to the max of his range!

This sadly causes the agents to bug out in a way where they are never close enough to attack each other resulting in something that looks like this:

enter image description here

So i thought to my self how can i change this behavior.

I came up with another idea which sadly had the same problem this time using navmesh agent:

Vector3 direction =
    (transform.position - Target.position).normalized;
Vector3 finalPosition = Target.position + direction * maxRange;
navMeshAgent.SetDestination(finalPosition);

Again sort of same behavior, however, this time they just kept their distance and if the other agent came to close they would start moving backward. Which basically meant that they would move back to the end of the world.

So this is where I am at right now. I have attempted to google this issue however without much luck.

So i am really praying that you guys have an answer for me :)

if you need more information please do not hesitate to comment!

\$\endgroup\$
  • \$\begingroup\$ If they only need to make sure they don't bump into each other, then why not to check only "bumping" range? That is, their collision shape range plus some optional bias value. \$\endgroup\$ – Ocelot Jul 13 at 12:13
  • \$\begingroup\$ @Ocelot This is a test scene there will be more units on the battlefield so they need to keep their distance \$\endgroup\$ – Marc Rasmussen Jul 13 at 12:21
  • \$\begingroup\$ This is confusing, make sure to include all the cases you want to handle before asking for a solution. Maybe you will come up with your own in the process. \$\endgroup\$ – Ocelot Jul 13 at 13:47
0
\$\begingroup\$

I would try using springs - for each of the two characters a compression spring representing "defensivness", and an extension spring representing "aggression".

The force generated by the spring is calculated as F=kx, where x says how much is the loose end of the spring displaced from its relaxed position, k is the stiffness of the spring - the sign depends on type of the spring (compression/extension).

Summing up the forces for each character (for more units force vectors) gives direction in which the character should move. The force magnitude could probably somehow be mapped to speed.

The stiffness of the springs could vary over time (using some noise function), or be fixed per character to represent his fighting style. Combination of both should probably work best.

I have no idea how well this will work in practice though. :-)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.