Object change direction after collide with controller - c#

In Unity3D I have got a gameobject that is attached with a box collider and physic material. The hand controller model is also attached to a box collider and physic material. When the gameobject collides with the hand controller, the CollideWithController logs on the console. However, the gameobject does not change direction.
if (other.CompareTag("HandController"))
{
Debug.Log("CollideWithController");
var magnitude = 1000;
var force = transform.position - other.transform.position;
force.Normalize();
gameObject.GetComponent<Rigidbody>().AddForce(force * magnitude);
}

Without seeing/knowing what other is, its hard to say, but generally there could be two problems:
transform.position-other.transform.position doesn't actually result in the direction you expect. To determine this, print the value or display it using Debug.DrawRay.
The force you're adding might not be enough to change direction, or there are other forces canceling it out.

var force = transform.position - other.transform.position;
You will get a direction vector to get other to the position of this. So you are moving into the collision, reversing the vector should fix your issue.

When you modify physics value like here with AddForce, you should do it in the FixedUpdate to minimize the risk of bug. (It can work outside of the FixedUpdate, but in most case it will create unwanted behavior).
In your code you use AddFroce, but if the actual force of the gameObject is greater than this the force you add will just slow the actual movement of the gameobject and not reverse it.
I think the best way to change the movement of your gameObject is to use the velocity vector and to reflect it.
One more advice : Don't use physics for gameplay system. Physics is something very powerfull, it can bring a lot of emergent behavior, but it's a chaotic system. And when it's about gameplay you don't want chaos you want control and consistency.
Unity doc :
Velocity : https://docs.unity3d.com/ScriptReference/Rigidbody-velocity.html
Reflect : https://docs.unity3d.com/ScriptReference/Vector3.Reflect.html

Related

AddForce to local transform

I'm currently trying to make a game to put my relatively new coding knowledge to test. I figured I learn a lot quicker by just doing things and seeing what happens. I'm currently working on a plane and the last couple of days I made a functional camera system (to rotate around the player based on the mouse) and some animations of the plane. I'm currently trying to create a movement system in which the down key rotates the player up. I noticed however that my AddForce function doesn't do what I want it to do. I'd like the plane to move in the Z axis depending on the current rotation of said plane instead of it just heading into the Z angle of the world.
I'm currently working on this snippet:
//Acceleration
if (gameObject.CompareTag("Player") && playerRb.velocity.z > -349)
{
playerRb.AddRelativeForce(0, 0, -playerSpeed, ForceMode.Acceleration);
}
else if (gameObject.CompareTag("Player") && playerRb.velocity.z < -349)
{
playerRb.velocity = new Vector3(playerRb.velocity.x, playerRb.velocity.y, -350);
}
//
//Movement
//Up/down controls
if (gameObject.CompareTag("Player") && Input.GetKey(KeyCode.DownArrow))
{
transform.Rotate((0.07f * playerSpeed) * Time.deltaTime, 0, 0);
}
As you can see I already tried AddRelativeForce as another topic mentioned but that doesn't seem to work for me. The moment it hits an edge it just falls down into the abyss regardless of it's rotation.
Additionally, I was considering using another AddForce function on the rotate as it doesn't leave the ground (considering it keeps hitting the floor with its tail), is there any way to apply a force on an object from a specific position/angle? (such as the front of the plane).
Thanks in advance!
I think the reason your plane is acting strange is not because of your addrelative force call -- it's because you are setting velocity. playerRb.velocity = new Vector3(playerRb.velocity.x, playerRb.velocity.y, -350); assigns the velocity to push you -350 in the world's z axis, which probably isn't what you want. Velocity is in the global space. Remove that and see what happens.
On a more general note, If you're using physics, try to use only forces and torquees. Using transform.Rotate to change a rigidbody's rotation while physics is active will just make your life difficult, and make the rigidbody do strange things. I do change the velocity of rigidbodies sometimes, but not in every frame. I just don't know enough about physics to mess with velocities that way.
Also, make sure you're doing these things in a FixedUpdate function, since that is where input that affects physics is supposed to be checked.

How would one add force to a rigidbody from a relative mouse position?

