Make rigid body bounce off the screen edge - unity3d

I'm currently working on an object that involves bubble-like movement. This object has a rigidbody and a sphere collider.
I use the AddForce method every 1-3 seconds to make it move continuously and slowly.
Now I'd like to know how to make the rigidbody move in the opposite direction (a.k.a bounce off) when they reach the screen edge already. I have already computed the screen edges using ViewportToWorldPoint method.
One ineffective solution that I thought of is to put empty game objects with collider at the edges but that won't work in my case since I'm building for mobile devices which have different screen resolutions/sizes.
Anyone know a good solution for this?

I'm not sure i got the idea. But i think i had the same problem when i was writing an old mobile game.
I had the same idea you did, use empty game objects with box collider on the edges, but then i thought, this isn't responsive, so i wrote this code:
public class Walls_c : MonoBehaviour {
public Transform righttop;
public Transform rightbottom;
public Transform lefttop;
public Transform leftbottom;
// Use this for initialization
void Start () {
righttop.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(1,1,0));
rightbottom.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(1,0,0));
lefttop.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(0,1,0));
leftbottom.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(0,0,0));
}
}
With this, i always get the corners of the screen. It's no fancy... but it works.
Let me now if it works.

In order to get a reflection effect, you need Material. Attach a bouncy material to the edges(gameObject) and let the physics calculate what should be the reaction of collision.
Create a Physics 2D material and set the bounceness to some appropriate value say 0.2.
Regarding your issue:
One ineffective solution that I thought of is to put empty game
objects with collider at the edges but that won't work in my case
since I'm building for mobile devices which have different screen
resolutions/sizes.
If you are working with UI component then dealing with boundaries should not be a problem (since it anchors with different resolution) but if it is not the case you can create a script CameraResizer and an enum Anchor (Left, Right, Top, Bottom) and using the same way ViewportToWorldPoint you can align your empty gameObject (boundary) to any screen size by attaching it the gameObject.
Hope it helps!

Related

Why does the object get stuck in the wall when repelled?

I made the endless movement of the object and its repulsion from the walls, but it does not always work correctly. At rounded corners (sometimes even at a straight wall), it just gets stuck and stops moving altogether, or moves slowly to the point where it stops moving. What can this be related to and how can it be fixed?
private void FixedUpdate() {
rb.velocity = direction * normalSpeed;
lastDirection = direction;
}
private void OnCollisionEnter2D(Collision2D collision) {
//Repulsion from objects.
direction = Vector3.Reflect(lastDirection.normalized, collision.GetContact(0).normal);
}
There is a small distance between the objects, but the circle seems to stick to the wall and moves with it until it collides with another collider:
Example
there are objects under the circle that also have colliders, but the collision between them is not considered, since they have the same layer (in the settings, I disabled the collision for objects on the same layer). What can be done to fix this error and what can it be related to?
The object in the general scale:
Example
I tried to increase the size of the wall collider, tried to change polygon collider to box collider, connect composite collider, changed the mechanics of the object movement (in these cases, the movement could work incorrectly), but the result was always the same - the jams (sticking to the wall) continued.
It is difficult to answer your question without having more information, but I can suggest if you are using physics to move your objects - utilize physic materials and remove code that changes direction manually in OnCollisionEnter. Using physic materials you can easily make your object bounce from colliders of your choice without losing velocity.

Unity3d - Need to hide a group of objects in the area

