Diablo style click to move


I had just purchased A* Pro. I am having alot of difficulty in setting up my new project to behave with a click to move in a diablo-style rpg.

For my player, I have these scripts attached to a capsule: Seeker, RVOController, Simple Smooth Modifier, AIPath.

I had made a slight adjustment to the AIPath script where if I click anywhere on my terrain, it sets the a transform (marker) to that point, and then I’m setting my target as that transform (marker).

a) My problem is: every 0.5 seconds it recalculates the path to my destination, the problem is that many of the times the start point of the path isnt even on the players position, sometimes it’s slightly to the left or to the right. Any idea why this is happening? (similar to a previous post by “BrianCrandell” who also has a zigzagging issue)

I also have 3 capsules (which are enemies) that find the path towards my player. the scripts I have attached to them are: Seeker, RVOController, AIPath, Simple Smooth Modifier.

b) The capsules move fine except that sometimes they are sliding sideways towards the player while looking (what seems to be) the next waypoint it’s trying to reach. Why is this happening?

c) Another issue I have is sometimes when they reach a player, one of the capsules will be behind the other 2, not able to reach the player because the other 2 are blocking it’s path. Any ideas on this one?

d) My last question is, how do I get the player to not “push” the other capsules out of the way if they are the player’s path?

Thanks for any help I receive in advance.

** I have created a short video which shows the issues I am having: http://www.youtube.com/watch?v=6N9hxBT52-k

If you could post the script you are using, It would help debugging a lot!! …

First off I will answer question D : I had the same issue with my RTS so I ended up editing the RVO controller script… Just copy this in to your RVO controller script

