C# DragRigidbody ArgumentException: get_main can only be called from the main thread

I’m trying to convert DragRigidbody into C# and I’ve encountered a problem. when I clicked my left mouse button I get the following error ArgumentException: get_main can only be called from the main thread. Following that Unity freezes and crashes. So I couldn’t read what was causing the error from the console. Any idea what is wrong with the script?

using UnityEngine;
using System.Collections;

public class DragRigidbody : MonoBehaviour {

	public float spring = 50.0f;
	public float damper = 5.0f;
	public float drag = 10.0f;
	public float angularDrag = 5.0f;
	public float distance = 0.2f;
	public bool attachToCenterOfMass = false;
	public Camera mainCamera = Camera.main;
	public RaycastHit hit;
	private SpringJoint springJoint;
	
	void Update ()
	{
		// Make sure the user pressed the mouse down
		if (!Input.GetMouseButtonDown (0))
			return;
		
		// We need to actually hit an object
		if (!Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition), out hit, 100))
			return;
		// We need to hit a rigidbody that is not kinematic
		if (!hit.rigidbody || hit.rigidbody.isKinematic)
			return;
		
		if (!springJoint)
		{
			GameObject go = new GameObject("Rigidbody dragger");
			Rigidbody body = go.AddComponent ("Rigidbody") as Rigidbody;
			springJoint = go.AddComponent("SpringJoint") as SpringJoint;
			body.isKinematic = true;
		}
		
		springJoint.transform.position = hit.point;
		if (attachToCenterOfMass)
		{
			Vector3 anchor = transform.TransformDirection(hit.rigidbody.centerOfMass) + hit.rigidbody.transform.position;
			anchor = springJoint.transform.InverseTransformPoint(anchor);
			springJoint.anchor = anchor;
		}
		else
		{
			springJoint.anchor = Vector3.zero;
		}
		
		springJoint.spring = spring;
		springJoint.damper = damper;
		springJoint.maxDistance = distance;
		springJoint.connectedBody = hit.rigidbody;
		
		StartCoroutine ("DragObject", hit.distance);
	}

	void DragObject (float distance)
	{
		float oldDrag = springJoint.connectedBody.drag;
		float oldAngularDrag = springJoint.connectedBody.angularDrag;
		springJoint.connectedBody.drag = drag;
		springJoint.connectedBody.angularDrag = angularDrag;
		Camera mainCamera = Camera.main;
		while (Input.GetMouseButton (0))
		{
			Ray ray = mainCamera.ScreenPointToRay (Input.mousePosition);
			springJoint.transform.position = ray.GetPoint(distance);
		}
		if (springJoint.connectedBody)
		{
			springJoint.connectedBody.drag = oldDrag;
			springJoint.connectedBody.angularDrag = oldAngularDrag;
			springJoint.connectedBody = null;
		}
	}
}

Problem #1, you need to move the initialization of this variable to Start(). So you will declare the variable:

 public Camera mainCamera;

Then you will add:

void Start() 
{
    mainCamera = Camera.main;
}

Problem #2 is that you’ve removed the ‘yield’ from line 68. That’s what is causing your script to hang Unity. So just below line 67, insert:

yield return null;

Now that you are using ‘yield’, ‘DragObject’ needs to be and IEnumerator. So line 57 becomes:

IEnumerator DragObject (float distance)

And I would change the StartCoroutine() call on line 54 to:

StartCoroutine (DragObject(hit.distance));

Make these changes, and your code will work.

excellent. been looking for this. the old js script sucks. Final working code below:

using UnityEngine;
using System.Collections;

public class dragRigidbody : MonoBehaviour {

	public float spring = 50.0f;
	public float damper = 5.0f;
	public float drag = 10.0f;
	public float angularDrag = 5.0f;
	public float distance = 0.2f;
	public bool attachToCenterOfMass = false;
	public Camera mainCamera;
	public RaycastHit hit;

	private SpringJoint springJoint;

	void Start()
	{
		mainCamera = Camera.main;
	}

	void Update ()
	{
		// Make sure the user pressed the mouse down
		if (!Input.GetMouseButtonDown (0))
			return;

		// We need to actually hit an object
		if (!Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition), out hit, 100))
			return;
		// We need to hit a rigidbody that is not kinematic
		if (!hit.rigidbody || hit.rigidbody.isKinematic)
			return;

		if (!springJoint)
		{
			GameObject go = new GameObject("Rigidbody dragger");
			Rigidbody body = go.AddComponent <Rigidbody>() as Rigidbody;
			springJoint = go.AddComponent<SpringJoint>() as SpringJoint;
			body.isKinematic = true;
		}

		springJoint.transform.position = hit.point;
		if (attachToCenterOfMass)
		{
			Vector3 anchor = transform.TransformDirection(hit.rigidbody.centerOfMass) + hit.rigidbody.transform.position;
			anchor = springJoint.transform.InverseTransformPoint(anchor);
			springJoint.anchor = anchor;
		}
		else
		{
			springJoint.anchor = Vector3.zero;
		}

		springJoint.spring = spring;
		springJoint.damper = damper;
		springJoint.maxDistance = distance;
		springJoint.connectedBody = hit.rigidbody;

		StartCoroutine(DragObject(hit.distance));
	}

	IEnumerator DragObject (float distance)
	{
		float oldDrag = springJoint.connectedBody.drag;
		float oldAngularDrag = springJoint.connectedBody.angularDrag;
		springJoint.connectedBody.drag = drag;
		springJoint.connectedBody.angularDrag = angularDrag;
		Camera mainCamera = Camera.main;
		while (Input.GetMouseButton (0))
		{
			Ray ray = mainCamera.ScreenPointToRay (Input.mousePosition);
			springJoint.transform.position = ray.GetPoint(distance);
			yield return null;
		}
		if (springJoint.connectedBody)
		{
			springJoint.connectedBody.drag = oldDrag;
			springJoint.connectedBody.angularDrag = oldAngularDrag;
			springJoint.connectedBody = null;
		}
	}
}