I have a game I am creating in Unity. It has a table with 30 cubes on it. I want a user to be able to shuffle the cubes on the table using their mouse/touch.
I am currently using a ray to get the initial table/cube hit point then accessing the rigidbody component on the cube to apply a force using AddForceAtPosition, happening in an OnMouseDrag. I am also pulling out my hair trying to figure out how to apply force in the direction from the mouse's last position to the hit point on the rigidbody of the cube.
Can someone please help me? An example would be great. I would share my code but I am a spaghetti code monster and fear criticism... Thanks much!
If I understood correctly, is something like this you want to achieve? https://www.youtube.com/watch?v=5Zli2CJGAtU&feature=youtu.be
If so, first you have to add your cubes and table to a new layermask, this step is only necessary if you don't want your ray to hit other colliders that might mess with your result.
After this you should add a tag to all the cubes you want to aplly the force, in my case I added a new tag called "Cubes".
You can search on youtube this if you don't know how to do it, there are plenty of tutorials to help you.
After that you create a new script and attach to the camera. Here is my script:
public class CameraForceMouse : MonoBehaviour
{
public LayerMask layerMask;
RaycastHit hit;
Vector3 lastPosition;
// Start is called before the first frame update
void Start()
{
lastPosition = new Vector3();
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0))
{
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 200f, layerMask))
{
if (hit.transform.CompareTag("Cubes"))
{
Rigidbody rb = hit.transform.GetComponent<Rigidbody>();
Vector3 force = (hit.point - lastPosition).normalized * 55f;
rb.AddForceAtPosition(force, hit.point);
}
lastPosition = hit.point;
}
}
}
}
Just want to say that there are a lot of ways to achieve the same thing, this is the way I decided to do, but there are probably other (maybe even better) ways of doing this.
Explaining the code:
The first thing is a public LayerMask that before you play the game you will have to select your camera in your scene and look for the script on the editor in the right side and select witch layerMask you added to your cubes and table.
If you don't know how raycast works, here is the documentation: https://docs.unity3d.com/ScriptReference/Physics.Raycast.html but you can also search on youtube.
The important thing here is the new vector being created to define the direction of the force.
First we declare a global variable called LastPosition, and for every frame that we are clicking, we will check for a collision, and if this collision happens, we will then create a new vector going out of the last position the mouse was to the position the mouse is now Vector3 force = (hit.point - lastPosition), than we normalize it because we only care about the direction and multiply it by the amount of force we want, you can make it as a nice variable but I just put it there directly.
Then, after you've applied the force to the position the ray hit the object, you have to define that this is now your last position, since you are going to the next frame. Remember to put it outside of the Tag check, because this is checking if the object we collided with is the cube we want to apply the force or if it is the table. If we add this line lastPosition = hit.point; inside of this check it will only assign a new lastPosition value when we hit the cube, and would lead to bugs.
I'm not saying my answer is perfect, I can think of a few bugs that can happen, when you click outside the table for example, but is a good start, and I think you can fix the rest.

Unity Object moves when AddForceAtPosition is applied when it should only rotate

I have a game object in unity I'd like to thrust vector around with some forces. At the moment I'm trying to add some realistic rotation forces hence using AddForceAtPosition using an offset from the rigidbody center of mass. Yet when i run the game, the object starts moving slightly in addition to the rotation. No other forces are present and there is no drag.
rb.AddForceAtPosition(transform.TransformDirection(Vector3.up * 5), transform.position + transform.TransformDirection(mainThrustPt));
The Rigidbody.AddForceAtPosition function apply both torque and force on the object. this means that the Object will be rotated and moved at the-same time.
If you just want to apply a rotational force that doesn't move the Object, use the Rigidbody.AddTorque or Rigidbody.AddRelativeTorque which will only apply a rotational force to the Object.
You can also free the Rigidbody x,y,z position if you don't want it to move but the movement behavior of the object will be weird sometimes when this is done.
Yet when i run the game, the object starts moving slightly in addition
to the rotation.
If the Object is moving without adding force to it or without using AddForceAtPosition, then gravity is pulling it. Disable "Use Gravity" as I did in the image above.
Use AddTorque if you need rotation.
If you pushed the edge of a ball tied up with string, you would expect it to swing as well as spin. Try using this before applying the force:
rigidbody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ;

Unity 2D mobile Game: How to make the world gravity follow device tilt

