PlayMaker Updates & Downloads > Share New Actions

Drag RigidBody

(1/4) > >>

jeanfabre:
Finally :)

 yes, finally, you can drag rigidBodies arounds with a single action, not complicated or manual setup :)

 I made it so that you can drag from a given fictive plane defined by a gameObject Up axis. This is very convenient if you want to drag objects on the ground instead of from the camera point of view.

 It of course against the moto of actions I feel, because it lacks of flexibility and it has too much responsability and not real implementation of how fsm should work, but there you go, it's a start :). For example it would be good to set up a mask variable to only allow for certain objects to be dragged. but that would be already for real scenarios. in that case, don't hesitate to come back to me for mods and more granular dragging properties.

usage: create a fsm, and on the start state, simply have this action. Play the scene and you'll be dragging any rigidbodies ( not set to kinematics of course).




--- Code: ---// (c) copyright Hutong Games, LLC 2010-2012. All rights reserved.

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{
[ActionCategory(ActionCategory.Physics)]
[Tooltip("Drag a Rigid body with the mouse. If draggingPlaneTransform is defined, it will use the UP axis of this gameObject as the dragging plane normal \n" +
"That is select the ground Plane, if you want to drag object on the ground instead of from the camera point of view.")]
public class DragRigidBody : FsmStateAction
{

[Tooltip("the springness of the drag")]
public FsmFloat spring;

[Tooltip("the damping of the drag")]
public FsmFloat  damper;

[Tooltip("the drag during dragging")]
public FsmFloat drag;

[Tooltip("the angular drag during dragging")]
public FsmFloat angularDrag;

[Tooltip("The Max Distance between the dragging target and the RigidBody being dragged")]
public FsmFloat distance;

[Tooltip("If TRUE, dragging will have close to no effect on the Rigidbody rotation ( except if it hits other bodies as you drag it)")]
public FsmBool attachToCenterOfMass;

[Tooltip("If Defined. Use this transform Up axis as the dragging plane normal. Typically, set it to the ground plane if you want to drag objects around on the floor..")]
public FsmOwnerDefault draggingPlaneTransform;


private SpringJoint springJoint;

private bool isDragging;

private float oldDrag;
private float oldAngularDrag;

private Camera _cam;

private GameObject _goPlane;

private Vector3 _dragStartPos;

private float dragDistance;

public override void Reset()
{
spring = 50f;
damper = 5f;
drag = 10f;
angularDrag = 5f;
distance = 0.2f;
attachToCenterOfMass = false;
draggingPlaneTransform = null;

}

public override void OnEnter()
{
_cam = Camera.main;
_goPlane = Fsm.GetOwnerDefaultTarget(draggingPlaneTransform);


}
public override void OnUpdate()
{

if (!isDragging && Input.GetMouseButtonDown (0))
{


// We need to actually hit an object
RaycastHit hit;
if (!Physics.Raycast(_cam.ScreenPointToRay(Input.mousePosition), out hit, 100))
{
return;
}

// We need to hit a rigidbody that is not kinematic
if (!hit.rigidbody || hit.rigidbody.isKinematic)
{
return;
}

StartDragging(hit);

}

if (isDragging)
{
Drag();
}


}

private void StartDragging(RaycastHit hit)
{
isDragging = true;

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

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

_dragStartPos = hit.point;


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

oldDrag = springJoint.connectedBody.drag;
oldAngularDrag = springJoint.connectedBody.angularDrag;

springJoint.connectedBody.drag = drag.Value;
springJoint.connectedBody.angularDrag = angularDrag.Value;

dragDistance = hit.distance;

}

private void Drag()
{

if (!Input.GetMouseButton (0))
{
StopDragging();
return;
}

Ray ray = _cam.ScreenPointToRay (Input.mousePosition);
if (_goPlane!=null)
{
Plane _plane = new Plane(_goPlane.transform.up,_dragStartPos);
float enter;

if (_plane.Raycast(ray,out enter))
{
springJoint.transform.position =ray.GetPoint(enter);
}

}else{

springJoint.transform.position = ray.GetPoint(dragDistance);
}



}

private void StopDragging()
{
isDragging = false;
if (springJoint==null)
{
return;
}
if (springJoint.connectedBody)
{
springJoint.connectedBody.drag = oldDrag;
springJoint.connectedBody.angularDrag = oldAngularDrag;
springJoint.connectedBody = null;
}
}

public override void OnExit()
{
StopDragging();
}
}
}

--- End code ---


 Bye,

 Jean

ar2511:
THX! It is very useful, however, Can I restrict it don't move Y axis or Z axis?
My game is a 2d game only.