`using UnityEngine;
using System.Collections;
using Pathfinding;
using Pathfinding.RVO;
using System.Collections.Generic;

/** RVO Character Controller.

  • Designed to be used as a drop-in replacement for the Unity Character Controller,

  • it supports almost all of the same functions and fields with the exception

  • that due to the nature of the RVO implementation, desired velocity is set in the Move function

  • and is assumed to stay the same until something else is requested (as opposed to reset every frame).

  • For documentation of many of the variables of this class: refer to the Pathfinding.RVO.IAgent interface.

  • ote Requires an RVOSimulator in the scene

  • \see Pathfinding.RVO.IAgent

  • \see RVOSimulator

  • \astarpro
    [AddComponentMenu(“Local Avoidance/RVO Controller”)]
    public class RVOController : MonoBehaviour {

    public float radius = 5;
    public float maxSpeed = 2;
    public float height = 1;
    public bool locked = false;

    public float agentTimeHorizon = 2;
    public float obstacleTimeHorizon = 2;
    public float neighbourDist = 10;

    public bool debug = false;

    public LayerMask mask = -1;

    public float wallAvoidForce = 1;
    public float falloff = 1;

    public Vector3 center;

    private IAgent rvoAgent;

    private Simulator simulator;

    private float adjustedY = 0;

    private Transform tr;

    Vector3 desiredVelocity;

    public bool RaycastDown;

    public bool ToggleLockWhenMoving;

    /** Position for the previous frame */
    private Vector3 lastPosition;

    public Vector3 position {
    get { return rvoAgent.InterpolatedPosition; }

    public Vector3 velocity {
    get { return rvoAgent.Velocity; }

    public void OnDisable () {
    //Remove the agent from the simulation but keep the reference
    //this component might get enabled and then we can simply
    //add it to the simulation again
    simulator.RemoveAgent (rvoAgent);

    public void Awake () {
    tr = transform;

     RVOSimulator sim = FindObjectOfType(typeof(RVOSimulator)) as RVOSimulator;
     if (sim == null) {
     	Debug.LogError ("No RVOSimulator component found in the scene. Please add one.");
     simulator = sim.GetSimulator ();


    public void OnEnable () {
    //We might have an rvoAgent
    //which was disabled previously
    //if so, we can simply add it to the simulation again
    if (rvoAgent != null) {
    simulator.AddAgent (rvoAgent);
    } else {
    rvoAgent = simulator.AddAgent (transform.position);

     UpdateAgentProperties ();
     rvoAgent.Position = transform.position;
     adjustedY = rvoAgent.Position.y;


    protected void UpdateAgentProperties () {
    rvoAgent.Radius = radius;
    rvoAgent.MaxSpeed = maxSpeed;
    rvoAgent.Height = height;
    rvoAgent.AgentTimeHorizon = agentTimeHorizon;
    rvoAgent.ObstacleTimeHorizon = obstacleTimeHorizon;
    rvoAgent.Locked = locked;
    rvoAgent.DebugDraw = debug;

    public void Move (Vector3 vel) {
    desiredVelocity = vel;
    if(ToggleLockWhenMoving == true && desiredVelocity == Vector3.zero){
    locked = true;
    if(ToggleLockWhenMoving == true && desiredVelocity != Vector3.zero){
    locked = false;

    public void Teleport (Vector3 pos) {
    tr.position = pos;
    lastPosition = pos;
    //rvoAgent.Position = pos;
    rvoAgent.Teleport (pos);
    adjustedY = pos.y;

    public void Update () {
    if (lastPosition != tr.position) {
    Teleport (tr.position);

     UpdateAgentProperties ();
     RaycastHit hit;
     //The non-interpolated position
     if(RaycastDown == true){
     	Vector3 realPos = rvoAgent.InterpolatedPosition;
     	realPos.y = adjustedY;
     	if (Physics.Raycast	(realPos + Vector3.up*height*0.5f,Vector3.down, out hit, float.PositiveInfinity, mask)) {
     		adjustedY = hit.point.y;
     	} else {
     		adjustedY = 0;
     	realPos.y = adjustedY;
     	rvoAgent.Position = new Vector3(rvoAgent.Position.x, adjustedY , rvoAgent.Position.z);
     List<ObstacleVertex> obst = rvoAgent.NeighbourObstacles;
     Vector3 force = Vector3.zero;
     for (int i=0;i<obst.Count;i++) {
     	Vector3 a = obst[i].position;
     	Vector3 b = obst[i].next.position;
     	Vector3 closest = position - Mathfx.NearestPointStrict (a,b,position);
     	if (closest == a || closest == b) continue;
     	float dist = closest.sqrMagnitude;
     	closest /= dist*falloff;
     	force += closest;

Debug.DrawRay (position, desiredVelocity + forcewallAvoidForce);
rvoAgent.DesiredVelocity = desiredVelocity + force
if(RaycastDown == true){
tr.position = rvoAgent.InterpolatedPosition + Vector3.upheight0.5f + center;
tr.position = rvoAgent.InterpolatedPosition + center;
lastPosition = tr.position;

^^ The ToggleLockWhenMoving option in the inspector should do what you want~

If you can post your main script~ I will try and answer the rest!!

Hey thanks for your attempt. It does seem to work better, but for some reason “local avoidance” stops working for my player when I use your modified script. I’m sort of regretting purchasing this A* :S. Do you have a gmail account? I would find it easier to debug via some sort of messenger if you would like.

Don’t worry quite yet Miroslaw!! You just need to find the right way to use it!! My email is Dmaydrum@gmail.com… I can give you a hand trying to figure this out!!

Issue A probably has something to do with the GetNearestNode being called for the start position VS having it be your exact location~

Issue B is probably an issue with your script~ the STOP-PATH or NEXT-NODE functions have to follow order of operation or you will get stuff like this… Or it might be as simple as not passing 0.0.0 when you want to stop ??

Issue C is just… Id have to think this through~ The quick and easy way that comes to mind is if a Spider has reached its target (in range of attacking) it becomes a No walk zone See RVO collides for that info~

Issue D I solved my self… I just might need to change something in the script to make is more re useable~