- Home /
[WILLING TO EVEN PAY $] Working Dragging objects/doors like in Amnesia, But Need Simple FIX
Hey!
I have this script and it is working however what I need is simple, but can't figure it out.
I have a door which is a rigidbody and the player can open and close the door with the script. HOWEVER when the player walks backwards while still holding the mouse keythen you can still control the door even if you are 10000 miles away from the door. I want it as soon as the player is away then then you cannot control it anymore... springJoint.connectedBody = null;? It's important :(
var normalCollisionCount = 1;
var spring = 50.0;
var damper = 5.0;
var drag = 10.0;
var angularDrag = 5.0;
var distance = 0.2;
var throwForce = 500;
var throwRange = 1000;
var attachToCenterOfMass = false;
private var springJoint : SpringJoint;
function Update ()
{
// Make sure the user pressed the mouse down
if (!Input.GetMouseButtonDown (0))
return;
var mainCamera = FindCamera();
// We need to actually hit an object
var hit : RaycastHit;
if (!Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition), hit, 100))
return;
// We need to hit a rigidbody that is not kinematic
if (!hit.rigidbody || hit.rigidbody.isKinematic)
return;
if (!springJoint)
{
var go = new GameObject("Rigidbody dragger");
var body : Rigidbody = go.AddComponent ("Rigidbody") as Rigidbody;
springJoint = go.AddComponent ("SpringJoint");
body.isKinematic = true;
}
springJoint.transform.position = hit.point;
if (attachToCenterOfMass)
{
var 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);
}
function DragObject (distance : float)
{
var oldDrag = springJoint.connectedBody.drag;
var oldAngularDrag = springJoint.connectedBody.angularDrag;
springJoint.connectedBody.drag = drag;
springJoint.connectedBody.angularDrag = angularDrag;
var mainCamera = FindCamera();
while (Input.GetMouseButton (0))
{
var ray = mainCamera.ScreenPointToRay (Input.mousePosition);
springJoint.transform.position = ray.GetPoint(distance);
yield;
if (Input.GetMouseButton (1)){
springJoint.connectedBody.AddExplosionForce(throwForce,mainCamera.transform.position,throwRange);
springJoint.connectedBody.drag = oldDrag;
springJoint.connectedBody.angularDrag = oldAngularDrag;
springJoint.connectedBody = null;
}
}
if (springJoint.connectedBody)
{
springJoint.connectedBody.drag = oldDrag;
springJoint.connectedBody.angularDrag = oldAngularDrag;
springJoint.connectedBody = null;
}
}
function FindCamera ()
{
if (camera)
return camera;
else
return Camera.main;
}
$$anonymous$$ight not be too good way to do it, but I think you could just Destroy() the joint when player is too far away from it. Have you tried your own idea of nullifying connectedBody?
Why not just use a bool that gets set to true if the player is withing range, and set to false if not, and only call the door moving code if the bool is true?
I don't think there is door moving code, ins$$anonymous$$d there is spring joint that is used.
Exactly. The door is a rigidbody with a hinge joint. What I need is if the player is away by X of distance, then the object will fall = null. However, it's harder then it sounds I think.
Answer by Bunny83 · Dec 15, 2016 at 02:20 PM
This is a strange approach, but kinda interesting ^^. Am i right that the player is supposed to "drag" the door open "manually"?
Currently you only "check" the player distance from the door / object when you click down. This script seems more like it's designed for "carrying" objects around. So currently it doesn't actually differentiate if you carry a "normal" object or if you push / pull a door. So that's the main problem you have.
You should check if the object you're dragging is a door (maybe add a tag "door") and check it when you get the object using your raycast. Just remembering that the dragged object is a door (with a boolean for example). Inside your coroutine you can simply do a distance check if it's a door. If the dragged object is too far away, just cancel the dragging.
To cancel the dragging your want:
revert the drag / angular drag values
set the connectedBody to null.
and use
yield break;
to terminate your coroutine
Actually you don't necessarily need to check if it's a door as this restriction may apply to any object. If the object is stuck somewhere and you continue walking, you should cancel the dragging anyways.
The distance you have to check is the distance between your "springJoint" object position and the connectedBody position.
edit
To be a bit more specific this is how you could implement the distance check:
// inside your coroutine
// relative anchor point on the dragged object.
var objAnchor = springJoint.connectedBody.transform.InverseTransformPoint(springJoint.transform.position);
while (Input.GetMouseButton (0))
{
var ray = mainCamera.ScreenPointToRay (Input.mousePosition);
springJoint.transform.position = ray.GetPoint(distance);
// current anchor pos of the spring in worldspace
var springPos = springJoint.transform.TransformPoint(springJoint.anchor);
// current anchor pos of the dragged object.
var objPos = springJoint.connectedBody.transform.TransformPoint(objAnchor);
var currentDist = Vector3.Distance( springPos, objPos );
if (currentDist > maxThreshold)
{
springJoint.connectedBody.drag = oldDrag;
springJoint.connectedBody.angularDrag = oldAngularDrag;
springJoint.connectedBody = null;
yield break;
}
yield;
Where "maxThreshold" is simply the distance which basically "breaks" the connection. Note that this is untested. I barely worked with spring joints so i might have gotten some relative references wrong but it should work (theoretically ^^).
"objAnchor" is basically the point where the joint is attached to in local space of the dragged object. This is turned back into worldspace ( "objPos" ) every frame. "springPos" is basically the opposite. It's the anchor point on the spring object transformed into worldspace. So if everything is right, those two positions should be "more or less" equal. Of course the spring nature leaves some space, so don't make your threshold too small.
ps: You might want to put that "detaching" code in a seperate method since you would have the same three lines at three different places.
Thanks for your response. You understood correctly, the player is suppose to drag the door manually open with the rigidbody script, it is with a hinge joint. I tried that however I can't really make it to work and just blew my $$anonymous$$d, not really sure on how to approach this.
Also it's not necessarily to check if it is a door, since as you said it be better if the player "sprints" and the object drop.
Any ideas on how to approach?
Thanks!
Have you seen my edit? Sometimes UA seems to swallow certain notifications.
Answer by Fobri · Dec 15, 2016 at 03:08 PM
Well the most simple way is the do a check every update if the player is still within the distance, Not saying that it's the best, but the easiest.
if(Vector3.Distance(playerObject.transform.position, doorObject.transform.position) < 3)
Thanks for responding, I tried ''if(Vector3.Distance(playerObject.transform.position, doorObject.transform.position) < 3)'' and on update an then if the distance is not correct, then the object will be null but didn't work.
@yokek And why didnt it work? did you assign the variables too? like create public GameObject playerObject and assign it in the inspector etc? You need to do that first my script was just an example.
Well, I tried it how I know. There can't be any gameobject as you can pick up any object in the scene, so there is no assigning. You can have 5 doors in the scene for example. I added the code then the null script to disable the gameobject if the distance is < 3 however didn't' work well for me..
@yokek You can use playerObject = GameObject.FindGameObjectWithTag("Player"); to get the player reference automatically. After reading your updated question im not sure about my answer anymore tho.
Answer by yokek · Dec 16, 2016 at 11:56 AM
Thank you all for your responses, still trying to get it to work but no luck yet. :(
Your answer
![](https://koobas.hobune.stream/wayback/20220612102745im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
How to open individual prefab doors 1 Answer
Opening Door with Key 1 Answer
How to glue multiple objects together 0 Answers
Door Hinge joint glitches out when pushed to a limit? 1 Answer