I've already tried depthmask shaders and examined some other ideas, but it seems like it doesn't suit me at all.
I'm making an AR game and I have a scene with a house and trees. All these objects are animated and do something like falling from the sky, but not all at once, but in sequence. For example, the house first, then trees, then fence etc.
(Plz, look at my picture for details) http://f2.s.qip.ru/bVqSAgcy.png
If user moves camera too far, he will see all these objects stucking in the air and waiting for their order to start falling, and it is not good. I want to hide this area from all sides (because in AR camera can move around freely) and make all parts visible only when each will start moving (falling down).
(One more screen) http://f3.s.qip.ru/bVqSAgcz.png
I thought about animation events, but there are too many objects (bricks, for example) and I can't handle all of them manually.
I look forward to your great advice ;)
P.S. Sorry for my bad english.
You can disable their(the objects that are gonna fall) mesh renderers and re active them when they are ready to fall.
See here for more details about mesh renderer.
Deactivate your Object. You might use the camera viewport coordinates to get a y position outside the viewport. They start on the bottom left of the screen (0,0) and go to the top right of the screen (1,1). Convert them to worldspace coordinates. Camera.ViewportToWorldPoint
Vector3 outsideCamera = Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 1.2f, 10.0f));
Now you can use the intended x and z positions of your object. Activate it when you want to drop it.
myObject.transform.position = new Vector3(myObject.transform.position.x, outsideCamera.y, myObject.transform.position.z);
Another thing you could additionally do is scaling the object from very small to its intended size when it is falling. This would prevent the object being visible before falling when the users point the camera upwards.
1- Maybe you can use the Camera far clipping plane property.
Or you can even use 2 Cameras if you need to display let's say the landscape on one (which will not render the house + trees + ...) with a "big" far clipping plane and use a second one with Depth only clear flags rendering only the items (this one can have a smaller far clipping plane from what I understand).
2- Other suggestion I'd give you is adding the scale to your animation:
set the scale to 0 on the beginning of animation
wait for the item to be needed to fall down
set the scale to 1 (with a transition if needed)
make the item fall down
EDIT: the workaround you found is quite just fine too! But tracking only world position should be enough I think (saving a tiny amount of memory).
Hope this helps,
Finally, the solution I chose. I've added this script to each object in composition. It stores object's position (in my case both world and local) at Start() and listening if it changes in Update(). So, if true, stop monitoring and set MeshRenderer in on state.
[RequireComponent(typeof(MeshRenderer))]
public class RenderScript : MonoBehaviour
{
private MeshRenderer mr;
private bool monitoring = true;
private Vector3 posLocal;
private Vector3 posWorld;
// Use this for initialization
void Start()
{
mr = GetComponent<MeshRenderer>();
mr.enabled = false;
posLocal = transform.localPosition;
posWorld = transform.position;
}
// Update is called once per frame
void Update()
{
if (monitoring)
{
if (transform.localPosition != posLocal || transform.position != posWorld)
{
monitoring = false;
mr.enabled = true;
}
}
}
}
Even my funny cheap сhinese smartphone is alive after this, so, I guess, it's OK.

Unity 2D Bounce Back moving object when colliding with another object

I have an object that, after receiving its respective input, it moves this way:
mov = new Vector3((Input.GetAxis("Horizontal") * vel), 0, 0);
transform.position += mov;
But, I want it to bounce back, once it collides with an object.
I´ve made the procedures already (OnCollisionEnter2D(Collsion2D col){bla bla...}), but I need help with what happens on the collision (bouncing back the object)....
I´ve tried giving the collided object a bouncing material, but it just slows it a bit, my guess is that because of the constant force given by the acceleration.
Greetings.
If you move the object with transform.position what you are doing is basically a "teleport" so it will ignore the bouncing material. If you want it to bounce you have to write the physics code to detect a collision and change the movement or you can do addforce to move the object and it will detect collisions and react automatically.
you are teleporting the object at the current time. instead you should use the Rigidbody.addForce this will add a force in the specified direction thus if you do the opposite direction will "bounce" of the object. Another option would be to create a physics material then not bother with the code.
You are not using materials, right?
See if the content of this post may help you, the OP is using a formula using Raycast and the answer guides him to use the Raycast with Layers Maks:
2D bouncing formula doesn't work properly
There is this one also with fixed angles (like Pong), but it uses material (with values: friction: 0, bounciness: 1):
https://gamedev.stackexchange.com/questions/70294/get-gameobject-to-bounce-of-colliders
But if nothing makes sense and you are going crazy and might want to start from zero, there is this official video tutorial on bouncing and sliding in 2D:
https://unity3d.com/learn/tutorials/modules/beginner/2d/sliding-bouncing-2d

Wheel Collider Unity: after adding torque the vehicle starts moving sideways

