So the range thing works that you need to be near it to grab it. Though after grabbing it moves it away for a certain distance which is a little weird. You might like to fix that. Also changing the range doesn´t seem to change it.
Edit:
Ok I found out how to adjust it:
In line 42 by changing the last number. But the distance from the camera should depend of the size of the object. Also it seems to slow them down, the smaller you set the number.
Edit2:
Ok cool just found out that the system is dependent on the mass of the grabbed object. Very neat! Also I changed the amount of force applied in line 44 to a multiplier of 30 instead of 10.
Line 41 - 46:
#Move The Object
offset = cam.worldPosition+(cam.worldOrientation*Vector([0,0,-2]))
V=offset-own['Grabbed'].worldPosition
own['Grabbed'].applyForce((V)*30*V.magnitude,0)
own['Grabbed'].applyForce((0,0,9.8*own['Grabbed'].mass),0)
own['Grabbed'].worldLinearVelocity*=.9
Set up like this it works really nice for me now. Thanks a lot for the template!
I actually made something similar some time ago except that it doesn’t snap objects to a point in front of a camera, it moves them relative to view vector. Run it on any object in script mode attached it to a positive triggering always sensor and try dragging around objects. Haven’t tested with a moving camera.
from bge import logic, render, events
from mathutils import Vector
mouse = logic.mouse
JUST_ACTIVATED = logic.KX_INPUT_JUST_ACTIVATED
ACTIVE = logic.KX_INPUT_ACTIVE
sc = logic.getCurrentScene()
obs = sc.objects
cam = sc.active_camera
def isTargetted():
cam = sc.active_camera
ray = cam.getScreenRay(logic.mouse.position[0], logic.mouse.position[1],90000, "")
return ray
def mousePosition(z):
camera = logic.getCurrentScene().active_camera
vec = cam.getScreenVect(*logic.mouse.position)
camPos = cam.worldPosition
projectedPos = (camPos - vec)*z
return Vector(projectedPos)
def mouseDrag(cont):
if not "ray" in cont.owner:
cont.owner["ray"] = None
cont.owner["offset"] = []
cont.owner["dist"] = 0
if mouse.events[events.LEFTMOUSE] == JUST_ACTIVATED:
cont.owner["ray"] = isTargetted()
if cont.owner["ray"]:
obs["Armature"]["chain"].selectActive(obs["Armature"], cont.owner["ray"]["bone"])
cont.owner["dist"] = cont.owner["ray"].getDistanceTo(sc.active_camera)
pos = mousePosition(cont.owner["dist"])
cont.owner["offset"] = Vector(pos-cont.owner["ray"].worldPosition.copy())
elif mouse.events[events.LEFTMOUSE] == ACTIVE:
if cont.owner["ray"]:
cont.owner["ray"].worldPosition = mousePosition(cont.owner["dist"])-cont.owner["offset"]
for i in range(obs["Armature"]["chain"].steps):
obs["Armature"]["chain"].update()
mouseDrag(logic.getCurrentController())
however I found the best method was to add a empty on grabbing at the mouse.hitPosition, and then apply forces to move the object to put that point under the cursor,
I will add a demo of this shortly.
Thanks everyone, I am trying really hard to put out useful resources based on what I have learned via wrectified.
i hate to necro post like this, but this is exactly what im looking for. i want to make draggable ragdoll but im not sure how to use this for it, im imagining i parent and empty to the points i want to drag from on the characters ragdoll armature yes?
Hi, im using your script and i would like to add the following fonction:
when the grabbed object is blocked by another thing (object, floor/wall friction,…) i would like it to drop (ungrab) at a certain distance from the player.
Learned quite a bit since I initially coded this so I recoded it from scratch to be less spammy and be ‘timed’
(so ‘dropping’ can’t be instantly recovered etc.)
This should work better and uses a ray cast from the camera instead of mouse_over,
iimport bge
def main():
cont = bge.logic.getCurrentController()
own = cont.owner
MouseClick = cont.sensors['Mouse']
TimeNotZ = cont.sensors['Time']
Cam=own.scene.objects['Camera']
#Set this to your players physics hitBox
#RayCaster = own.scene.objects['PlayerHitBoxName']
RayCaster = Cam
if own['Clock']>=1:
own['Clock']-=1
if 'Lifting' not in own:
#if Clock is zero and mouse is clicked cast ray to attempt to choose target
if MouseClick.positive and not TimeNotZ.positive:
own['Clock']=30
End = Cam.worldPosition+(Cam.worldOrientation.col[2]*-own['Range'])
Start = Cam.worldPosition
#Debug ray
bge.render.drawLine(End,Start,(0,1,0))
Ray = RayCaster.rayCast(End,Start,0,own['Ident'],0,0,0)
if Ray[0]:
print('hit')
own['Lifting']=Ray[0]
own['Clock']=-30
#picking up object
else:
if own['Clock']<=-2:
own['Clock']+=1
Position = Cam.worldPosition+(Cam.worldOrientation.col[2]*-own['DistanceOut'])
#Apply lifting force
V=Position-own['Lifting'].worldPosition
own['Lifting'].applyForce((V)*10*V.magnitude,0)
own['Lifting'].applyForce((0,0,9.8*own['Lifting'].mass),0)
own['Lifting'].worldLinearVelocity*=.9
#Drop if obstructed
End = own['Lifting'].worldPosition
Start = Cam.worldPosition
if own['Clock']==-1:
ray = RayCaster.rayCast(End,Start,0,'',0,0,0)
if ray[0]:
if ray[0]!=own['Lifting']:
own['Clock']=60
del own['Lifting']
#Drop if not holding mouse click
if not MouseClick.positive:
own['Clock']=30
if 'Lifting' in own:
del own['Lifting']
main()
thank you very much it works well but when i grab something its moove far away from the camera (same for the first version but i have take the set up of “CG-sky”)