# 3d cursor?

Discussion in 'Scripting' started by Mr. Animator, Feb 5, 2006.

1. ### Mr. Animator

Joined:
Oct 2, 2005
Posts:
193
Here's what I'd like to do, and I'm not quite sure where to begin...

I'd like to have a 3D game object (let's say a primitive to keep things simple) that follows my cursor around. However I don't want it to simply stay perpendicular to the camera, I want it to ride along the top of a ground plane... imagine manipulating an air-hockey 'goalie' along the surface of a plane by moving your mouse.

What I plan to have is a character that you direct by clicking the ground and having them walk to where you click. So it would be nice to have a 3d cursor of sorts that basically attaches itself to the ground wherever the mouse is floating over at any given time. My newbie assumption is that it would involve casting a ray out from the camera based on where the mouse is. From there it would be a simple matter of placing my cursor object at the point of impact between the raycast and the ground, but its the part leading up to that I can't get my head around.

Any thoughts would be appreciated.

2. ### antenna-tree

Joined:
Oct 30, 2005
Posts:
5,324
This is the script I use for a polygon plane "crosshair" that follows the cursor position, rotates and snaps to any mesh polygon normals that your cursor is over, and keeps the size constant in relation to the distance from the camera.

Code (csharp):
1.
2.
3. var crossHair : GameObject;
4. var aimSizer = new Vector3(0.0, 0.0, 0.0);
5. var disappear = new Vector3(0, 0, 0);
6. var hit : RaycastHit;
7. var theDistance = 0.0;
8.
9. function Update ()
10. {
11.     Screen.showCursor = false;
12.     ray = camera.ScreenPointToRay (Input.mousePosition);
13.
14.
15.     if (Physics.Raycast (ray, hit, Mathf.Infinity))
16.     {
17.         crossHair.transform.rotation = Quaternion.FromToRotation (Vector3.up, hit.normal);
18.         crossHair.transform.position = hit.point + (hit.normal * 0.03);
19.
20.         theDistance = Mathf.Sqrt (hit.distance) * 0.15;
21.         aimSizer = Vector3 (theDistance, theDistance, theDistance);
22.         crossHair.transform.localScale = aimSizer;
23.     }
24.
25.     else
26.     {
27.         crossHair.transform.position = disappear;
28.     }
29. }
30.
31.
This script is a little personalized, but should work as a starting point.

HTH

3. ### Mr. Animator

Joined:
Oct 2, 2005
Posts:
193
Thanks for sharing this bit o code, looks like just what I was looking for (although the keeping the target scaled the same is not necessary, but cool).

Got a newbie questions, in my attempt to slowly fill in the gaps in my javascript knowledge. In this line...

var layerMask = 1 << 9;

What is the resulting contents of the variable? I'm not familiar with the << operator. Is it the range between 1 and 9?

4. ### antenna-tree

Joined:
Oct 30, 2005
Posts:
5,324
var layerMask = 1 << 9;

Sorry, I took that snippet out in an edit. That's for designating a single layer of your scene that the raycast will hit. Just delete it for now, but definitely look layers up in the reference because they're indispensible.

5. ### Mr. Animator

Joined:
Oct 2, 2005
Posts:
193
Ah, that's actually exactly what I wanted to do! I plan to have a 'terrain' layer that will catch the cursor while any other colliders will safely ignore it. The << makes sense now after I managed to find this page of the scripting reference...

http://otee.dk/Documentation/ScriptingConcepts/Layers.html

Anyhow I've succesfully modified your script to fit my needs and it's now working like a charm. Thanks for the help!

6. ### marty

Joined:
Apr 27, 2005
Posts:
1,170
Heya AT,

I'm having trouble with the lines in your code that scale the cursor plane object:

theDistance = Mathf.Sqrt (hit.distance) * 0.15;
aimSizer = Vector3 (theDistance);
crossHair.transform.localScale = aimSizer;

