What you want to do is have either the Camera or some other reference point for instance the barrel of a gun, to have the raycast begin.
With this simple GrabScript I can set the âoriginâ to a fixed transform (if this is meant to be moved with parent I suggest parenting it). There is a property called âOriginâ that will check if âoriginâ is assigned, if its NULL it will return the Cameraâs transform and we will Recast from that.
âraycastDistanceâ is the maxDistance the raycast will go.
âObjectGrabbedEventâ a UnityEvent event that will get fired when this event is invoked.
âObjectDroppedEventâ a UnityEvent event that will get fired when this event is invoked.
âgrabObjectâ the KeyCode to be used for Input (I used Mouse0 which is the left click).
âgrabableObjectLayerâ a filter to be used when raycasting, this is great so you donât get a Transform you donât want.
âm_objectGrabbedâ cached reference to the object grabbed.
GrabScript.cs
using UnityEngine;
using System.Collections;
public class GrabScript : MonoBehaviour {
[SerializeField] Transform origin; // Use this if you want to specify where you want the raycast to start firing. If not it will default to the Camera.
[SerializeField] float raycastDistance; // The distance the ray cast will go from the origin/camera point.
[SerializeField] ObjectGrabbedEvent onObjectGrabbed; // Events you can use to register when an object is grabbed.
[SerializeField] ObjectDroppedEvent onObjectDropped; // Events you can use to register when an object is dropped.
[SerializeField] KeyCode grabObject; // Hard coded keycode for grabbing an object.
[SerializeField] LayerMask grabableObjectLayer;
GameObject m_objectGrabbed;
void Update() {
if(Input.GetKeyDown(this.grabObject)) {
RaycastHit hit;
if(Physics.Raycast(this.Origin.position, this.Origin.forward, out hit, this.raycastDistance, this.grabableObjectLayer)) {
this.m_objectGrabbed = hit.collider.gameObject;
this.onObjectGrabbed.Invoke(this.m_objectGrabbed);
}
}
if(Input.GetKeyUp(this.grabObject)) {
if(this.m_objectGrabbed != null) {
this.onObjectDropped.Invoke(this.m_objectGrabbed);
this.m_objectGrabbed = null;
}
}
}
protected Transform Origin {
get {
if(this.origin == null) {
return Camera.main.transform;
} else {
return this.origin;
}
}
}
public ObjectGrabbedEvent ObjectGrabbedEvent {
get {
return this.onObjectGrabbed;
} set {
this.onObjectGrabbed = value;
}
}
public ObjectDroppedEvent ObjectDroppedEvent {
get {
return this.onObjectDropped;
} set {
this.onObjectDropped = value;
}
}
}
Custom events to be used with UnityEngine.Events namespace. By serializing them, they will show up in the inspector very convenient.
UnityEvents.cs
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
[System.Serializable]
public class ObjectGrabbedEvent : UnityEvent<GameObject> { }
[System.Serializable]
public class ObjectDroppedEvent : UnityEvent<GameObject> { }
âfinalPositionâ the final transform for the object to move to.
âspeedâ how fast it moves to and from
ârotationSpeedâ how fast it rotates to and from.
âoriginalPositionâ cached position from where the object was grabbed.
âoriginalRotationâ cached Quaternion from where the object was grabbed.
âm_objectGrabbedâ cached reference to the gameObject grabbed.
GrabListener.cs
using UnityEngine;
using System.Collections;
public class GrabListener : MonoBehaviour {
[SerializeField] Transform finalPosition;
[SerializeField] float speed = 2.0f;
[SerializeField] float rotationSpeed = 10.0f;
Vector3 originalPosition;
Quaternion originalRotation;
GameObject m_objectGrabbed;
public void ObjectGrabbed(GameObject objectGrabbed) {
this.m_objectGrabbed = objectGrabbed;
this.originalPosition = this.m_objectGrabbed.transform.position;
this.originalRotation = this.m_objectGrabbed.transform.rotation;
this.StopCoroutine("ReturnObjectBackPosition");
this.StopCoroutine("ReturnObjectBackRotation");
this.StartCoroutine("BringObjectForwardPosition");
this.StartCoroutine("BringObjectForwardRotation");
}
public void ObjectDropped(GameObject objectDropped) {
this.StopCoroutine("BringObjectForwardPosition");
this.StopCoroutine("BringObjectForwardRotation");
this.StartCoroutine("ReturnObjectBackPosition");
this.StartCoroutine("ReturnObjectBackRotation");
}
IEnumerator BringObjectForwardPosition() {
while(this.m_objectGrabbed.transform.position != this.finalPosition.position) {
this.m_objectGrabbed.transform.position = Vector3.MoveTowards(this.m_objectGrabbed.transform.position, this.finalPosition.position, this.speed * Time.deltaTime);
yield return null;
}
}
IEnumerator BringObjectForwardRotation() {
while(this.m_objectGrabbed.transform.rotation != this.finalPosition.rotation) {
this.m_objectGrabbed.transform.rotation = Quaternion.RotateTowards(this.m_objectGrabbed.transform.rotation, this.finalPosition.rotation, this.rotationSpeed * Time.deltaTime);
yield return null;
}
}
IEnumerator ReturnObjectBackPosition() {
while(this.m_objectGrabbed.transform.position != this.originalPosition) {
this.m_objectGrabbed.transform.position = Vector3.MoveTowards(this.m_objectGrabbed.transform.position, this.originalPosition, this.speed * Time.deltaTime);
yield return null;
}
}
IEnumerator ReturnObjectBackRotation() {
while(this.m_objectGrabbed.transform.rotation != this.originalRotation) {
this.m_objectGrabbed.transform.rotation = Quaternion.RotateTowards(this.m_objectGrabbed.transform.rotation, this.originalRotation, this.rotationSpeed * Time.deltaTime);
yield return null;
}
}
}
Hope this helps.
2197488â145862âObject Grab.unitypackage (4.38 KB)