2

I am very new to unity and am building a VR app for Oculus Go. I want to pick and move the object by pointing the ray from the controller on the object and then picking or releasing it by pressing the trigger button. I want the object to stay fixed at the end of the ray's position rather than coming suddenly onto the controller. I have used this script to create a ray and basically allow the controller to pick it up but this script shits the object to the controller's position and as a result I can only move object in a circle(in 360 degrees). It also does not drop the object correctly, as the objects continue to float.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerPointer : MonoBehaviour {

//Returns whatever object is infrount of the controller
private GameObject pointerOver;
[SerializeField]
//Is the object that is currently intractable
private PropBase selectedObject;
//Is the object currently stored in hand, ready to throw.
[SerializeField]
private PickUp inHand;

//This is a refrance to the object we want the pointer to be cast from.
[SerializeField]
public Transform controllerRef;
//This is where we want object we are holding to appear
[SerializeField]
private Transform holdingRef;
//The amount of force we want to throw objects from our hand with.
[SerializeField]
[Range(2,12)]
private float throwForce = 10;

//The script that handles the visuals to show what object is selected
[SerializeField]
private HighlightObject selectVisual;
private LineRenderer line;

void Start () {
    line = GetComponent<LineRenderer> ();
}

void Update () {
    //If a object is currently being held I don't want to select another 
object until it is thrown.
    if (inHand == null) {
        WorldPointer ();
    } else {
        line.SetPosition (0, controllerRef.position);
        line.SetPosition (1, controllerRef.position);
        pointerOver = null;
    }
    //This function handles how you intract with selected objects
    Intract ();
}

//This function handles shooting a raycast into the world from the 
controller to see what can be intracted with.
void WorldPointer(){
    //We set the line visual to start from the controller.
    line.SetPosition (0, controllerRef.position);

    RaycastHit hit;
    //We reset the pointer so things don't stay selected when we are 
pointing at nothing.
    pointerOver = null;

    //This sends a line from the controller directly ahead of it, it returns 
true if it hits something. Using the RaycastHit we can then get information 
back.
    if (Physics.Raycast (controllerRef.position, controllerRef.forward, out 
hit)) {
        //Beacuse raycast is true only when it hits anything, we don't need 
to check if hit is null
        //We set pointerOver to whatever object the raycast hit.
        pointerOver = hit.collider.gameObject;
        //We set the line visual to stop and the point the raycast hit the 
object.
        line.SetPosition (1, hit.point);

        //Here we check if the object we hit has the PropBase component, or 
a child class of its.
        if (pointerOver.GetComponent<PropBase> ()) {
            //We set the object to be highlighted
            selectVisual.NewObject (pointerOver);
        } else {
            selectVisual.ClearObject ();
        }
    } else {
        //If the raycast hits nothing we set the line visual to stop a
little bit infrount of the controller.
        line.SetPosition (1, controllerRef.position + controllerRef.forward 
* 10);
        selectVisual.ClearObject ();
    }

    Debug.DrawRay(controllerRef.position , controllerRef.forward * 
10,Color.grey);
}

void Intract(){
    //We set up the input "OculusTouchpad" in the Input manager
    if (Input.GetButtonDown ("Jump") || OVRInput.GetDown 
(OVRInput.Button.PrimaryTouchpad)) {
        selectVisual.ClearObject ();                
        //Check if you are holding something you can throw first
        if (inHand != null) {
            inHand.Release (controllerRef.forward, throwForce);
            inHand = null;
            //We do this check here to prevent Errors if you have nothing 
selected
        } else if (selectedObject != null) {
            //Check if you can pick up the selected object second
            if (selectedObject.GetComponent<PickUp> ()) {
                //Beacuse PickUp is a child of PropBase, we can ask InHand 
to store selectedObject as PickUp, rather than use GetComponent
                inHand = selectedObject as PickUp;
                inHand.Store (holdingRef);
                //If non of the above were valid then simple call the 
trigger function of the selected object
            } else {
                selectedObject.Trigger ();
            }
        }
        //If you have a object that you need to hold down a button to 
intract with
    } else if (Input.GetButton ("Jump") && selectedObject != null || 
OVRInput.Get (OVRInput.Button.PrimaryTouchpad) && selectedObject != null) {
        selectedObject.Pulse ();
        //When you are not pressing down the touchpad button, the selected 
object can be updated
    } else if (pointerOver != null) {
        if (pointerOver.GetComponent<PropBase> ()) {
            selectedObject = pointerOver.GetComponent<PropBase> ();
        } else {
            selectedObject = null;
        }
    } else {
        selectedObject = null;
    }

   }

}

