I want a grabbing system that will put the object in front of the camera, and keep it there until the user presses the grab button again. I have the raycast set up and everything, the only thing i need is an equation that puts it in front of the camera. i have tried many things, but nothing seems to work. can anayone help please?
Untested: Vector3 worldPositionAhead = Camera.main.transform.forward * distanceFromCamera; Edit: plus camera position.. Vector3 worldPositionAhead = Camera.main.transform.position + (Camera.main.transform.forward * distanceFromCamera);
i tried it, but i don't know how to implement it into my current grab code. here is that code: Code (CSharp): using UnityEngine; public class SelectionManager : MonoBehaviour { [SerializeField] private string selectableTag = "Selectable"; [SerializeField] private Material highlightMaterial; [SerializeField] private Material defaultMaterial; private Transform _selection; public Transform camera; private void Update() { if (_selection != null) { var selectionRenderer = _selection.GetComponent<Renderer>(); selectionRenderer.material = defaultMaterial; _selection = null; } var ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { var selection = hit.transform; if (selection.CompareTag(selectableTag)) { var selectionRenderer = selection.GetComponent<Renderer>(); if (selectionRenderer != null) { selectionRenderer.material = highlightMaterial; } _selection = selection; if (Input.GetKeyDown(KeyCode.E)) { UnityEngine.Debug.Log("Block Grabbed"); //equation here } } } } }
you're setting selection to null on the frame after it's set. you'll want to keep a reference around, or maybe add a public Transform grabbed; then where you have "equation here" you would put grabbed = selection; and somewhere else in Update (maybe at the bottom) add something like.. Code (CSharp): if (grabbed != null) grabbed.position = Camera.main.transform.position + (Camera.main.transform.forward * 10.0f);
and actually, after a bit of experimenting, i got it to teleport to the right spot, except the only problem is that it only teleports once and then stops. any fix? current code: Code (CSharp): using UnityEngine; public class SelectionManager : MonoBehaviour { [SerializeField] private string selectableTag = "Selectable"; [SerializeField] private Material highlightMaterial; [SerializeField] private Material defaultMaterial; private Transform _selection; public Transform camera; public bool grabbing; private void Update() { if (_selection != null) { var selectionRenderer = _selection.GetComponent<Renderer>(); selectionRenderer.material = defaultMaterial; _selection = null; } var ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { var selection = hit.transform; if (selection.CompareTag(selectableTag)) { var selectionRenderer = selection.GetComponent<Renderer>(); if (selectionRenderer != null) { selectionRenderer.material = highlightMaterial; } _selection = selection; if (Input.GetKeyDown(KeyCode.E)) { UnityEngine.Debug.Log("Block Grabbed"); if (selection != null) selection.position = camera.position + (camera.forward * 3.0f); } } } } }
The issue is this: Code (CSharp): private void Update() { if (_selection != null) { //[...] _selection = null; The very next frame you don't have a reference anymore, because you set that to null. If you want to keep holding it in front of you, there needs to be a reference - that's why I said you should add "grabbed" and use that. Try this.. Code (CSharp): using UnityEngine; public class SelectionManager : MonoBehaviour { [SerializeField] private string selectableTag = "Selectable"; [SerializeField] private Material highlightMaterial; [SerializeField] private Material defaultMaterial; private Transform _selection; private Transform _grabbed; public Transform camera; public bool grabbing; private void Update() { if (_selection != null) { var selectionRenderer = _selection.GetComponent<Renderer>(); selectionRenderer.material = defaultMaterial; _selection = null; } if (_grabbed != null) { if (Input.GetKeyDown(KeyCode.E)) { Debug.Log("No longer grabbing"); _grabbed = null; } else { _grabbed.position = camera.position + (camera.forward * 3.0f); } return; } var ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { var selection = hit.transform; if (selection.CompareTag(selectableTag)) { var selectionRenderer = selection.GetComponent<Renderer>(); if (selectionRenderer != null) { selectionRenderer.material = highlightMaterial; } _selection = selection; if (Input.GetKeyDown(KeyCode.E)) { _grabbed = _selection; UnityEngine.Debug.Log("Block Grabbed"); } } } } }