Help with Click to move script

Hey All…A little new to unity been kicking through tutorials and demos off and on the last couple months.

I have a nice mmo style cam setup that lets you orbit the character on right mouse button, zoom in and out with mouse wheel, and uses WASD to move.

I also have a script set up that draws a 3d arrow pointing down towards an object or terrain normal (via raycast) on left mouse click.

The following script will turn my character object towards the arrow object on left mouse click and the line I have commented out towards the bottom will “lead” the character around if activated(on mouse down).

The leading around is cool but problematic,
A) the character ignores collision and falls through the world and 2) I need the character to walk to the location of the mouse click…like rts, Diablo, torchlight…etc…

CAn anyone help, Ive looked at the generals RTS demo but the click to move function in there is a little beyond my experience and I cant seem to pick out and implement the bits that apply to what I want to do.
Any help is GReatly appreciated…

var dir : Vector3;
var hit : RaycastHit ;
var rot = 0;
var k : Vector3;

function Update()
{

var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
Physics.Raycast (Camera.main.transform.position,ray.direction,hit,1000);

dir = hit.point - transform.position;
dir[1] = 0;

var angle = Vector3.Angle(dir, transform.forward);
var k = Vector3.Cross(transform.forward, dir);
k.Normalize();

rot = k[1]*(angle*2.5);

if (Input.GetMouseButton(0)) transform.Rotate(Vector3.up*rot*Time.deltaTime);
//if (Input.GetMouseButton(0)) transform.Translate(0, 0, .2);

}

you might want to use the character controller component and use Move instead of Translate, which will take care of collisions and such.
for moving with a character controlling you should use FixedUpdate instead of Update and multiply the vector that you want to move by Time.deltaTime to get a constant speed.
to give you an idea of what i am talking about:

yourCharacterController.Move(dir.normalized * Time.deltaTime * speed);

where speed is a variable for you to adjust the characters’ speed.
let me know if you run into any problems

Yo,
Can you tell me where is this tutorial? the general rps one?

@felipi - heres the link to the generals RTS thread:
http://forum.unity3d.com/viewtopic.php?t=18802&highlight=generals+rts

@dbp - Thanks for the response, still trying to figure it out…to be clear my character object (a simple box object for the moment) has a character controller component attached to it via the components-physics menu.

the above script is attached to that character object, I have my cam look and W,A,S,D controls attached to the main camera.

I changed the function update to a fixedupdate and tried adding the code you suggest, but Im stuck on the implementation and obviously not doing it right, I get errors saying there is no character controller.

in the above code example can you help me implement the move to click statement correctly?
thank you for your time on this…

I think your looking for an A* algorithm. It’s a pathfinding algorithm that will move your character to a specific point. If you search google for A* Pathfinding, you’ll find lots of good resources.

A few people have already experimented with this in Unity, have you checked that out yet?

You can even use the heuristic variable to really tweak the pathfinding for you specific game.

Make sure to check out all the different variants:

@Brucebannor - That system you linked seems to do it all for path finding and point and click movement… A bit more complex than I was looking for…but I’m looking through the demos and scripts now they work really well, will take a little doing to retool my project to work with this system…thank you for the help, though I was hoping there was a simple couple of lines that could make the character object move to the click in the code above…if you have any ideas about that please post.

There’s lots more algorithms for path-finding but I don’t think any quite as nice as A*. If your trying to accomplish movement in a terrain or around obstacles, I believe A* is the way to go.

Having an object move to another point in a straight line without obstacles is much easier. But if you incorporate obstacles the object will walk right into them and hang.

Well, Im more artist than coder so why reinvent the wheel if this already works…I’ll implement this system and get into making levels , UI, assets and gameplay quicker…thanks for the help…

i modified your code from the first post to do what i was talking about. i didn’t test this so there might still be an error but i hope you get the idea. this will only make the character walk in the direction you clicked though, if you want to automatically avoid obstacles and all that stuff then you’re better off using the A* system that was suggested.

var dir : Vector3;
var hit : RaycastHit ;
var rot = 0;
var k : Vector3;
var speed : float = 1.0;

private var yourCharacterController : CharacterController;

function Start() {
  yourCharacterController = GetComponent(CharacterController);
}

function FixedUpdate()
{

var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Physics.Raycast(Camera.main.transform.position,ray.direction,hit,1000);

dir = hit.point - transform.position;
dir[1] = 0;

var angle = Vector3.Angle(dir, transform.forward);
var k = Vector3.Cross(transform.forward, dir);
k.Normalize();

rot = k[1]*(angle*2.5);

if (Input.GetMouseButton(0)) transform.Rotate(Vector3.up*rot*Time.deltaTime);
yourCharacterController.Move(dir.normalized * Time.deltaTime * speed);

}

hay thanks for the replies and the code help…Ill check try this out…
Even if I use the A* pathfinding ( why is it called A*)
I still want to learn from my original code…

Hi, about the code above. I kept getting this error.

NullReferenceException: Object reference not set to an instance of an object.

And when I double click it, it led me to this code. What’s the cause of the problem. Any ideas?

var ray = Camera.main.ScreenPointToRay(Input.mousePosition);

The error report might be playing tricks with you here (it’s not likely to be this line that is causing the problem). Can you post a few lines of context either side of this line?

A few attempts were made at developing the algorithm before the familiar version was discovered. They were codenamed A1, A2, etc. Eventually it was found that a simple modification gave optimal performance and this version of the algorithm was called A*. This is a mathematical joke that means “replace the star with any number you like”. Like most mathematical jokes, it isn’t actually funny at all.

I’ve solved it. Thanks for trying to help! =D
I’ve changed Camera.main to a var which I declared.

var ray = mainCam.ScreenPointToRay(Input.mousePosition);

[/code]

Ok, first off, this script works perfectly for what I needed. However, when I started my game my character would just ‘slide’ in the direction of the mouse…weird. It was like he was on ice, when I clicked leftclick, then the walk animation actually played. So, it was working, but not really.

Well after messing around and getting frustrated and almost giving up…I tried moving things around, I tried ‘else’ calls, didn’t work, I tried ‘if’ didn’t work…

What did work:

if (Input.GetMouseButton(0)) yourCharacterController.Move(dir.normalized * Time.deltaTime * speed);
transform.Rotate(Vector3.up * rot * Time.deltaTime);

All I did was switch which line was called first and it worked!
Call the Movement BEFORE Rotation and it will perform exactly as intended :slight_smile:

I’m using Unity3D version: 3.1.0f3