I really killed few hours to try to fix this, Googling for a solution, but I could not.
I've got a vehicle, it's a go-cart, so there are no suspensions (technically there are, but the values are close to 0, to simulate the tires). The vehicle has a rigid body attached and the child object contains the 4 wheel colliders (and the model itself), as can be seen here:
https://dl.dropboxusercontent.com/u/76599014/sxc/Clipboard01.jpg
For testing, I added a short script to make the vehicle move. It's in the GameObject called "gokart":
public class carControler : MonoBehaviour {
public WheelCollider fr, fl, rr, rl;
public float performance = 50f;
void FixedUpdate () {
throttle();
}
public void throttle() {
this.rl.motorTorque = this.performance;
this.rr.motorTorque = this.performance;
} }
What happens is: the rear wheels start to rotate, as intended, but the vehicle starts moving sideways slowly. The movement speed depends on the torque amount (the wheel rotation in this case). There is no movement forward, so this is not the bug, where when you are standing on a flat surface you are drifting on the sides.
Any ideas? If you need a video or a GIF (I have to figure out how to make one) of the movement, I'll be glad to provide one.
I think you should try and apply 0 brake torque to the front wheels while applying motor torque to the rear wheels.
public void throttle() {
this.rl.motorTorque = this.performance;
this.rr.motorTorque = this.performance;
this.fr.brakeTorque = 0f;
this.fl.brakeTorque = 0f;
}
That being said, anything could go wrong if the Rigidbody/wheelcolliders aren't set up correctly. Unity's wheel colliders can be difficult to set up and work with. Unity changed the physics in Unity 5 so most documentations are outdated.
I found this very good short document that was made by unity: http://unity3d.com/profiles/unity3d/themes/unity/resources/downloads/beta/unity-5.0-user-guide.pdf
It highlights the changes that was made to unity 5 and at the end of page 5 you can find a section that explains how to set up a car. I have tried it about a month ago in a new unity project and it worked. the instructions are clear so try this tutorial out and I hope it will help.
Regards
Not having the image available I'm not a totally sure about the situation but my assumption based on your description is you should try increasing the sideways friction and tweak the forward friction a little bit according to your taste. You have to increase the sideways friction anyways as you are making a go-cart. As far as I know, most arcadey go-carts don't drift and behave a lot different from regular racing cars.
Hope that will solve the problem.

How to detect that my object is completely inside a box?

