Move Object by dragging (mobile) makes the balls fall from the cup - unity3d

I have this cup that contains balls inside. All 2D
I am using Rigidbody2d and Collider2d.
When running in unity and moving the cup (with arrow keys) the balls stay inside the cup. I also added drag movement for Android touch to move the cup.
The problem is that when moving the cup too fast (by draging) the balls fall from the cup collider (using Polygon colider 2d).
Code for movement is:
public float speed = 0.1F;
void Update() {
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
transform.Translate(-touchDeltaPosition.x * speed, -touchDeltaPosition.y * speed, 0);
}
}
I tried to play with the speed parameter but it wont really help. if the cup movement is too slow it is not very useful for me.
I believe it is related the velocity/force of the ball or cup which makes the cup collider miss...
Any help on this would be appreciated greatly!

it is because you are moving it by changing the position of the cup, that means that when you move it fast, it disappears, and reappears where you dragged it, leaving the balls behind, and then they fall. I had the same thing where my objects would just go through the walls and out of the camera area. I fixed that by using AddForce. This makes the cup move, position by position over to where you dragged. this bumps the balls along, and they stay in the cup. This is what I guess is going on. If you use velocity that would work to.
you could rather than transform.Translate, you could find the vector to where you want to move to.
var direction = touchDeltaPosition - transform.position;
gameObject.rigidbody2D.velocity.x = direction.x * speed;
gameObject.rigidbody2D.velocity.y = direction.y * speed;
hope this solves it

The problem is that, when you're moving the cup too fast, at Frame 1 the ball is inside the cup, but at Frame 2 it's outside. You can reduce the value of "Fixed Timestep" (http://docs.unity3d.com/Manual/class-TimeManager.html) to increase the frequency of the physics calculations, or make the colliders larger.
If a ball in the cup will always stay in the cup, maybe you can turn off the physics of the ball once it's in the cup, or something along those lines.

Usually transform.Translate() is not very efficient when dealing with colliders, instead, you can try three other solutions:
1) rigidbody2D.AddForce(Vector2.Up * Input.GetAxis("Vertical"));
2) rigidbody2D.velocity = new Vector2(//write what you need);
3) which I consider the best solution for dealing with colliders and dragging is : MoveRigidbody2D

Well, this is what worked for me:
var newVec = new Vector2 (transform.position.x, transform.position.y);
var touchDeltaPosition = Input.GetTouch(0).deltaPosition*touchSpeed;
var direction = touchDeltaPosition- newVec;
rigidbody2D.AddForce(direction);

Related

How to make a model appear in front of AR Camera after the session starts using ARFoundation?

I was looking to update the ARcamera position.I am doing ImageTracking project.It detects an image and a corresponding prefab is shown in front of the camera.It starts playing an animation.After the animation I want the prefab to come really close towards the camera.When I give the code prefab.position=ARcamera.position; after animation code,I think the prefab goes to the initial position where the ARCamera was when the app had started that is (0,0,0).
How to make the prefab come really close towards the front camera.
speed = 10f;
float step = speed * Time.deltaTime;
Showprefabs.transform.GetChild(0).position = Vector3.MoveTowards(Showprefabs.transform.GetChild(0).position,
new Vector3(Arcam.transform.position.x, Arcam.transform.position.y + 0.2f,
Arcam.transform.position.z + 6.3f), step);
//The values 0.2f and 6.3f I added using the Editor to make the prefab come near the camera(But in world position it is different.)
First of all I hope by "prefab" you mean already Instantiated GameObject. It makes no sense to move a prefab ;)
You tried to calculate the target position but did it with World-Space coordinates.
You probably want to do something like
var targetObject = Showprefabs.transform.GetChild(0);
var currentPosition = targetObject.position;
var targetPosition = Arcam.transform.position
// Place it 60cm in front of the camera
+ Arcam.transform.forward * 0.6f
// additionally move it "up" 20cm perpendicular to the view direction
+ Arcam.transform.up * 0.2f;
targetObject.position = Vector3.MoveTowards(currentPosition, targetPosition, step * Time.deltaTime);
If you want that movement a bit smoother so it moves slower if already close and faster if further away you might be interested in rather using Vector3.Lerp here
public float smoothFactor = 0.5f;
targetObject.position = Vector3.Lerp(currentPosition, targetPosition, smoothFactor);
Where a smoothFactor of 0.5 reads: Every frame set the object to a position in the center of the currentPosition and targetPosition. A value closer to 0 results in slower movement, closer to 1 in faster reaching the targetPosition.
Note that actually this approach will never really fully arrive at the targetPosition but only come very very close but usually this doesn't matter in AR where the Camera constantly moves a bit anyway.

Unity: How to find a empty hole in a wall for player?