Best Regards

Alex Chouls:
You could try the Constraints in RigidBody. Haven't tested to see if it works with this action, but it should...

ar2511:
Yes It works

I have some question would like to ask.

How can I make it move smoothly? I have tried for 1 day.

I have done some control experiment

increase  the spring

decrease the damper

decrease the drag

Best Regards

PS: I am a new beginner, plz forgive my annoying

mylesb:
Hi guys :)
I made one small change.
I added a bool variable to check if you want to drag the object up and down or forward and back.


--- Code: ---// (c) copyright Hutong Games, LLC 2010-2012. All rights reserved.

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{
[ActionCategory(ActionCategory.Physics)]
[Tooltip("Drag a Rigid body with the mouse. If draggingPlaneTransform is defined, it will use the UP axis of this gameObject as the dragging plane normal \n" +
"That is select the ground Plane, if you want to drag object on the ground instead of from the camera point of view.")]
public class DragRigidBody : FsmStateAction
{

[Tooltip("the springness of the drag")]
public FsmFloat spring;

[Tooltip("the damping of the drag")]
public FsmFloat  damper;

[Tooltip("the drag during dragging")]
public FsmFloat drag;

[Tooltip("the angular drag during dragging")]
public FsmFloat angularDrag;

[Tooltip("The Max Distance between the dragging target and the RigidBody being dragged")]
public FsmFloat distance;

[Tooltip("If TRUE, dragging will have close to no effect on the Rigidbody rotation ( except if it hits other bodies as you drag it)")]
public FsmBool attachToCenterOfMass;

[Tooltip("Move th object forward and back or up and down")]
public FsmBool moveUp;

[Tooltip("If Defined. Use this transform Up axis as the dragging plane normal. Typically, set it to the ground plane if you want to drag objects around on the floor..")]
public FsmOwnerDefault draggingPlaneTransform;

private SpringJoint springJoint;

private bool isDragging;

private float oldDrag;
private float oldAngularDrag;

private Camera _cam;

private GameObject _goPlane;

private Vector3 _dragStartPos;

private float dragDistance;

public override void Reset()
{
spring = 50f;
damper = 5f;
drag = 10f;
angularDrag = 5f;
distance = 0.2f;
attachToCenterOfMass = false;
draggingPlaneTransform = null;
moveUp = true;
}

public override void OnEnter()
{
_cam = Camera.main;
_goPlane = Fsm.GetOwnerDefaultTarget(draggingPlaneTransform);


}
public override void OnUpdate()
{

if (!isDragging && Input.GetMouseButtonDown (0))
{


// We need to actually hit an object
RaycastHit hit;
if (!Physics.Raycast(_cam.ScreenPointToRay(Input.mousePosition), out hit, 100))
{
return;
}

// We need to hit a rigidbody that is not kinematic
if (!hit.rigidbody || hit.rigidbody.isKinematic)
{
return;
}

StartDragging(hit);

}

if (isDragging)
{
Drag();
}


}

private void StartDragging(RaycastHit hit)
{
isDragging = true;

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

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

_dragStartPos = hit.point;


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

oldDrag = springJoint.connectedBody.drag;
oldAngularDrag = springJoint.connectedBody.angularDrag;

springJoint.connectedBody.drag = drag.Value;
springJoint.connectedBody.angularDrag = angularDrag.Value;

dragDistance = hit.distance;

}

private void Drag()
{

if (!Input.GetMouseButton (0))
{
StopDragging();
return;
}

Ray ray = _cam.ScreenPointToRay (Input.mousePosition);
if (_goPlane!=null)
{
Plane _plane = new Plane();

if ( moveUp.Value )
{
_plane = new Plane(_goPlane.transform.forward,_dragStartPos);
}
else
{
_plane = new Plane(_goPlane.transform.up,_dragStartPos);
}

float enter;

if (_plane.Raycast(ray,out enter))
{
springJoint.transform.position =ray.GetPoint(enter);
}

}else{

springJoint.transform.position = ray.GetPoint(dragDistance);
}



}

private void StopDragging()
{
isDragging = false;
if (springJoint==null)
{
return;
}
if (springJoint.connectedBody)
{
springJoint.connectedBody.drag = oldDrag;
springJoint.connectedBody.angularDrag = oldAngularDrag;
springJoint.connectedBody = null;
}
}

public override void OnExit()
{
StopDragging();
}
}
}
--- End code ---

Hope this is useful!

Cheers  :)
Myles Blasonato.

Navigation

[0] Message Index

[#] Next page

Go to full version