And i have attached this script to the objects I want to pick:

public class PickUp : PropBase
{

private Rigidbody rb;

void Start()
{
    rb = GetComponent<Rigidbody>();
}

public virtual void Store(Transform NewParent)
{
    //The following stops the object being effected by physics while it's in 
the players hand
    rb.isKinematic = true;
    //And fixes it to the new parent it is given by the player script to 
follow.
    transform.parent = NewParent;
    //It then resets it's position and rotation to match it's new parent 
object
    transform.localRotation = Quaternion.identity;
    transform.localPosition = Vector3.zero;
}
public virtual void Release(Vector3 ThrowDir, float ThrowForce)
{
    //On Release the object is made to be effected by physics again.
    rb.isKinematic = false;
    //Free itself from following it's parent object
    transform.parent = null;
    //And applies a burst of force for one frame to propel itself away from 
the player.
    rb.AddForce(ThrowDir * ThrowForce, ForceMode.Impulse);
    }
}

What i'd like to see is have the position of the sphere change according to wherever the end of the ray is cast.

I have also attached this script to the player contoller, which allows it to move to a point by pointing to it and pressing the touchpad button.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ClickToMove : MonoBehaviour
{

private Vector3 targetPos; //This Vector3 will store the position where we 
click to move.

private bool Moving = false; /*This bool keeps track of whether we are in 
the process of moving or not.*/

private GameObject targetInstance;

/*The variables we want to customize. Added info headers to these for the 
Unity Editor.*/

[Header("Our Go controller object")]

public GameObject goController;

[Header("Movement Speed")]

public float speed = 1;

[Header("Stop When This Far Away From Target")]

public float haltDistance = 0;

[Header("Optional Target Object")]

public GameObject targetObj;

void Update()

{

    MoveToTarget(); /*Here we simply run our MoveToTarget method in the 
Update method.*/

    //That way we don't clutter up the Update method with too much code.

}

void MoveToTarget() //Here we do the cluttering instead.

{

    var ray = new Ray(goController.transform.position, 
goController.transform.forward); /*Create a ray going from the goController 
position and in the Forward direction of the goController.*/

    RaycastHit hitInfo; //Store info about what the ray hits.

    Physics.Raycast(ray, out hitInfo, 100);

    if (OVRInput.GetUp(OVRInput.Button.PrimaryTouchpad)) /*If we release the 
trigger..*/

    {

        targetPos = hitInfo.point; /*Make our targetPos assume the 
positional value of the hit point.*/

        if (targetObj) /*If we have specified a Target Object to mark where 
we click*/

        //If we didn't, then we don't want to try to instantiate it.

        {

            if (targetInstance) /*If there is already a Target Object in the 
scene.*/

            {

                Destroy(targetInstance); //Destroy it.

            }

            targetInstance = Instantiate(targetObj, targetPos, 
transform.rotation); //Create our Target object at the position we clicked.

        }

        Moving = true; //And finally we set Moving to True.

    }

    if (Moving == true) //Since Moving is now true

    {

        transform.position = Vector3.MoveTowards(transform.position, new 
Vector3(targetPos.x, transform.position.y, targetPos.z), speed * 
Time.deltaTime); /*Transform our x and z position to move towards the 
targetPos.*/

        /*Note that our y position is kept at default transform position 
since we only want to move along the ground plane.*/

    }

    if (Vector3.Distance(transform.position, targetPos) <= haltDistance + 1) 
 /*Check proximity to targetPos. Mainly useful to keep your player from 
  setting a target position right next to say a building and then end up 
  clipping  through half of it.*/

    {

        if (targetInstance) //If we created a Target Object..

        {

            Destroy(targetInstance); //Then we want to destroy it when we 
reach it.

        }

        Moving = false; //Since we have now arrived at our target 
//destination.

    }

}

}