I know it could be a basic question for Unity developers. But I am struggling to find answers for this problem. I want to move all objects in my game screen based on device acceleration. I only think of 2 possibles solutions:
1st: change the whole world gravity based on device tilt
2nd: apply the forces to all objects or change the velocity of all objects (I tried changing the velocity but the game got lagging)
Is there any good way to make 2D game objects smoothly move based on device tilt?
You can do this by modifying Physics2D.gravity. It will change the gravity of all GameObjects in the scene.
Physics2D.gravity = Input.acceleration * 50; would have worked but because Input.acceleration has low, mid and high values, it wont work. So you can't assign Input.acceleration directly to Physics2D.gravity.
You need to turn on you device then use Debug.Log(Input.acceleration) to view the low, middle and high values of each axis then you can use if statement and temporary Vector2 value to get what 2D value to assign to Physics2D.gravity.
Also for any GameObject you want the accelerometer to affect more, less or not at-all, you can modify the RigidBody Gravityscale of that GameObject.
The gravity applied to all rigid bodies in the scene can be changed by setting Physics2D.gravity.
Note: Make sure you also set rigidbody.useGravity = true (for gravity to affect the objects).
Example:
Physics2D.gravity = new Vector2(x, y);
Physics.gravity Unity API
Input-acceleration Unity API
Place this in the update() block of any element.
Physics2D.gravity is a "global" value that takes a Vector2 for value.
Debug.Log(Input.acceleration);
Physics2D.gravity = new Vector2(Input.acceleration.x*1.5f, Input.acceleration.y*1.5f);
(You may edit/remove the multiplying floats in each input acceleration property, I added them just for some exponential gravity speed.)
Note:
This will impact all the rigidbodies.

Unity3d flappy bird tutorial - space button not working

I am a total beginner at Unity3d. I have some background in android programming, but no C# experience whatsoever. The first thing I am trying to do is to create a clone of flappy bird game, called flappy plane, according to this tutorial
http://anwell.me/articles/unity3d-flappy-bird/
The problem is, when I tried to write a script that allows player to move (player.cs) with the code
using UnityEngine;
using System.Collections;
public class player: MonoBehaviour {
public Vector2 jumpForce = new Vector2(0,300);
public Vector2 jumpForce2 = new Vector2(0,-300);
// Use this for initialization
// Update is called once per frame
void Update () {
if (Input.GetKeyUp("space")){
Rigidbody2D.velocity = Vector2.zero;
Rigidbody2D.AddForce(jumpForce);
}
}
}
I get an error "An Object reference is required to access non-static member 'UnityEngine.Rigidbody2D.velocity'". I have googled that and it is suggested to access Rigidbody2d with GetComponent().velocity,
so I changed
Rigidbody2D.velocity = Vector2.zero;
Rigidbody2D.AddForce(jumpForce);
with
GetComponent<Rigidbody2D>().velocity = Vector2.zero;
GetComponent<Rigidbody2D>().AddForce(jumpForce);
The error is gone and I am able to add the script to the object, still I don`t get the desired action - after I hit play the object turns invisible and just falls down, does not react to spacebar button. What am I doing wrong?
Thanks for the answer.
It's possible that you're not adding enough force to have the object move upwards.
There's technically nothing wrong with your code. (Although you do have somethings mixed up in your question). The problem is in the fact that you're not adding ANY force upwards every single frame.
Essentially, at the moment, your player object is in free-fall the instant you hit the play button, and you're adding a minuscule force to the player only on the frames that the space bar is pressed.
To solve this, here's what you should be doing
Add an upward force to counter-act the force of gravity every frame. You can do this in two ways.
a. Set the rigidbody's velocity.y to 0 BEFORE detecting the space bar (this is really a hacky way, but it'll suffice and doesn't need any more code)
b. Add an upward force to the player which will nullify the effect of gravity. Just use F = mg to get the value of force you'd need to add.
You could, alternatively set the isKinematic property to true by default on the Player's rigidbody, set it to false on pressing the space bar, and back to true after a few frames (5 - 6 frames)
make sure your player object and the ground both have BoxCollider2D colliders to keep above ground.
you could keep a reference stored for the rigidBody like Rigidbody2D myRigidbody;
then in start put myRigidbody = GetComponent<Rigidbody2D>(); then you would use like myRigidbody.AddForce(jumpForce); your jumpForce2 though is shooting your player downward you should not need it in a jump as the physics and gravity will apply with the rigidbody.
incase your input is not set up in the project settings try to fire the jump with
Input.GetKeyDown(KeyCode.Space);

Categories