- Home /
How to move a raycasted game object ?
Hi, I'm new to Unity and I'm learning to create some scripts at the same time. I'm developing an application using the Oculus Rift and I'm trying to do something with raycasts: In my scene, I have several gameObjects in front of my camera and I have a raycast with my camera as its origin.
What I want to do is, when the user looks at the object (so the ray hits the object), the object moves to a position but when the object is no longer raycasted (the user looks somewhere else), the object returns to its original position.
If that helps, I have this script on my camera to move to a position when I start the scene:
using UnityEngine;
using System.Collections;
public class MovementC : MonoBehaviour {
public Vector3 endPoint;
public float duration = 1.0f;
private Vector3 startPoint;
private float startTime;
// Use this for initialization
void Start () {
startPoint = transform.position;
startTime = Time.time;
}
// Update is called once per frame
void Update () {
transform.position = Vector3.Lerp(startPoint, endPoint, (Time.time - startTime)/duration);
}
}
Any ideas ?
Thanks in advance,
Havauk
Hey, thank you for your response !
I implemented your code to my camera, and altough it's not exactly what I'm looking for, it's nearly there !
The thing is with your code I only have one new position and I need one for each of my game objects. So when I look at a gameObject, it is instantly teleported to (0,0,0) (I can change the coordinates if newPos is public) but when I look at another gameObject, the previous object goes back to its original position (good) but the one I looked at goes to (0,0,0)
Not sure if I explained well my problem the 1st time, so I made a schema of my scene in top view:
What I want is, for example: When the user looks at the Obj1 (at original position), it moves towards the user to its new position. But when the user looks to Obj2, it moves to its new position and Obj1 goes back to its original position, and etc...
To avoid the object appearing instantly to a position, I think I can use Vector3.Lerp to have a smooth translation.
Thank you again !
if this is a response to my answer you should comment at the answer or it's confusing. Well, since there is only 1 answer here ($$anonymous$$e) it's clear but it wouldn't be if there where more.
Oh, I think I see the problem, yeah made a bit of a mistake in my script (I wasn't really thinking much when I typed it out, just tried to go for the generic idea...)
Anyway, if you go by my script, when the ray hits something, it is then immediately moved to newPos.
in order to change this, it should be smt like (small snip)
//looking at something
if(Physics.Raycast(ray, out hit)){
//not currently looking at a thing
if(lookAt == null){
//store new thing we look at
lookAt = hit.transform.root.gameObject;
prevPos = lookAt.transform.position)
}
if(lookAt != null){
//already looking at a thing!
//is it the same thing we looked at last frame?
if(lookAt == hit.transform.root.gameObject){
//if yes, update its position
lookAt.transform.position += (transform.position - lookAt.transform.position).normalized * Time.deltaTime * speed;
}else {
//this is a different thing than last frame! reset old one & store new
lookAt.transform.position = prevPos;
lookAt = hit.transform.root.gameObject;
prevPos = hit.transform.root.position;
}
}
}
I just typed this out loosely again, but I think it is what you want? The old object still snaps back though.
You /could/ prevent that, but you'd need to keep lists of all objects that haven't moved back to their original position and the original positions.
(it may actually be easier to put a script on all look-at-able gameObjects that moves them when they are/are not being looked at... something to consider maybe).
Yeah that's weird, I was sure I was responding to your comment, oh well..
Not on my computer right now (at least not the one with the project on it) but I'll definitly check it out, thanks !
Hey, so I thought about when you said it may actually be easier to put a script on all look-at-able gameObjects and I found this:
hit.transform.Send$$anonymous$$essage("HitByRay");
So my ray script sends a message to the object hit by the ray, and with this script in my object:
void HitByRay () { Debug.Log ("I was hit by a ray"); transform.position = newPos; }
I can move my object to a position when hit by the ray, but I did not manage to make it move back to the original position when not raycasted, any ideas ?
Yeah, wee bit complex maybe, but, would do something like
public class LookAbleObject : $$anonymous$$onoBehaviour {
bool beingLookedAt;
//call this function when hit by a look-at-ray
public void HitByLookRay(){
beingLookedAt = true;
}
void LateUpdate(){
if(beingLookedAt){
//move to newPos code
}else{
move back to original place code
}
beingLookedAt = false;
}
}
that's very $$anonymous$$imal and I've not written anything to store the original position which of course you should do.
I'll just explain the idea here:
you call your raycast function in Update(). If your raycast hits the object, it switches the 'beingLookedAt' boolean to true (which is ALWAYS false at this point, get to that later)
Then, in LateUpdate(), we do the movement of the object. You do this in LateUpdate to make sure that the beingLookedAt boolean is set to true if it should be, then after your movement is done in LateUpdate, you set beingLookedAt back to false to ensure that it is always false when an update loop starts.
The key here is that you need to make sure that the movement code is executed after the code that deter$$anonymous$$es if your object is being looked at in this frame. I've done it with Update() and LateUpdate() here, but you could also do it with setting the Script Execution Order in the project settings.
Answer by siaran · May 19, 2015 at 01:07 PM
not going to work it out completely but what about
//object currently being looked at
GameObject lookAt;
//previous position of looked-at object
Vector3 prevPos;
//point where we move an object we look at
Vector3 newPos;
void Update {
RaycastHit hit;
//too lazy to define the look ray here
if(Physics.Raycast(ray, out hit)){
//if not currently looking at something
if(lookAt == null){
//look at the hit object
lookAt = hit.transform.root.gameObject;
//store its position
prevPos = lookAt.transform.position;
//move it to the new position
lookAt.transform.position = newPos;
}
//if not looking at something and we still have a lookat object stored
}else if(lookAt != null){
///put it back
lookAt.transform.position = prevPos;
//set curretn lookAt to null
lookAt = null;
}
}
One major problem with this script occurs when you look at another object without looking at 'nothing' in between, but that is easy to fix, just put some condition in the raycast-if like if(hit.transform.root.gameObject != lookAt)
, you basically do the same to the current ('old') one as when you no longer look at something and then set the one you are looking at now as the current one.
Your answer