If anyone could point me in a right direction or help me with this, I would greatly appreciate it!

Thanks in advance.

Ali
  • 53
  • 7
  • What have you tried so far, I did stuff with vr raycasts jus yesterday but not sure how I can help (I had no picking) – zambari Oct 29 '18 at 10:09
  • Hey, I have edited my post and added some scripts I have used for the purpose. – Ali Oct 29 '18 at 11:10

1 Answers1

2

Okay, with your updated question its now possible to try and answer.

First off - have you tried not resetting your BaseProp localPosition to the controller's? Try commenting the line that says

transform.localPosition = Vector3.zero;

This wil still orient the object and parent it to the controller but will lock it in a position relative to the moment of parenting.

You currently use "holdingRef" object as a place where the object appears. You may want to use "controllerRef" instead.

To vary distance at which the object appears you can set the object position to:

controllerRef.position+ distance*controllerRef.forward

As this is the direction in which you fire your raycasts. You can get the hit distance by querying hit.distance.

If for any reason that doesn't work out for you, the very point of the raycast hitting the collider is available within HitInfo, so with hit.point you can extract the hit position and position the object relative to that point. Another very useful attribute of hitinfo is .normal, which enables you to get direction at which the hit happened. You can pass that info along with your Store method.

zambari
  • 4,797
  • 1
  • 12
  • 22
  • Hey, it still does not allow forward or backward movement of the object. Do you know how can i do that? – Ali Oct 29 '18 at 14:53
  • do yo mean to keep the same distance from the object that you parent to? it should already do that. In case you want to keep it 'on the surface', use hit.point clue from my answer – zambari Oct 29 '18 at 15:07
  • What I want is that when I first press the trigger, it should stay at that point, however after that i should be able to move it anywhere I want by moving the controller. Like also increase or decrease the distance from the parent afterwards, tho keeping it same initially. – Ali Oct 29 '18 at 15:12
  • I have edited my answer to add some more tips that may help you – zambari Oct 29 '18 at 15:29
  • Hey, One more thing. I have this move script which I have on my PlayerController as well that allows me to move to a point on floor by pointing to it and clicking the trigger button. However when my Player is moving, the ray is then not pointing from the controller anymore but from the center of the screen or somewhere. I have attached the script above on my post. Will be grateful if you could have a look and help me out. – Ali Oct 30 '18 at 14:03
  • would you mind accepting the answer if you find it helpful? – zambari Oct 30 '18 at 14:33
  • Hey, sorry just did. Also can you please help me with the other problem mentioned above. – Ali Oct 30 '18 at 14:45
  • thank you . I cannot see anything straight off wron with your move script. One thing to suggest (which got me a few times) is that raycasts can be hitting the player collider (in case your have any). I found LayerMasks quite useful, so your object raycast, and your floor raycast can happen sort of independently. While at it, i would suggest only performing the move raycast if the button is pressed, currently you are doing it always, and then check for button presses. How exactly does your last script fail? – zambari Oct 30 '18 at 14:56
  • Hey, I didn't get it exactly. It fails as if that when my player controller is moving, the ray is not being casted from the controller but from somewhere behind it. As soon as the the player controller reaches the desired destination and stops moving, the ray gets adjusted and is again pointing out of the controller. I have kind of tried everything but it stays the same. – Ali Oct 30 '18 at 15:00
  • I think this might be because you are racyasting against the object you are holding. Maybe you can switch off its collider temporarily? Alternatnatively use different layermasks depending on weather you hold the object or not – zambari Oct 31 '18 at 12:38
  • Yeah, it helped thanks man. One last thing, now I wanna limit the movement of the object. After parenting the object to the controller, i want it to move in just one direction, e.g. along the x-axis only. I tried doing it by freezing the object's position in its rigid body component, however, it as no effect, when the controller is attached to the object. I will be grateful if you could help me out. – Ali Nov 07 '18 at 11:40
  • remove rigidbody from the object when you want to move it by hand – zambari Nov 09 '18 at 16:31
  • I don't want to remove the rigidbody. I just want to make sure that when in hand, some objects can only be moved in one direction, e.,g. just along the x axis. – Ali Nov 12 '18 at 08:48