I'm trying to figure out simple custom 2D physics for platformer. At the moment I'm using ray casts to figure out collision between the player and map. However using ray cast has some problems. For example, if the player is falling (has somewhat high downwards velocity) its unable to pick up holes in the wall because it moves past them due to going too far down to be detected as empty space.
One solution is to move to tile based system instead of using ray casts but I would preferably not to do so.
So I'm wondering is there some kinda solution to figure out empty holes in wall, even small edge ones without huge performance impact.
High quality drawn illustration, assume leftwards velocity:
Physics2D.BoxCast is how I would tackle this. It does what you expect, instead of a ray it calculates as if a full box was traversing the distance.
Usage is very similar to raycasting. Example:
public Collider2D mainCollider;
public Vector2 velocity;
void Update() {
Vector2 origin = new Vector2(transform.position.x, transform.position.y);
Vector2 size = mainCollider.bounds.size;
Vector2 direction = velocity * Time.deltaTime;
float maxDist = velocity.magnitude;
var hit = Physics2D.BoxCast(origin, size, 0, direction, maxDepth);
if (hit == null) {
transform.position += direction;
} else {
transform.position += direction.normalized * hit.distance;
}
}
If boxes are not your taste, there's also a Physics2D.CapsuleCast and Physics2D.CircleCast.

Using Unity Physics to consistently bounce a ball to the same height

My ball can only bounce on the y axis. X and Z movement as well as all rotation are locked in the rigidbody component. Originally I was planning to handle this using a combination of the two methods below. I'm adding my own faux-gravity to the object in FixedUpdate and bouncing the ball upwards when it collides with a platform in OnCollisionEnter. Esentially sending it bouncing up and down forever.
void OnCollisionEnter(Collision collision)
{
ball.AddForce(Vector3.up * force, ForceMode.Impulse);
}
void FixedUpdate()
{
Vector3 gravity = globalGravity * Vector3.up;
ball.AddForce(gravity, ForceMode.Acceleration);
}
The problem is that if I place an angled platform under the ball, it no longer bounces vertically with the same force. I believe this is because Unity Physics is calculating the angle/force the object should bounce in a 3D space, and then because of my script only applying the upward force of that calculation. However, I'd like my ball to bounce with a consistent vertical force regardless of the angle of the platform placed under it.
This could be achieved using a coroutine and Lerp to a certain height, which I tried using the script below, using Physics gravity this time, but it didn't have the same natural bouncing feel as Unity Physics. I'd like to go back to using the Physics system but I don't know how to stop Unity from doing the angular calculation and just launch my ball vertically with the force I want.
IEnumerator MoveBall(Vector2 newPos, float time)
{
ball.useGravity = false;
float elapsedTime = 0;
Vector2 startingPos = transform.position;
while (elapsedTime < time)
{
transform.position = Vector2.Lerp(startingPos, newPos, (elapsedTime / time));
elapsedTime += Time.deltaTime;
yield return null;
}
ball.useGravity = true;
}
It sounds like you want your collider to be setup as a trigger. On your ball's collider, set isTrigger to true and then use OnTriggerEnter instead of OnCollisionEnter. This will prevent Unity's physics engine from creating and resolving a Collision between the ball and whatever it hits.
If you'd also want the ball to bounce off other objects in way that uses Unity's Physics, you'll need to then get creative with which colliders are/arent' triggers, and which physics layers they belong to.

unity2D Moving to a fixed object causes weightlessness

Please look at the photo. There are two objects.
left circle object = circle colider2D + rigidbody2D(freeze Rotation Z, script for move )
Rigidbody2D rigid;
float moveX;
void Start()
{
rigid = gameObject.GetComponent<Rigidbody2D>();
}
void PlayerMove(){
moveX = Input.GetAxisRaw("Horizontal");
rigid.velocity = new Vector2(moveX * 5f, rigid.velocity.y);
}
void Update(){
PlayerMove();
}
right square object = square colider2D + rigidbody2D(freeze positionY, freeze positionX, freeze Rotation Z)
I can move the circle from side to side.
While I press the keyboard and push the circle to the right wall, gravity doesn't work.
I don't know why. I hope gravity will work even if the circle hit the wall.
How can I prevent the problem?
Looks like physics material that's applied to that rigidbody has too much friction and slows down too much when hugging the wall. Try reducing friction value on the material (you can create the physics2D material from the assets panel).

How to prevent colliders from passing through each other?