These generate an error indicating that the Vector3 "does not have a visible contructor that matches the argument list." Is there more that I need to add or do?

7. ### antenna-tree

Joined:
Oct 30, 2005
Posts:
5,324
Sorry Marty, stupid mistake on my part trying to slim stuff down when I posted this...

aimSizer = Vector3 (theDistance);

should be...

aimSizer = Vector3 (theDistance, theDistance, theDistance);

BTW, this is clearly a hackery that will only work perfectly if your camera is a certain field of view. I put it in there so my crosshair would stay relatively the same size and not look HUGE if it pops up on a surface very close to the camera.

8. ### marty

Joined:
Apr 27, 2005
Posts:
1,170
Yeah, I spotted the typo as soon as I took a minute to actually read the code.

The scaling only seems to make a noticable difference if the cursor object changes its camera-relative position big-time, as you say, but it's a cool effect!

Here's something intersting though, if the model who's surface you are trackng is changing its transform (i.e. rotating on an axis), the code seems to go haywire. I've tried putting it in a LateUpdate, and various other things, but to no avail.

Any idea what might be causing that?

9. ### marty

Joined:
Apr 27, 2005
Posts:
1,170
BTW, Antennaguy, how do you post code in the forums and have it appear all icely formatted in those big, white boxes?

10. ### antenna-tree

Joined:
Oct 30, 2005
Posts:
5,324
Ha! Yeah, I forgot about that. I haven't used this thing with moving objects in a while but it goes absolutely nutzo. I have no clue why this happens. Maybe damping the rotation and postion a little bit with some Lerps would help?

 Use the "Code" tags at the top of the message box.

11. ### marty

Joined:
Apr 27, 2005
Posts:
1,170
It's kooky, isn't it.

I actualy wrote a different version of ths code myself many months back (uses a cross product with the normal of the tracking object) and it did the same thing. When I saw you code, I was thinking maybe it wouldn't do it. But alas ...

I'm thinking maybe it has something to do wth the physics mesh that you need to attach to do the raycasting. Maybe it gets "jumbled" durng the frame?

### Unity Technologies

Joined:
Mar 16, 2005
Posts:
5,203
Did you make sure that the crossHair object doesn't have a collider attached?
Otherwise you get feedback and you cast rays against the cross hair.

Also you might want to try making your moving objects kinematic rigidbodies instead of just colliders.

13. ### marty

Joined:
Apr 27, 2005
Posts:
1,170
The crosshair object is on its own layer, being ignored by the rays, in my version. So, I don't think that's the problem.

14. ### marty

Joined:
Apr 27, 2005
Posts:
1,170
Okay, I give up, how do I make the terrain object a kinematic rb?

I can make a RigidBody instance just fine, but it doesn't appear to have the IsKinematic parameter that I'm reading about in the Help subsystem anywhere in the Inspector.

Also, it looks like using IsKinematic (if I ever find out where to enable it) will result in losing a lot of physics that I would like to keep for the object.

Hmmm ... any ideas?

### Unity Technologies

Joined:
Mar 16, 2005
Posts:
5,203
Do you have your inspectors set to simple?
(See the screenshot for where the isKinematic checkbox is)
You really shouldn't need to add the kinematic rigidbody though.

Anyway, what kind of behaviour exactly do you see?

When i attached the script to a moving object it worked perfectly fine.
(Neat script btw.)

I just made sure that the cursor doesn't have a collider. Not sure why you would ever want a cursor to have a collider anyway.

File size:
8.4 KB
Views:
4,059
16. ### marty

Joined:
Apr 27, 2005
Posts:
1,170
Doh!

That was it. I reinstalled Unity today. The default Inspector must be Simple, so mine was Simple. I've been on Expert for so long, I forgot it has other modes.

BTW, you actually published a script just like this, only in c#, back when Unity first came out. It was in the HowTo's until a release or two ago.