3
\$\begingroup\$

I'm trying to implement the Wander Steering Behaviour but getting strange result (see .gif). What am i doing wrong? I want to move a sphere in a random direction.

wander problem

using UnityEngine;

public class UnitWander : MonoBehaviour
{
    public const float CircleDistance = 1f;
    public const float CircleRadius = 0.1f;
    public const float AngleChange = 50f;

    public float Mass = 1;
    public float MaxSpeed = 1;
    public float MaxForce = 1;

    private Vector3 velocity = Vector3.forward;
    private float wanderAngle;

    private void Update()
    {
        var steering = GetWanderForce();
        steering = Vector3.ClampMagnitude(steering, MaxForce);
        steering /= Mass;

        velocity = Vector3.ClampMagnitude(velocity + steering, MaxSpeed);
        transform.position += velocity;
        transform.forward = velocity;
    }

    private Vector3 GetWanderForce()
    {
        var circleCenter = velocity.normalized * CircleDistance;

        var displacement = transform.right * Mathf.Cos(wanderAngle * Mathf.Deg2Rad) * CircleRadius;
        displacement += transform.up * Mathf.Sin(wanderAngle * Mathf.Deg2Rad) * CircleRadius;

        wanderAngle += (Random.value * AngleChange) - (AngleChange * 0.5f);

        var wanderForce = circleCenter + displacement;
        return wanderForce;
    }
}
\$\endgroup\$
  • \$\begingroup\$ add sample of code in the question. Links may go down \$\endgroup\$ – dnk drone.vs.drones Sep 3 '15 at 11:32
  • 1
    \$\begingroup\$ I see some neat gimbal locking \$\endgroup\$ – ratchet freak Sep 3 '15 at 11:44
  • 1
    \$\begingroup\$ Anglechange seems a bit large. The angle is measured in radians, 50 seems more a degree value. Also: do you pick a random direction every frame? \$\endgroup\$ – Felsir Sep 3 '15 at 12:16
  • \$\begingroup\$ @Felsir "do you pick a random direction every frame?" - yes, like in article. \$\endgroup\$ – Rusildo Sep 3 '15 at 12:41
  • \$\begingroup\$ @Rusildo picking a random direction in 3D means sampling the surface of the unit sphere. \$\endgroup\$ – ratchet freak Sep 3 '15 at 13:48
3
\$\begingroup\$

I solved the problem. Now script work fine. Just drop this script on game object and enjoy.

wander swarm

using UnityEngine;

public class UnitWander : MonoBehaviour
{
    public float CircleRadius = 1;
    public float TurnChance = 0.05f;
    public float MaxRadius = 5;

    public float Mass = 15;
    public float MaxSpeed = 3;
    public float MaxForce = 15;

    private Vector3 velocity;
    private Vector3 wanderForce;
    private Vector3 target;

    private void Start()
    {
        velocity = Random.onUnitSphere;
        wanderForce = GetRandomWanderForce();
    }

    private void Update()
    {
        var desiredVelocity = GetWanderForce();
        desiredVelocity = desiredVelocity.normalized * MaxSpeed;

        var steeringForce = desiredVelocity - velocity;
        steeringForce = Vector3.ClampMagnitude(steeringForce, MaxForce);
        steeringForce /= Mass;

        velocity = Vector3.ClampMagnitude(velocity + steeringForce, MaxSpeed);
        transform.position += velocity * Time.deltaTime;
        transform.forward = velocity.normalized;

        Debug.DrawRay(transform.position, velocity.normalized * 2, Color.green);
        Debug.DrawRay(transform.position, desiredVelocity.normalized * 2, Color.magenta);
    }

    private Vector3 GetWanderForce()
    {
        if (transform.position.magnitude > MaxRadius)
        {
            var directionToCenter = (target - transform.position).normalized;
            wanderForce = velocity.normalized + directionToCenter;
        }
        else if (Random.value < TurnChance)
        {
            wanderForce = GetRandomWanderForce();
        }

        return wanderForce;
    }

    private Vector3 GetRandomWanderForce()
    {
        var circleCenter = velocity.normalized;
        var randomPoint = Random.insideUnitCircle;

        var displacement = new Vector3(randomPoint.x, randomPoint.y) * CircleRadius;
        displacement = Quaternion.LookRotation(velocity) * displacement;

        var wanderForce = circleCenter + displacement;
        return wanderForce;
    }
}
\$\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.