# 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. 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;

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

var wanderForce = circleCenter + displacement;
return wanderForce;
}
}

• add sample of code in the question. Links may go down – dnk drone.vs.drones Sep 3 '15 at 11:32
• I see some neat gimbal locking – ratchet freak Sep 3 '15 at 11:44
• 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? – Felsir Sep 3 '15 at 12:16
• @Felsir "do you pick a random direction every frame?" - yes, like in article. – Rusildo Sep 3 '15 at 12:41
• @Rusildo picking a random direction in 3D means sampling the surface of the unit sphere. – ratchet freak Sep 3 '15 at 13:48

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

public class UnitWander : MonoBehaviour
{
public float TurnChance = 0.05f;

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()
{
{
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;
}
}