I'm developing a game that you drag and drop objects into boxes and I have no idea what's the best and most efficient way to detect whether my objects are in a box.
I'm well aware of colliders and I'm using BoxColliders and triggers to find out whether my object is touching a box but I want to detect the moment when my object (which we can assume to be sphere for sake of simplicity but later will be a mesh) is completely inside my box trigger/collider.
I read about "Contains" method of colliders but IIRC they just check if one single point inside that collider but I'm interested to know if the whole object is inside the collider.
Thanks in advance folks.
Short answer: If you want 100% accuracy, your algorithm will never be better than O(|V|) (worst case) where V = {all vertices in mesh}, meaning you'd run .Collides() over every vertex and break if you find one that is outside your container.
Longer answer: Several methods exist to subdivide mesh surfaces, examples include: KD-Trees, OcTrees. These are beyond the scope of an SO answer to provide a full implementation, I suggest you see the wiki pages for details.
You could use these methods to divide your mesh up in to smaller sets of vertices. To speed up your algorithm you would start at the root of your subdivision tree and test if that node is contained in your container box. Keep working through the tree until you find a node that is not contained by your box. This will allow your "contains" test to fail faster but ultimately you'll wind up testing every vertex if your box contains your mesh.
Caveat: This solution does not work if your mesh is animated. In that case your best bet is to use the bounds around things like arms, feet, legs, etc and use that information to cull your Contains() tests. Again, you'll end up having to test every vertex if the mesh is fully inside your box.
All boxes have a boxCollider. If an object touches the second box, the object must be inside the first box.
This is not a good solution but, maybe it will be usefull.
Use Renderer.bounds property to get bounding box of your object.
Depending on what object you have and how accurate you want to check it to be inside a collider you might than use one of the simple ways to determine that.
for a more refined and cleaner approach. this would be perfect for what you are doing .
you can check the distance between the object you are dragging and the box .
the box has a x,y,z value which represents its position in space.
so when you drag your gameobject it may be just 0.2 on the x,y, or z away from the centere of your box. so just use this method to calculate the distance between your dragged object and the box.
var other :Transform;
function Update()
{
var dist = Vector3.Distance(other.position, transform.position);
// while dragging
if(dist <10)// 10 being on all 3 axiz .
{
//dragged object.position = box position
}
if (dist == 0)
{
print("i am in the centre of the box");
}
}
thus your gameobject will be in the box .
The box within a box solution above is a good option, but if that won't work (due to variably sized/shaped objects) you might be able to accomplish something with Physics.Raycast or Collider.Raycast. I had a similar problem where I needed to test if arbitrary points were contained inside colliders (many of which were unusual blobby concave objects).
The basic idea is a "bed of nails" approach where I cast rays toward the point from multiple directions. If I hit the outside collider on all of the rays, then I can be pretty confident that the point is contained inside the collider (but still not completely certain). Here's a pic:
In this picture, we're trying to see if the blue point is inside the yellow collider. The GREEN arrows represent successful raycasts (the yellow collider is hit), and the PINK one is unsuccessful (the yellow collider is NOT hit).
Here is a code snippet illustrating this:
public static class CollisionUtils {
private static readonly Vector3[] raycastDirections;
// These are the directions that we shoot rays from to check the collider.
static UltrasoundCollisionUtils() {
raycastDirections = new Vector3[5];
raycastDirections[0] = new Vector3(0,1,0);
raycastDirections[1] = new Vector3(0,-1,-0);
raycastDirections[2] = new Vector3(0,0,1);
raycastDirections[3] = new Vector3(-1.41f, 0, -0.5f);
raycastDirections[4] = new Vector3(1.41f, 0, -0.5f);
}
public static bool IsContained (Vector3 targetPoint, Collider collider) {
// A quick check - if the bounds doesn't contain targetPoint, then it definitely can't be contained in the collider
if (!collider.bounds.Contains(targetPoint)) {
return false;
}
// The "100f * direction" is a magic number so that we
// start far enough from the point.
foreach (Vector3 direction in raycastDirections) {
Ray ray = new Ray(targetPoint - 100f * direction, direction);
RaycastHit dummyHit = new RaycastHit();
// dummyHit because collider.Raycast requires a RaycastHit
if (!collider.Raycast(ray, out dummyHit, 100f)) {
return false;
}
}
return true;
}
}
One way you could adapt this algorithm is rather than use Collider.Raycast, do a Physics.Raycast. If the rays hit anything other than your collider, then you know that your target object isn't entirely in the collider.
Add a BoxCollider which surrounds the whole of the object you are testing for and check its bounds min and max are contained within the BoxCollider its entering ... this may not suit for complex mesh objects but you may be able to get away with it and its cheap
Simply,
You can place a box Collider at the bottom of your container.. If your sphere or whatever object touches that then it is completely inside the container..
There is one method though....not that accurate but will work :
Make four empties with collider(Circle / Box) like four wheels of a car and make the object parent to these empty objects with collider.
Then assign every collider a bool whether it is touched or not....
Count the number of colliders touched along with the actual mesh collider...Roughly estimates the orientation of the overlap. If it is 2 that means touched or overlaped from sideways.
Ex: If two collider + the mesh collider is colliding which means it is overlapped sideways...
I solved it using bounds.contains(vector 3 point).
I placed a single point on the object to be detected, and once it was inside the checking limits, I was able to acknowledge its presence.
public class PointInsideBound : MonoBehaviour
{
public Collider BoundCollider;
private Transform pointToCheck;
private void OnTriggerEnter(Collider other)
{
if (pointToCheck == null)
{
//There is a point on top of the collided object. Getting the reference here.
pointToCheck = other.transform.GetChild(0);
}
}
private void OnTriggerStay(Collider other)
{
if (pointToCheck == null)
{
return;
}
if (BoundCollider.bounds.Contains(pointToCheck.position))
{
Debug.Log(" Point Inside the boxcollider");
BoundCollider.enabled = false;
}
}
}
You should use a collider. This is description. http://docs.unity3d.com/Documentation/ScriptReference/Collider.html