Wander steering behaviour in 3D

Wander steering behaviour in 3D

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.

I read this article Understanding Steering Behaviors: Wander


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;
    }
}

Solutions/Answers:

Answer 1:

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;
    }
}

References