I am having trouble keeping game objects inside of a contained space. When they reach the edge, there is some momentary push back but then they will go right through the wall.
I am using a Box Collider on the player, and a Mesh Collider for the level's wall. I am having issues with both a Player Character (a space ship) that the movement is controlled by the player. And with projectiles, which are fire and forget moving at a constant speed.
This is my movement code for my player. It is being run in the FixedUpdate() function.
//Movement
haxis = Input.GetAxis("Horizontal") * speed;
vaxis = Input.GetAxis("Vertical") * speed;
moveVector.x = haxis;
moveVector.z = vaxis;
if(moveVector.magnitude > 1)
{
moveVector.Normalize();
}
rigidbody.MovePosition(transform.position + moveVector * speed);
With the bullets, they are given a velocity and the engine calculates their moviements. They are using Box Collider and it is set as a Trigger so they don't have physics. But I use OnTriggerEnter to destroy them.
//Projectiles without physics collisiions
function OnTriggerEnter (other : Collider) {
Destroy(gameObject);
}
Some, but not all of the bullets will be destroyed when hitting the mesh collider wall. The player will sometimes hit it and stop, but can usually push through it. How can I make the collisions with the mesh collider work every time?
Collision with fast-moving objects is always a problem. A good way to ensure that you detect all collision is to use Raycasting instead of relying on the physics simulation. This works well for bullets or small objects, but will not produce good results for large objects.
http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html
Pseudo-codeish (I don't have code-completion here and a poor memory):
void FixedUpdate()
{
Vector3 direction = new Vector3(transform.position - lastPosition);
Ray ray = new Ray(lastPosition, direction);
RaycastHit hit;
if (Physics.Raycast(ray, hit, direction.magnitude))
{
// Do something if hit
}
this.lastPosition = transform.position;
}
I have a pinball prototype that also gave me much trouble in the same areas. These are all the steps I've taken to almost (but not yet entirely) solve these problems:
For fast moving objects:
Set the rigidbody's Interpolate to 'Interpolate' (this does not affect the actual physics simulation, but updates the rendering of the object properly - use this only on important objects from a rendering point of view, like the player, or a pinball, but not for projectiles)
Set Collision Detection to Continuous Dynamic
Attach the script DontGoThroughThings (https://www.auto.tuwien.ac.at/wordpress/?p=260) to your object. This script cleverly uses the Raycasting solution I posted in my other answer to pull back offending objects to before the collision points.
In Edit -> Project Settings -> Physics:
Set Min Penetration for Penalty to a very low value. I've set mine to 0.001
Set Solver Iteration Count to a higher value. I've set mine to 50, but you can probably do ok with much less.
All that is going to have a penalty in performace, but that's unavoidable. The defaults values are soft on performance but are not really intented for proper simulation of small and fast-moving objects.
How about set the Collision Detection of rigidbody to Continuous or Continuous Dynamic?
http://unity3d.com/support/documentation/Components/class-Rigidbody.html
So I haven't been able to get the Mesh Colliders to work. I created a composite collider using simple box colliders and it worked exactly as expected.
Other tests with simple Mesh Colliders have come out the same.
It looks like the best answer is to build a composite collider out of simple box/sphere colliders.
For my specific case I wrote a Wizard that creates a Pipe shaped compound collider.
#script AddComponentMenu("Colliders/Pipe Collider");
class WizardCreatePipeCollider extends ScriptableWizard
{
public var outterRadius : float = 200;
public var innerRadius : float = 190;
public var sections : int = 12;
public var height : float = 20;
#MenuItem("GameObject/Colliders/Create Pipe Collider")
static function CreateWizard()
{
ScriptableWizard.DisplayWizard.<WizardCreatePipeCollider>("Create Pipe Collider");
}
public function OnWizardUpdate() {
helpString = "Creates a Pipe Collider";
}
public function OnWizardCreate() {
var theta : float = 360f / sections;
var width : float = outterRadius - innerRadius;
var sectionLength : float = 2 * outterRadius * Mathf.Sin((theta / 2) * Mathf.Deg2Rad);
var container : GameObject = new GameObject("Pipe Collider");
var section : GameObject;
var sectionCollider : GameObject;
var boxCollider : BoxCollider;
for(var i = 0; i < sections; i++)
{
section = new GameObject("Section " + (i + 1));
sectionCollider = new GameObject("SectionCollider " + (i + 1));
section.transform.parent = container.transform;
sectionCollider.transform.parent = section.transform;
section.transform.localPosition = Vector3.zero;
section.transform.localRotation.eulerAngles.y = i * theta;
boxCollider = sectionCollider.AddComponent.<BoxCollider>();
boxCollider.center = Vector3.zero;
boxCollider.size = new Vector3(width, height, sectionLength);
sectionCollider.transform.localPosition = new Vector3(innerRadius + (width / 2), 0, 0);
}
}
}
1.) Never use MESH COLLIDER. Use combination of box and capsule collider.
2.) Check constraints in RigidBody. If you tick Freeze Position X than it will pass through the object on the X axis. (Same for y axis).
Old Question but maybe it helps someone.
Go to Project settings > Time and Try dividing the fixed timestep and maximum allowed timestep by two or by four.
I had the problem that my player was able to squeeze through openings smaller than the players collider and that solved it. It also helps with stopping fast moving objects.
Edit ---> Project Settings ---> Time ... decrease "Fixed Timestep" value .. This will solve the problem but it can affect performance negatively.
Another solution is could be calculate the coordinates (for example, you have a ball and wall. Ball will hit to wall. So calculate coordinates of wall and set hitting process according these cordinates )
Try setting the models to environment and static. That fix my issue.