- Home /
How should I control a 'rake' that pushes objects around a table?
I won't get into too many details about my game, but I have a flat table that has a bunch of objects on it. Using the mouse, the player needs to be able to push these objects around, push them off the table, push them into a hole in the table, etc.
Right now I have a 'rake' rigidbody with 'kinematic' enabled, with a box collider - and I'm using the 'rigidbody.MovePosition' method to move it in line with the mouse movements. There are three major problems:
1) Even though the hitbox touches the surface of the table (and even extends below it a bit), sometimes the objects get 'stuck' and the rake passes right over them with barely a nudge, or flipping the object over.
2) Moving the rake quickly will very often pass right through objects.
3) Sometimes a small twitch will send the objects flying, even though the rake isn't moving very far.
I've tried a few different ways to let these objects interact, but I'm not familiar enough with Unity to know what options I have.
I want this to feel like you're really pushing objects - when you pull the rake through a pile, it should just pull them all with the rake and not leave any behind.
Thanks for any advice.
Are the objects rigidbodies too? Try changing your rake's collision on the rigidbody to "Continuous Dynamic," as fast or unexpected jerks of the rake will sometimes cause unexpected behavior.
Try adding mass to your objects, and make them use gravity if you are not already.
I would try to make the collision box match exactly flush with the table, ins$$anonymous$$d of trying to extend under it. Does your table have a collider too? $$anonymous$$oving a collider through another collider like that (Rake through table in this case) can sometimes confuse objects with other collision detection into thinking the table itself is moving.
Let me know if any of this helps!
Hi.
Yes, the objects are rigidbodies that obey gravity.
I will try giving them more mass, I will try making the collider exactly flush with the table. Yes, the table has a box collider, but not a rigidbody. Since the Rake is kinematic, they don't interact at all, but I can see how it would mess with detection.
Okay great, if you'd like to post a picture of the issue perhaps I can offer different solutions. Namely, pushing the objects manually with vector3 at the speed and direction of the rake using an OnTriggerEnter function. That would give you very predictable results, unlike the physics engine solution you're currently using.
I made the first change you suggested to the box collider, and it made the problem worse =(
I couldn't get a video to record properly, but I took some screenshots:
Images 1 and 2 are the result of dragging the rake through the pile at a consistent speed over a period of about 1 second. I didn't mention it, but in my project settings I turned '$$anonymous$$in penetration for penalty' to .0001 - to try to prevent the objects 'sinking' into the floor.
Images 3 and 4 are an unrelated glitch that is also happening pretty often. There are two box colliders in the table that are touching, and the cards have a thickness of .02 (the rake height is .4 for comparison). I could just throw more box colliders to overlap any cracks in the object, but that feels like the wrong way to fix this.
I thought about your solution to add force, but isn't that what the physics engine basically does anyway? I feel like I'm trying to reinvent the wheel if I go down that path.
edit:
I played around with this a bit more. Even when I make things much thicker, they still sometimes duck under the rake. Looking closely, I can see the rake is pushing them forward a bit, but then they get pushed downward into the table, and resurface behind the rake - like ice floating in water. I'm guessing all my problems revolve around the fact that everything sinks into the table too much.
I see, okay try this: Somewhere in your script, lock the Y axis of your chips by setting it's Y value manually. This should inevitably prevent any sinking.
function LateUpdate() { ChipsOrDollars.transform.position.y = 2.0;
}
EDIT: You don't/won't have to use the translate.position scripts in conjunction with this fix, you can just put a simple script locking the Y axis of your chip/group of chips and it should stop the sinking. Just make sure it's LateUpdate or you may run into some issues.
Answer by fdsdfg · Jul 19, 2014 at 04:02 PM
I messed around with this a lot, and found out it was because when I move the 'rake' rigidbody, the objects don't know whether to go forward (pushed across the table, what I'd expect to happen), or down (sink into the table, bad).
I figure this is because instead of the rake having a force moving in one direction, the 'moveposition' just sort of places it on top of the object - and the object will choose the shortest path out of the collider - which can often be down.
I fixed this by having the collider extend very far down into the table - so there's no way the shortest path would be anything other than parallel to the table surface.
Cool! I'm very glad you got it working as expected, and I'll remember this fix when I inevitably come across a similar situation.
Answer by Addyarb · Jul 18, 2014 at 10:52 PM
using UnityEngine;
using System.Collections;
//Attach this script to your chip objects, or possibly even a group of chips with their own colliders.
public class PutObjectsInHole : MonoBehaviour {
public GameObject Rake; //Name your rake "Rake"
public GameObject Hole; //Name the hole in the center of the table "Hole"
public float RakeSpeed = 5;
public float TableHeight = 10.111f; //Set the exact (to the hundredths or better) position of your table's collider's top surface.
public Transform ChipOrDollar;//Adjust this to make the raking of objects more realistic by matching it's speed.
// Use this for initialization
void Start () {
Rake = GameObject.Find ("Rake");
Hole = GameObject.Find ("Hole");
ChipOrDollar = transform;
}
// Update is called once per frame
void LateUpdate () {
ChipOrDollar.transform.position.y = TableHeight;
}
void OnTriggerEnter(Collider col){
if (col.gameObject.tag == "RakeTag") {
ChipOrDollar.position = Vector3.MoveTowards(transform.position, Hole.transform.position, RakeSpeed*Time.deltaTime);
}
}
void OnTriggerExit(Collider col){
if (col.gameObject.tag == "RakeTag") {
GameObject.Destroy(ChipOrDollar);
Debug.Log ("Here is where you would add the chips to a player")
//if(ChipOrDollar.tag = red){
//chipScript.score += 10;
//}
}
}
Thanks, but it is really important that the objects are pushed around in response to physics, and can go in any direction - they can't just be 'scooted' toward the goal. Even if I had them move in the direction the rake is moving, it's still very awkward compared to physics force being applied.